From a658f81bdd9ec5962f5a342cb5618aab3afe6edc Mon Sep 17 00:00:00 2001 From: Ben Hale Date: Mon, 18 Dec 2006 22:03:24 +0000 Subject: [PATCH] --- build-spring-ldap/.project | 11 + build-spring-ldap/build.xml | 233 ++ build-spring-ldap/checklist_release.txt | 64 + build-spring-ldap/jdiff/lib/2000/10/XMLSchema | 2201 +++++++++++++++ .../jdiff/lib/2000/10/XMLSchema-instance | 31 + build-spring-ldap/jdiff/lib/2001/XMLSchema | 2441 +++++++++++++++++ .../jdiff/lib/2001/XMLSchema-instance | 38 + build-spring-ldap/jdiff/lib/Null.java | 9 + build-spring-ldap/jdiff/lib/ant.jar | Bin 0 -> 417110 bytes build-spring-ldap/jdiff/lib/antjdiff.jar | Bin 0 -> 5885 bytes build-spring-ldap/jdiff/lib/background.gif | Bin 0 -> 559 bytes build-spring-ldap/jdiff/lib/black.gif | Bin 0 -> 799 bytes build-spring-ldap/jdiff/lib/classdoc.jar | Bin 0 -> 42559 bytes build-spring-ldap/jdiff/lib/jdiff.jar | Bin 0 -> 129537 bytes build-spring-ldap/jdiff/lib/jdiff_logo.gif | Bin 0 -> 1867 bytes build-spring-ldap/jdiff/lib/new.gif | Bin 0 -> 116 bytes build-spring-ldap/jdiff/lib/xerces.jar | Bin 0 -> 1802885 bytes build-spring-ldap/project.properties | 5 + build-spring-ldap/readme.txt | 16 + build-spring-ldap/release-toc.txt | 11 + ...AttributesIntegrityViolationException.java | 40 + .../ldap/AttributesMapper.java | 53 + .../ldap/AuthenticationSource.java | 40 + .../ldap/BadLdapGrammarException.java | 39 + ...ollectingNameClassPairCallbackHandler.java | 63 + .../ldap/ContextAssembler.java | 36 + .../springframework/ldap/ContextExecutor.java | 50 + .../springframework/ldap/ContextMapper.java | 61 + .../springframework/ldap/ContextSource.java | 51 + .../ldap/DefaultNameClassPairMapper.java | 46 + .../DefaultNamingExceptionTranslator.java | 96 + .../ldap/DirContextProcessor.java | 49 + .../ldap/EntryNotFoundException.java | 37 + .../springframework/ldap/LdapOperations.java | 1350 +++++++++ .../springframework/ldap/LdapTemplate.java | 1379 ++++++++++ .../ldap/NameClassPairCallbackHandler.java | 39 + .../ldap/NameClassPairMapper.java | 42 + .../ldap/NamingExceptionTranslator.java | 39 + .../springframework/ldap/SearchExecutor.java | 51 + .../ldap/SearchLimitExceededException.java | 37 + .../ldap/UncategorizedLdapException.java | 35 + .../org/springframework/ldap/package.html | 3 + .../ldap/support/AbstractContextSource.java | 459 ++++ .../support/AggregateDirContextProcessor.java | 72 + .../support/AttributeModificationsAware.java | 36 + .../CountNameClassPairCallbackHandler.java | 51 + .../ldap/support/DefaultDirObjectFactory.java | 93 + .../ldap/support/DefaultDnParserFactory.java | 38 + .../ldap/support/DirContextAdapter.java | 1271 +++++++++ .../ldap/support/DirContextOperations.java | 161 ++ .../ldap/support/DirContextSource.java | 47 + .../ldap/support/DistinguishedName.java | 629 +++++ .../ldap/support/DnParser.java | 39 + .../ldap/support/LdapContextSource.java | 92 + .../ldap/support/LdapEncoder.java | 235 ++ .../springframework/ldap/support/LdapRdn.java | 198 ++ .../ldap/support/LdapRdnComponent.java | 163 ++ .../AcegiAuthenticationSource.java | 81 + ...ltValuesAuthenticationSourceDecorator.java | 157 ++ .../ldap/support/authentication/package.html | 3 + ...ractRequestControlDirContextProcessor.java | 90 + .../support/control/PagedResultsCookie.java | 50 + .../control/PagedResultsRequestControl.java | 200 ++ .../ldap/support/control/package.html | 3 + .../ldap/support/filter/AbstractFilter.java | 58 + .../ldap/support/filter/AndFilter.java | 59 + .../support/filter/BinaryLogicalFilter.java | 95 + .../ldap/support/filter/CompareFilter.java | 123 + .../ldap/support/filter/EqualsFilter.java | 57 + .../ldap/support/filter/Filter.java | 58 + .../filter/GreaterThanOrEqualsFilter.java | 52 + .../filter/LessThanOrEqualsFilter.java | 51 + .../ldap/support/filter/LikeFilter.java | 78 + .../ldap/support/filter/NotFilter.java | 89 + .../ldap/support/filter/OrFilter.java | 59 + .../filter/WhitespaceWildcardsFilter.java | 84 + .../ldap/support/filter/package.html | 16 + .../springframework/ldap/support/package.html | 3 + .../ldap/util/ListComparator.java | 67 + .../springframework/ldap/util/package.html | 3 + .../src/main/java/overview.html | 3 + ...AttributesIntegrityViolationException.java | 40 + .../ldap/AttributesMapper.java | 53 + .../ldap/AuthenticationSource.java | 40 + .../ldap/BadLdapGrammarException.java | 39 + ...ollectingNameClassPairCallbackHandler.java | 63 + .../ldap/ContextAssembler.java | 36 + .../springframework/ldap/ContextExecutor.java | 50 + .../springframework/ldap/ContextMapper.java | 61 + .../springframework/ldap/ContextSource.java | 51 + .../ldap/DefaultNameClassPairMapper.java | 46 + .../DefaultNamingExceptionTranslator.java | 96 + .../ldap/EntryNotFoundException.java | 37 + .../springframework/ldap/LdapOperations.java | 1104 ++++++++ .../springframework/ldap/LdapTemplate.java | 1176 ++++++++ .../ldap/NameClassPairCallbackHandler.java | 39 + .../ldap/NameClassPairMapper.java | 42 + .../ldap/NamingExceptionTranslator.java | 39 + .../springframework/ldap/SearchExecutor.java | 51 + .../ldap/SearchLimitExceededException.java | 37 + .../ldap/UncategorizedLdapException.java | 35 + .../org/springframework/ldap/package.html | 3 + .../ldap/support/AbstractContextSource.java | 455 +++ .../support/AttributeModificationsAware.java | 36 + .../CountNameClassPairCallbackHandler.java | 51 + .../ldap/support/DefaultDirObjectFactory.java | 115 + .../ldap/support/DirContextAdapter.java | 1186 ++++++++ .../ldap/support/DirContextOperations.java | 161 ++ .../ldap/support/DirContextSource.java | 47 + .../ldap/support/DistinguishedName.java | 570 ++++ .../ldap/support/LdapContextSource.java | 48 + .../ldap/support/LdapEncoder.java | 235 ++ .../springframework/ldap/support/LdapRdn.java | 217 ++ .../AcegiAuthenticationSource.java | 81 + ...ltValuesAuthenticationSourceDecorator.java | 157 ++ .../ldap/support/authentication/package.html | 3 + .../ldap/support/filter/AbstractFilter.java | 58 + .../ldap/support/filter/AndFilter.java | 59 + .../support/filter/BinaryLogicalFilter.java | 95 + .../ldap/support/filter/CompareFilter.java | 123 + .../ldap/support/filter/EqualsFilter.java | 57 + .../ldap/support/filter/Filter.java | 58 + .../filter/GreaterThanOrEqualsFilter.java | 52 + .../filter/LessThanOrEqualsFilter.java | 51 + .../ldap/support/filter/LikeFilter.java | 78 + .../ldap/support/filter/NotFilter.java | 89 + .../ldap/support/filter/OrFilter.java | 59 + .../filter/WhitespaceWildcardsFilter.java | 84 + .../ldap/support/filter/package.html | 16 + .../springframework/ldap/support/package.html | 3 + common-build/.cvsignore | 11 + common-build/.project | 11 + common-build/clover-targets.xml | 82 + common-build/common-targets.xml | 928 +++++++ common-build/db-targets.xml | 140 + common-build/doc-targets.xml | 157 ++ common-build/ejb21-targets.xml | 65 + common-build/hibernate-targets.xml | 127 + common-build/ivyconf.properties | 2 + common-build/ivyconf.xml | 89 + common-build/lib/ivy-1.4.1.jar | Bin 0 -> 571869 bytes common-build/project.properties | 135 + common-build/readme.txt | 37 + common-build/spring-targets.xml | 49 + common-build/templates/db/data.xml | 5 + common-build/templates/jsp/includeBottom.jsp | 5 + common-build/templates/jsp/includeTop.jsp | 22 + common-build/templates/jsp/pageshell.jsp | 7 + common-build/templates/log4j/log4j.properties | 19 + .../templates/projects/standard/.classpath | 13 + .../templates/projects/standard/.cvsignore | 8 + .../templates/projects/standard/.project | 17 + .../templates/projects/standard/build.xml | 19 + .../templates/projects/standard/ivy.xml | 35 + .../projects/standard/project.properties | 5 + .../standard/src/etc/filter.properties | 33 + .../src/etc/test-resources/log4j.properties | 16 + .../src/etc/test-resources/readme.txt | 5 + .../standard/src/main/java/readme.txt | 5 + .../standard/src/main/resources/readme.txt | 5 + .../standard/src/test/java/readme.txt | 5 + .../webapp/WEB-INF/classes/log4j.properties | 19 + .../WEB-INF/dispatcher-servlet-config.xml | 8 + .../templates/projects/webapp/WEB-INF/web.xml | 41 + .../templates/projects/webapp/index.html | 10 + common-build/templates/readme.txt | 2 + .../FlowExecutionTestTemplate.java | 24 + .../flow-definition-1.0-form.xml | 22 + .../flow-definition-1.0-simplest.xml | 15 + .../spring-webflow/flow-definition-1.0.xml | 12 + .../webflow-config-1.0-spring-1.2.xml | 33 + .../spring-webflow/webflow-config-1.0.xml | 35 + .../templates/spring-webflow/webflow-form.jsp | 18 + .../templates/spring/bean-definitions-1.2.xml | 9 + .../templates/spring/bean-definitions-2.0.xml | 10 + common-build/templates/tomcat/context.xml | 4 + common-build/tomcat-targets.xml | 139 + common-build/version.txt | 13 + pom.xml | 277 ++ sandbox/.classpath | 48 + sandbox/.project | 34 + sandbox/.settings/org.eclipse.jdt.core.prefs | 248 ++ sandbox/.settings/org.eclipse.jdt.ui.prefs | 3 + sandbox/.springBeans | 25 + sandbox/build.xml | 84 + sandbox/itest-openldap-targets.xml | 234 ++ sandbox/itest-targets.xml | 230 ++ sandbox/ivy.xml | 101 + sandbox/project.properties | 14 + sandbox/project.xml | 237 ++ sandbox/readme.txt | 2 + .../java/conf/ldap-openldap.properties | 4 + .../src/itest-openldap/java/conf/ldap.conf | 23 + .../conf/ldapTemplateTestContext-openldap.xml | 22 + ...dapTemplateVirtualListViewSearchITest.java | 140 + .../src/itest/java/conf/apacheDsContext.xml | 82 + sandbox/src/itest/java/conf/ldap.properties | 4 + .../conf/ldapTemplateAcegiTestContext.xml | 66 + .../ldapTemplateBaseSuffixTestContext.xml | 25 + .../java/conf/ldapTemplateTestContext.xml | 24 + sandbox/src/itest/java/log4j.properties | 9 + sandbox/src/itest/java/setup_data.ldif | 71 + .../ContextSourceTransactionManager.java | 88 + .../ldap/support/DirContextHolder.java | 21 + .../ldap/support/DirContextProxy.java | 7 + .../ldap/support/TlsContextSource.java | 174 ++ .../TransactionAwareContextSourceProxy.java | 102 + .../VirtualListViewRequestControl.java | 219 ++ .../control/VirtualListViewResultsCookie.java | 49 + .../ContextSourceTransactionManagerTest.java | 127 + spring-ldap-article/.classpath | 22 + spring-ldap-article/.project | 23 + .../.settings/org.eclipse.jdt.core.prefs | 260 ++ .../.settings/org.eclipse.jdt.ui.prefs | 4 + spring-ldap-article/.springBeans | 16 + spring-ldap-article/build.xml | 18 + spring-ldap-article/docs/base_data.ldif | 9 + spring-ldap-article/docs/ldap.conf.example | 21 + spring-ldap-article/docs/readme.txt | 52 + spring-ldap-article/docs/setup_data.ldif | 70 + spring-ldap-article/docs/teardown_data.ldif | 3 + spring-ldap-article/ivy.xml | 31 + spring-ldap-article/pom.xml | 84 + spring-ldap-article/project.properties | 10 + spring-ldap-article/readme.txt | 1 + .../src/itest/java/config/ldap.properties | 4 + .../src/itest/java/config/testContext.xml | 34 + .../dao/AbstractPersonDaoIntegrationTest.java | 121 + .../dao/PersonDaoImplIntegrationTest.java | 33 + ...aditionalPersonDaoImplIntegrationTest.java | 33 + .../src/main/java/log4j.properties | 19 + .../ldap/samples/article/dao/PersonDao.java | 42 + .../samples/article/dao/PersonDaoImpl.java | 198 ++ .../article/dao/TraditionalPersonDaoImpl.java | 385 +++ .../ldap/samples/article/domain/Person.java | 104 + .../src/main/java/overview.html | 3 + spring-ldap-article/src/test/java/.dummy | 0 spring-ldap-person/.classpath | 49 + spring-ldap-person/.project | 23 + .../.settings/org.eclipse.jdt.core.prefs | 260 ++ .../.settings/org.eclipse.jdt.ui.prefs | 4 + spring-ldap-person/.springBeans | 35 + spring-ldap-person/build.xml | 22 + spring-ldap-person/deps.txt | 677 +++++ spring-ldap-person/docs/base_data.ldif | 9 + spring-ldap-person/docs/ldap.conf.example | 25 + spring-ldap-person/docs/readme.txt | 57 + spring-ldap-person/docs/setup_data.ldif | 90 + spring-ldap-person/docs/teardown_data.ldif | 3 + spring-ldap-person/ivy.xml | 94 + spring-ldap-person/pom.xml | 151 + spring-ldap-person/project.properties | 10 + spring-ldap-person/readme.txt | 3 + spring-ldap-person/src/itest/java/.dummy | 0 .../src/main/java/log4j.properties | 19 + .../springframework/ldap/ConfigEnvHelper.java | 58 + .../ldap/LdapServerManager.java | 132 + .../samples/person/dao/DummyGroupDao.java | 67 + .../samples/person/dao/DummyPersonDao.java | 83 + .../person/dao/GroupContextMapper.java | 48 + .../ldap/samples/person/dao/GroupDao.java | 40 + .../ldap/samples/person/dao/GroupDaoImpl.java | 130 + .../person/dao/PersonContextMapper.java | 68 + .../ldap/samples/person/dao/PersonDao.java | 42 + .../samples/person/dao/PersonDaoImpl.java | 120 + .../person/dao/TraditionalPersonDaoImpl.java | 228 ++ .../ldap/samples/person/domain/Group.java | 63 + .../samples/person/domain/GroupValidator.java | 39 + .../ldap/samples/person/domain/Person.java | 121 + .../person/domain/PersonValidator.java | 43 + .../samples/person/domain/SearchCriteria.java | 51 + .../domain/SearchCriteriaValidator.java | 50 + .../samples/person/service/GroupService.java | 42 + .../person/service/GroupServiceImpl.java | 85 + .../samples/person/service/PersonService.java | 43 + .../person/service/PersonServiceImpl.java | 88 + .../person/web/EditGroupFormAction.java | 103 + .../person/web/EditPersonFormAction.java | 44 + .../src/main/java/overview.html | 3 + .../src/main/java/setup_data.ldif | 111 + .../main/webapp/WEB-INF/apacheDsContext.xml | 79 + .../applicationContext-acegi-security.xml | 135 + .../webapp/WEB-INF/applicationContext.xml | 88 + .../webapp/WEB-INF/classes/log4j.properties | 21 + .../WEB-INF/flows/detail-flow-beans.xml | 14 + .../main/webapp/WEB-INF/flows/detail-flow.xml | 66 + .../WEB-INF/flows/detail-group-flow-beans.xml | 18 + .../WEB-INF/flows/detail-group-flow.xml | 74 + .../WEB-INF/flows/personmanager-flow.xml | 64 + .../WEB-INF/flows/search-flow-beans.xml | 14 + .../main/webapp/WEB-INF/flows/search-flow.xml | 39 + .../WEB-INF/flows/search-group-flow-beans.xml | 14 + .../WEB-INF/flows/search-group-flow.xml | 39 + .../main/webapp/WEB-INF/jsp/editDetails.jsp | 53 + .../webapp/WEB-INF/jsp/editGroupDetails.jsp | 65 + .../src/main/webapp/WEB-INF/jsp/error.jsp | 18 + .../main/webapp/WEB-INF/jsp/includeBottom.jsp | 5 + .../main/webapp/WEB-INF/jsp/includeTop.jsp | 21 + .../src/main/webapp/WEB-INF/jsp/menu.jsp | 23 + .../main/webapp/WEB-INF/jsp/searchForm.jsp | 46 + .../webapp/WEB-INF/jsp/searchGroupForm.jsp | 46 + .../webapp/WEB-INF/jsp/searchGroupResult.jsp | 52 + .../main/webapp/WEB-INF/jsp/searchResult.jsp | 60 + .../webapp/WEB-INF/jsp/showAddCandidates.jsp | 58 + .../main/webapp/WEB-INF/jsp/showDetails.jsp | 50 + .../webapp/WEB-INF/jsp/showGroupDetails.jsp | 40 + .../src/main/webapp/WEB-INF/ldap.properties | 4 + .../webapp/WEB-INF/ldaptemplate-servlet.xml | 26 + .../WEB-INF/ldaptemplate-webflow-config.xml | 19 + .../src/main/webapp/WEB-INF/web.xml | 50 + .../src/main/webapp/acegilogin.jsp | 52 + .../src/main/webapp/images/spring-logo.jpg | Bin 0 -> 31339 bytes .../src/main/webapp/images/webflow-logo.jpg | Bin 0 -> 2383 bytes spring-ldap-person/src/main/webapp/index.jsp | 21 + spring-ldap-person/src/main/webapp/logoff.jsp | 4 + spring-ldap-person/src/main/webapp/style.css | 58 + .../samples/person/dao/GroupDaoImplTest.java | 216 ++ .../samples/person/dao/PersonDaoImplTest.java | 221 ++ .../ldap/samples/person/domain/GroupTest.java | 51 + .../samples/person/domain/PersonTest.java | 25 + .../person/domain/SearchCriteriaTest.java | 21 + .../person/service/PersonServiceImplTest.java | 162 ++ .../person/web/DetailFlowExecutionTest.java | 152 + .../web/PersonManagerFlowExecutionTest.java | 180 ++ .../person/web/SearchFlowExecutionTest.java | 79 + spring-ldap-person/trifork.map | 7 + spring-ldap/.checkstyle | 4 + spring-ldap/.classpath | 50 + spring-ldap/.project | 34 + .../.settings/org.eclipse.jdt.core.prefs | 248 ++ .../.settings/org.eclipse.jdt.ui.prefs | 3 + spring-ldap/.springBeans | 25 + spring-ldap/build.xml | 219 ++ spring-ldap/changelog.txt | 212 ++ spring-ldap/docs/quickstart/quickstart.pdf | Bin 0 -> 54787 bytes .../docs/reference/images/admons/blank.png | Bin 0 -> 374 bytes .../docs/reference/images/admons/caution.gif | Bin 0 -> 743 bytes .../docs/reference/images/admons/caution.png | Bin 0 -> 1250 bytes .../docs/reference/images/admons/caution.tif | Bin 0 -> 1978 bytes .../docs/reference/images/admons/draft.png | Bin 0 -> 17454 bytes .../docs/reference/images/admons/home.gif | Bin 0 -> 321 bytes .../docs/reference/images/admons/home.png | Bin 0 -> 1156 bytes .../reference/images/admons/important.gif | Bin 0 -> 1003 bytes .../reference/images/admons/important.png | Bin 0 -> 722 bytes .../reference/images/admons/important.tif | Bin 0 -> 2020 bytes .../docs/reference/images/admons/next.gif | Bin 0 -> 1083 bytes .../docs/reference/images/admons/next.png | Bin 0 -> 1150 bytes .../docs/reference/images/admons/note.gif | Bin 0 -> 580 bytes .../docs/reference/images/admons/note.png | Bin 0 -> 490 bytes .../docs/reference/images/admons/note.tif | Bin 0 -> 460 bytes .../docs/reference/images/admons/prev.gif | Bin 0 -> 1118 bytes .../docs/reference/images/admons/prev.png | Bin 0 -> 1132 bytes .../docs/reference/images/admons/tip.gif | Bin 0 -> 598 bytes .../docs/reference/images/admons/tip.png | Bin 0 -> 449 bytes .../docs/reference/images/admons/tip.tif | Bin 0 -> 420 bytes .../reference/images/admons/toc-blank.png | Bin 0 -> 318 bytes .../reference/images/admons/toc-minus.png | Bin 0 -> 259 bytes .../docs/reference/images/admons/toc-plus.png | Bin 0 -> 264 bytes .../docs/reference/images/admons/up.gif | Bin 0 -> 1089 bytes .../docs/reference/images/admons/up.png | Bin 0 -> 1111 bytes .../docs/reference/images/admons/warning.gif | Bin 0 -> 743 bytes .../docs/reference/images/admons/warning.png | Bin 0 -> 1241 bytes .../docs/reference/images/admons/warning.tif | Bin 0 -> 1990 bytes .../docs/reference/images/callouts/1.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/1.png | Bin 0 -> 329 bytes .../docs/reference/images/callouts/10.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/10.png | Bin 0 -> 361 bytes .../docs/reference/images/callouts/11.gif | Bin 0 -> 244 bytes .../docs/reference/images/callouts/11.png | Bin 0 -> 565 bytes .../docs/reference/images/callouts/12.gif | Bin 0 -> 244 bytes .../docs/reference/images/callouts/12.png | Bin 0 -> 617 bytes .../docs/reference/images/callouts/13.gif | Bin 0 -> 244 bytes .../docs/reference/images/callouts/13.png | Bin 0 -> 623 bytes .../docs/reference/images/callouts/14.gif | Bin 0 -> 244 bytes .../docs/reference/images/callouts/14.png | Bin 0 -> 411 bytes .../docs/reference/images/callouts/15.gif | Bin 0 -> 244 bytes .../docs/reference/images/callouts/15.png | Bin 0 -> 640 bytes .../docs/reference/images/callouts/2.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/2.png | Bin 0 -> 353 bytes .../docs/reference/images/callouts/3.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/3.png | Bin 0 -> 350 bytes .../docs/reference/images/callouts/4.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/4.png | Bin 0 -> 345 bytes .../docs/reference/images/callouts/5.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/5.png | Bin 0 -> 348 bytes .../docs/reference/images/callouts/6.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/6.png | Bin 0 -> 355 bytes .../docs/reference/images/callouts/7.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/7.png | Bin 0 -> 344 bytes .../docs/reference/images/callouts/8.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/8.png | Bin 0 -> 357 bytes .../docs/reference/images/callouts/9.gif | Bin 0 -> 968 bytes .../docs/reference/images/callouts/9.png | Bin 0 -> 357 bytes spring-ldap/docs/reference/readme.txt | 20 + spring-ldap/docs/reference/src/basic.xml | 385 +++ .../docs/reference/src/configuration.xml | 195 ++ .../docs/reference/src/contextprocessor.xml | 226 ++ .../docs/reference/src/dirobjectfactory.xml | 286 ++ spring-ldap/docs/reference/src/executors.xml | 133 + .../docs/reference/src/images/banner4.jpg | Bin 0 -> 83374 bytes .../docs/reference/src/images/bannerR.gif | Bin 0 -> 7949 bytes .../docs/reference/src/images/logo.png | Bin 0 -> 23834 bytes spring-ldap/docs/reference/src/index.xml | 52 + spring-ldap/docs/reference/src/overview.xml | 325 +++ spring-ldap/docs/reference/src/preface.xml | 32 + spring-ldap/docs/reference/styles/fopdf.xsl | 475 ++++ spring-ldap/docs/reference/styles/html.css | 270 ++ spring-ldap/docs/reference/styles/html.xsl | 100 + .../docs/reference/styles/html_chunk.xsl | 103 + .../docs/reference/styles/tld.to.docbook.xsl | 197 ++ .../docs/reference/styles/xsd.to.docbook.xsl | 123 + spring-ldap/itest-openldap-targets.xml | 234 ++ spring-ldap/itest-targets.xml | 230 ++ spring-ldap/ivy.xml | 100 + spring-ldap/license.txt | 201 ++ spring-ldap/notice.txt | 16 + spring-ldap/pom.xml | 176 ++ spring-ldap/project.properties | 17 + spring-ldap/project.xml | 240 ++ spring-ldap/readme.txt | 82 + .../java/conf/ldap-openldap.properties | 4 + .../src/itest-openldap/java/conf/ldap.conf | 23 + .../conf/ldapTemplateTestContext-openldap.xml | 23 + .../ldap/LdapTemplateLookupOpenLdapITest.java | 217 ++ .../ldap/LdapTemplatePagedSearchITest.java | 153 ++ .../src/itest/java/conf/apacheDsContext.xml | 82 + .../src/itest/java/conf/ldap.properties | 4 + .../conf/ldapContextSourceTestContext.xml | 10 + .../conf/ldapTemplateAcegiTestContext.xml | 66 + .../ldapTemplateNoBaseSuffixTestContext.xml | 24 + .../java/conf/ldapTemplateTestContext.xml | 25 + spring-ldap/src/itest/java/log4j.properties | 9 + .../ldap/AttributeCheckAttributesMapper.java | 66 + .../ldap/AttributeCheckContextMapper.java | 65 + .../springframework/ldap/ConfigEnvHelper.java | 58 + .../ldap/LdapServerManager.java | 123 + .../LdapTemplateAttributesMapperITest.java | 54 + .../ldap/LdapTemplateBindUnbindITest.java | 122 + .../ldap/LdapTemplateContextExecutorTest.java | 60 + .../ldap/LdapTemplateContextMapperITest.java | 59 + .../ldap/LdapTemplateListITest.java | 150 + .../ldap/LdapTemplateLookupITest.java | 220 ++ .../ldap/LdapTemplateModifyITest.java | 251 ++ .../ldap/LdapTemplateNoBaseSuffixITest.java | 100 + .../LdapTemplateRecursiveDeleteITest.java | 125 + .../ldap/LdapTemplateRenameITest.java | 101 + .../ldap/LdapTemplateSearchCountITest.java | 94 + .../ldap/LdapTemplateSearchCountITest.xls | Bin 0 -> 17408 bytes .../ldap/LdapTemplateSearchResultITest.java | 178 ++ .../java/org/springframework/ldap/Person.java | 64 + .../ldap/PersonAttributesMapper.java | 47 + .../ldap/PersonContextMapper.java | 42 + .../ldap/support/DnParsePerformanceITest.java | 73 + .../ldap/support/LdapContextSourcelITest.java | 89 + .../LdapContextSourcelMultiServerITest.java | 46 + .../AcegiAuthenticationSourceITest.java | 81 + spring-ldap/src/itest/java/setup_data.ldif | 110 + spring-ldap/src/itest/java/teardown_data.ldif | 5 + ...AttributesIntegrityViolationException.java | 40 + .../ldap/AttributesMapper.java | 53 + .../ldap/AuthenticationSource.java | 40 + .../ldap/BadLdapGrammarException.java | 39 + ...ollectingNameClassPairCallbackHandler.java | 63 + .../ldap/ContextAssembler.java | 36 + .../springframework/ldap/ContextExecutor.java | 50 + .../springframework/ldap/ContextMapper.java | 61 + .../springframework/ldap/ContextSource.java | 51 + .../ldap/DefaultNameClassPairMapper.java | 46 + .../DefaultNamingExceptionTranslator.java | 96 + .../ldap/DirContextProcessor.java | 49 + .../ldap/EntryNotFoundException.java | 37 + .../springframework/ldap/LdapOperations.java | 1350 +++++++++ .../springframework/ldap/LdapTemplate.java | 1379 ++++++++++ .../ldap/NameClassPairCallbackHandler.java | 39 + .../ldap/NameClassPairMapper.java | 42 + .../ldap/NamingExceptionTranslator.java | 39 + .../springframework/ldap/SearchExecutor.java | 51 + .../ldap/SearchLimitExceededException.java | 37 + .../ldap/UncategorizedLdapException.java | 35 + .../org/springframework/ldap/package.html | 3 + .../ldap/support/AbstractContextSource.java | 459 ++++ .../support/AggregateDirContextProcessor.java | 72 + .../support/AttributeModificationsAware.java | 36 + .../CountNameClassPairCallbackHandler.java | 51 + .../ldap/support/DefaultDirObjectFactory.java | 92 + .../ldap/support/DefaultDnParserFactory.java | 38 + .../ldap/support/DirContextAdapter.java | 1271 +++++++++ .../ldap/support/DirContextOperations.java | 161 ++ .../ldap/support/DirContextSource.java | 47 + .../ldap/support/DistinguishedName.java | 647 +++++ .../ldap/support/DnParser.java | 39 + .../ldap/support/LdapContextSource.java | 92 + .../ldap/support/LdapEncoder.java | 235 ++ .../springframework/ldap/support/LdapRdn.java | 198 ++ .../ldap/support/LdapRdnComponent.java | 163 ++ .../AcegiAuthenticationSource.java | 81 + ...ltValuesAuthenticationSourceDecorator.java | 157 ++ .../ldap/support/authentication/package.html | 3 + ...ractRequestControlDirContextProcessor.java | 90 + .../ldap/support/control/PagedResult.java | 89 + .../support/control/PagedResultsCookie.java | 78 + .../control/PagedResultsRequestControl.java | 200 ++ .../ldap/support/control/package.html | 3 + .../ldap/support/filter/AbstractFilter.java | 58 + .../ldap/support/filter/AndFilter.java | 59 + .../support/filter/BinaryLogicalFilter.java | 95 + .../ldap/support/filter/CompareFilter.java | 123 + .../ldap/support/filter/EqualsFilter.java | 57 + .../ldap/support/filter/Filter.java | 58 + .../filter/GreaterThanOrEqualsFilter.java | 52 + .../filter/LessThanOrEqualsFilter.java | 51 + .../ldap/support/filter/LikeFilter.java | 78 + .../ldap/support/filter/NotFilter.java | 89 + .../ldap/support/filter/OrFilter.java | 59 + .../filter/WhitespaceWildcardsFilter.java | 84 + .../ldap/support/filter/package.html | 16 + .../springframework/ldap/support/package.html | 3 + .../ldap/util/ListComparator.java | 67 + .../springframework/ldap/util/package.html | 3 + spring-ldap/src/main/java/overview.html | 3 + spring-ldap/src/main/javacc/DnParserImpl.jj | 165 ++ ...ctingNameClassPairCallbackHandlerTest.java | 61 + .../ldap/LdapTemplateListTest.java | 439 +++ .../ldap/LdapTemplateLookupTest.java | 453 +++ .../ldap/LdapTemplateRenameTest.java | 198 ++ .../ldap/LdapTemplateTest.java | 1708 ++++++++++++ .../ldap/RequestControlMatcher.java | 72 + .../AggregateDirContextProcessorTest.java | 99 + ...ameClassPairResultCallbackHandlerTest.java | 51 + .../support/DefaultDirObjectFactoryTest.java | 157 ++ .../support/DirContextAdapterBugTest.java | 89 + .../ldap/support/DirContextAdapterTest.java | 664 +++++ .../ldap/support/DistinguishedNameTest.java | 448 +++ .../ldap/support/LdapContextSourceTest.java | 220 ++ .../ldap/support/LdapEncoderTest.java | 71 + .../ldap/support/LdapRdnComponentTest.java | 55 + .../ldap/support/LdapRdnTest.java | 214 ++ .../AcegiAuthenticationSourceTest.java | 129 + ...luesAuthenticationSourceDecoratorTest.java | 119 + ...RequestControlDirContextProcessorTest.java | 144 + .../ldap/support/control/PagedResultTest.java | 46 + .../control/PagedResultsCookieTest.java | 41 + .../PagedResultsRequestControlTest.java | 188 ++ .../support/filter/AbstractFilterTest.java | 67 + .../ldap/support/filter/AndFilterTest.java | 79 + .../ldap/support/filter/EqualsFilterTest.java | 71 + .../filter/GreaterThanOrEqualsFilterTest.java | 61 + .../filter/LessThanOrEqualsFilterTest.java | 60 + .../ldap/support/filter/LikeFilterTest.java | 56 + .../ldap/support/filter/NotFilterTest.java | 50 + .../ldap/support/filter/OrFilterTest.java | 64 + .../filter/WhitespaceWildcardsFilterTest.java | 75 + .../ldap/util/ListComparatorTest.java | 92 + .../src/test/resources/log4j.properties | 4 + spring-ldap/xdocs/navigation.xml | 43 + 555 files changed, 57531 insertions(+) create mode 100644 build-spring-ldap/.project create mode 100644 build-spring-ldap/build.xml create mode 100644 build-spring-ldap/checklist_release.txt create mode 100644 build-spring-ldap/jdiff/lib/2000/10/XMLSchema create mode 100644 build-spring-ldap/jdiff/lib/2000/10/XMLSchema-instance create mode 100644 build-spring-ldap/jdiff/lib/2001/XMLSchema create mode 100644 build-spring-ldap/jdiff/lib/2001/XMLSchema-instance create mode 100644 build-spring-ldap/jdiff/lib/Null.java create mode 100644 build-spring-ldap/jdiff/lib/ant.jar create mode 100644 build-spring-ldap/jdiff/lib/antjdiff.jar create mode 100644 build-spring-ldap/jdiff/lib/background.gif create mode 100644 build-spring-ldap/jdiff/lib/black.gif create mode 100644 build-spring-ldap/jdiff/lib/classdoc.jar create mode 100644 build-spring-ldap/jdiff/lib/jdiff.jar create mode 100644 build-spring-ldap/jdiff/lib/jdiff_logo.gif create mode 100644 build-spring-ldap/jdiff/lib/new.gif create mode 100644 build-spring-ldap/jdiff/lib/xerces.jar create mode 100644 build-spring-ldap/project.properties create mode 100644 build-spring-ldap/readme.txt create mode 100644 build-spring-ldap/release-toc.txt create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/AttributesMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextAssembler.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextExecutor.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DirContextProcessor.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapOperations.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapTemplate.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchExecutor.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DnParser.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/ListComparator.java create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1.1/src/main/java/overview.html create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextAssembler.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextExecutor.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapOperations.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapTemplate.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchExecutor.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/package.html create mode 100644 build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/package.html create mode 100644 common-build/.cvsignore create mode 100644 common-build/.project create mode 100644 common-build/clover-targets.xml create mode 100644 common-build/common-targets.xml create mode 100644 common-build/db-targets.xml create mode 100644 common-build/doc-targets.xml create mode 100644 common-build/ejb21-targets.xml create mode 100644 common-build/hibernate-targets.xml create mode 100644 common-build/ivyconf.properties create mode 100644 common-build/ivyconf.xml create mode 100644 common-build/lib/ivy-1.4.1.jar create mode 100644 common-build/project.properties create mode 100644 common-build/readme.txt create mode 100644 common-build/spring-targets.xml create mode 100644 common-build/templates/db/data.xml create mode 100644 common-build/templates/jsp/includeBottom.jsp create mode 100644 common-build/templates/jsp/includeTop.jsp create mode 100644 common-build/templates/jsp/pageshell.jsp create mode 100644 common-build/templates/log4j/log4j.properties create mode 100644 common-build/templates/projects/standard/.classpath create mode 100644 common-build/templates/projects/standard/.cvsignore create mode 100644 common-build/templates/projects/standard/.project create mode 100644 common-build/templates/projects/standard/build.xml create mode 100644 common-build/templates/projects/standard/ivy.xml create mode 100644 common-build/templates/projects/standard/project.properties create mode 100644 common-build/templates/projects/standard/src/etc/filter.properties create mode 100644 common-build/templates/projects/standard/src/etc/test-resources/log4j.properties create mode 100644 common-build/templates/projects/standard/src/etc/test-resources/readme.txt create mode 100644 common-build/templates/projects/standard/src/main/java/readme.txt create mode 100644 common-build/templates/projects/standard/src/main/resources/readme.txt create mode 100644 common-build/templates/projects/standard/src/test/java/readme.txt create mode 100644 common-build/templates/projects/webapp/WEB-INF/classes/log4j.properties create mode 100644 common-build/templates/projects/webapp/WEB-INF/dispatcher-servlet-config.xml create mode 100644 common-build/templates/projects/webapp/WEB-INF/web.xml create mode 100644 common-build/templates/projects/webapp/index.html create mode 100644 common-build/templates/readme.txt create mode 100644 common-build/templates/spring-webflow/FlowExecutionTestTemplate.java create mode 100644 common-build/templates/spring-webflow/flow-definition-1.0-form.xml create mode 100644 common-build/templates/spring-webflow/flow-definition-1.0-simplest.xml create mode 100644 common-build/templates/spring-webflow/flow-definition-1.0.xml create mode 100644 common-build/templates/spring-webflow/webflow-config-1.0-spring-1.2.xml create mode 100644 common-build/templates/spring-webflow/webflow-config-1.0.xml create mode 100644 common-build/templates/spring-webflow/webflow-form.jsp create mode 100644 common-build/templates/spring/bean-definitions-1.2.xml create mode 100644 common-build/templates/spring/bean-definitions-2.0.xml create mode 100644 common-build/templates/tomcat/context.xml create mode 100644 common-build/tomcat-targets.xml create mode 100644 common-build/version.txt create mode 100644 pom.xml create mode 100644 sandbox/.classpath create mode 100644 sandbox/.project create mode 100644 sandbox/.settings/org.eclipse.jdt.core.prefs create mode 100644 sandbox/.settings/org.eclipse.jdt.ui.prefs create mode 100644 sandbox/.springBeans create mode 100644 sandbox/build.xml create mode 100644 sandbox/itest-openldap-targets.xml create mode 100644 sandbox/itest-targets.xml create mode 100644 sandbox/ivy.xml create mode 100644 sandbox/project.properties create mode 100644 sandbox/project.xml create mode 100644 sandbox/readme.txt create mode 100644 sandbox/src/itest-openldap/java/conf/ldap-openldap.properties create mode 100644 sandbox/src/itest-openldap/java/conf/ldap.conf create mode 100644 sandbox/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml create mode 100644 sandbox/src/itest-openldap/java/org/springframework/ldap/LdapTemplateVirtualListViewSearchITest.java create mode 100644 sandbox/src/itest/java/conf/apacheDsContext.xml create mode 100644 sandbox/src/itest/java/conf/ldap.properties create mode 100644 sandbox/src/itest/java/conf/ldapTemplateAcegiTestContext.xml create mode 100644 sandbox/src/itest/java/conf/ldapTemplateBaseSuffixTestContext.xml create mode 100644 sandbox/src/itest/java/conf/ldapTemplateTestContext.xml create mode 100644 sandbox/src/itest/java/log4j.properties create mode 100644 sandbox/src/itest/java/setup_data.ldif create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/ContextSourceTransactionManager.java create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/DirContextHolder.java create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/DirContextProxy.java create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/TlsContextSource.java create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/TransactionAwareContextSourceProxy.java create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewRequestControl.java create mode 100644 sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewResultsCookie.java create mode 100644 sandbox/src/test/java/org/springframework/ldap/support/ContextSourceTransactionManagerTest.java create mode 100644 spring-ldap-article/.classpath create mode 100644 spring-ldap-article/.project create mode 100644 spring-ldap-article/.settings/org.eclipse.jdt.core.prefs create mode 100644 spring-ldap-article/.settings/org.eclipse.jdt.ui.prefs create mode 100644 spring-ldap-article/.springBeans create mode 100644 spring-ldap-article/build.xml create mode 100644 spring-ldap-article/docs/base_data.ldif create mode 100644 spring-ldap-article/docs/ldap.conf.example create mode 100644 spring-ldap-article/docs/readme.txt create mode 100644 spring-ldap-article/docs/setup_data.ldif create mode 100644 spring-ldap-article/docs/teardown_data.ldif create mode 100644 spring-ldap-article/ivy.xml create mode 100644 spring-ldap-article/pom.xml create mode 100644 spring-ldap-article/project.properties create mode 100644 spring-ldap-article/readme.txt create mode 100644 spring-ldap-article/src/itest/java/config/ldap.properties create mode 100644 spring-ldap-article/src/itest/java/config/testContext.xml create mode 100644 spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/AbstractPersonDaoIntegrationTest.java create mode 100644 spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/PersonDaoImplIntegrationTest.java create mode 100644 spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImplIntegrationTest.java create mode 100644 spring-ldap-article/src/main/java/log4j.properties create mode 100644 spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDao.java create mode 100644 spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDaoImpl.java create mode 100644 spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImpl.java create mode 100644 spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/domain/Person.java create mode 100644 spring-ldap-article/src/main/java/overview.html create mode 100644 spring-ldap-article/src/test/java/.dummy create mode 100644 spring-ldap-person/.classpath create mode 100644 spring-ldap-person/.project create mode 100644 spring-ldap-person/.settings/org.eclipse.jdt.core.prefs create mode 100644 spring-ldap-person/.settings/org.eclipse.jdt.ui.prefs create mode 100644 spring-ldap-person/.springBeans create mode 100644 spring-ldap-person/build.xml create mode 100644 spring-ldap-person/deps.txt create mode 100644 spring-ldap-person/docs/base_data.ldif create mode 100644 spring-ldap-person/docs/ldap.conf.example create mode 100644 spring-ldap-person/docs/readme.txt create mode 100644 spring-ldap-person/docs/setup_data.ldif create mode 100644 spring-ldap-person/docs/teardown_data.ldif create mode 100644 spring-ldap-person/ivy.xml create mode 100644 spring-ldap-person/pom.xml create mode 100644 spring-ldap-person/project.properties create mode 100644 spring-ldap-person/readme.txt create mode 100644 spring-ldap-person/src/itest/java/.dummy create mode 100644 spring-ldap-person/src/main/java/log4j.properties create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/ConfigEnvHelper.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/LdapServerManager.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyGroupDao.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyPersonDao.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupContextMapper.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDao.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDaoImpl.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonContextMapper.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDao.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDaoImpl.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/TraditionalPersonDaoImpl.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Group.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/GroupValidator.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Person.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/PersonValidator.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteria.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteriaValidator.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupService.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupServiceImpl.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonService.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonServiceImpl.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditGroupFormAction.java create mode 100644 spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditPersonFormAction.java create mode 100644 spring-ldap-person/src/main/java/overview.html create mode 100644 spring-ldap-person/src/main/java/setup_data.ldif create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/apacheDsContext.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/applicationContext.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/classes/log4j.properties create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow-beans.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/personmanager-flow.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow-beans.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/editDetails.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/editGroupDetails.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/error.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeBottom.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeTop.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/menu.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchForm.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupForm.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupResult.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchResult.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/showAddCandidates.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/showDetails.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/jsp/showGroupDetails.jsp create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/ldap.properties create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-servlet.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml create mode 100644 spring-ldap-person/src/main/webapp/WEB-INF/web.xml create mode 100644 spring-ldap-person/src/main/webapp/acegilogin.jsp create mode 100644 spring-ldap-person/src/main/webapp/images/spring-logo.jpg create mode 100644 spring-ldap-person/src/main/webapp/images/webflow-logo.jpg create mode 100644 spring-ldap-person/src/main/webapp/index.jsp create mode 100644 spring-ldap-person/src/main/webapp/logoff.jsp create mode 100644 spring-ldap-person/src/main/webapp/style.css create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/GroupDaoImplTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/PersonDaoImplTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/GroupTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/PersonTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/SearchCriteriaTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/service/PersonServiceImplTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/DetailFlowExecutionTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/PersonManagerFlowExecutionTest.java create mode 100644 spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/SearchFlowExecutionTest.java create mode 100644 spring-ldap-person/trifork.map create mode 100644 spring-ldap/.checkstyle create mode 100644 spring-ldap/.classpath create mode 100644 spring-ldap/.project create mode 100644 spring-ldap/.settings/org.eclipse.jdt.core.prefs create mode 100644 spring-ldap/.settings/org.eclipse.jdt.ui.prefs create mode 100644 spring-ldap/.springBeans create mode 100644 spring-ldap/build.xml create mode 100644 spring-ldap/changelog.txt create mode 100644 spring-ldap/docs/quickstart/quickstart.pdf create mode 100644 spring-ldap/docs/reference/images/admons/blank.png create mode 100644 spring-ldap/docs/reference/images/admons/caution.gif create mode 100644 spring-ldap/docs/reference/images/admons/caution.png create mode 100644 spring-ldap/docs/reference/images/admons/caution.tif create mode 100644 spring-ldap/docs/reference/images/admons/draft.png create mode 100644 spring-ldap/docs/reference/images/admons/home.gif create mode 100644 spring-ldap/docs/reference/images/admons/home.png create mode 100644 spring-ldap/docs/reference/images/admons/important.gif create mode 100644 spring-ldap/docs/reference/images/admons/important.png create mode 100644 spring-ldap/docs/reference/images/admons/important.tif create mode 100644 spring-ldap/docs/reference/images/admons/next.gif create mode 100644 spring-ldap/docs/reference/images/admons/next.png create mode 100644 spring-ldap/docs/reference/images/admons/note.gif create mode 100644 spring-ldap/docs/reference/images/admons/note.png create mode 100644 spring-ldap/docs/reference/images/admons/note.tif create mode 100644 spring-ldap/docs/reference/images/admons/prev.gif create mode 100644 spring-ldap/docs/reference/images/admons/prev.png create mode 100644 spring-ldap/docs/reference/images/admons/tip.gif create mode 100644 spring-ldap/docs/reference/images/admons/tip.png create mode 100644 spring-ldap/docs/reference/images/admons/tip.tif create mode 100644 spring-ldap/docs/reference/images/admons/toc-blank.png create mode 100644 spring-ldap/docs/reference/images/admons/toc-minus.png create mode 100644 spring-ldap/docs/reference/images/admons/toc-plus.png create mode 100644 spring-ldap/docs/reference/images/admons/up.gif create mode 100644 spring-ldap/docs/reference/images/admons/up.png create mode 100644 spring-ldap/docs/reference/images/admons/warning.gif create mode 100644 spring-ldap/docs/reference/images/admons/warning.png create mode 100644 spring-ldap/docs/reference/images/admons/warning.tif create mode 100644 spring-ldap/docs/reference/images/callouts/1.gif create mode 100644 spring-ldap/docs/reference/images/callouts/1.png create mode 100644 spring-ldap/docs/reference/images/callouts/10.gif create mode 100644 spring-ldap/docs/reference/images/callouts/10.png create mode 100644 spring-ldap/docs/reference/images/callouts/11.gif create mode 100644 spring-ldap/docs/reference/images/callouts/11.png create mode 100644 spring-ldap/docs/reference/images/callouts/12.gif create mode 100644 spring-ldap/docs/reference/images/callouts/12.png create mode 100644 spring-ldap/docs/reference/images/callouts/13.gif create mode 100644 spring-ldap/docs/reference/images/callouts/13.png create mode 100644 spring-ldap/docs/reference/images/callouts/14.gif create mode 100644 spring-ldap/docs/reference/images/callouts/14.png create mode 100644 spring-ldap/docs/reference/images/callouts/15.gif create mode 100644 spring-ldap/docs/reference/images/callouts/15.png create mode 100644 spring-ldap/docs/reference/images/callouts/2.gif create mode 100644 spring-ldap/docs/reference/images/callouts/2.png create mode 100644 spring-ldap/docs/reference/images/callouts/3.gif create mode 100644 spring-ldap/docs/reference/images/callouts/3.png create mode 100644 spring-ldap/docs/reference/images/callouts/4.gif create mode 100644 spring-ldap/docs/reference/images/callouts/4.png create mode 100644 spring-ldap/docs/reference/images/callouts/5.gif create mode 100644 spring-ldap/docs/reference/images/callouts/5.png create mode 100644 spring-ldap/docs/reference/images/callouts/6.gif create mode 100644 spring-ldap/docs/reference/images/callouts/6.png create mode 100644 spring-ldap/docs/reference/images/callouts/7.gif create mode 100644 spring-ldap/docs/reference/images/callouts/7.png create mode 100644 spring-ldap/docs/reference/images/callouts/8.gif create mode 100644 spring-ldap/docs/reference/images/callouts/8.png create mode 100644 spring-ldap/docs/reference/images/callouts/9.gif create mode 100644 spring-ldap/docs/reference/images/callouts/9.png create mode 100644 spring-ldap/docs/reference/readme.txt create mode 100644 spring-ldap/docs/reference/src/basic.xml create mode 100644 spring-ldap/docs/reference/src/configuration.xml create mode 100644 spring-ldap/docs/reference/src/contextprocessor.xml create mode 100644 spring-ldap/docs/reference/src/dirobjectfactory.xml create mode 100644 spring-ldap/docs/reference/src/executors.xml create mode 100644 spring-ldap/docs/reference/src/images/banner4.jpg create mode 100644 spring-ldap/docs/reference/src/images/bannerR.gif create mode 100644 spring-ldap/docs/reference/src/images/logo.png create mode 100644 spring-ldap/docs/reference/src/index.xml create mode 100644 spring-ldap/docs/reference/src/overview.xml create mode 100644 spring-ldap/docs/reference/src/preface.xml create mode 100644 spring-ldap/docs/reference/styles/fopdf.xsl create mode 100644 spring-ldap/docs/reference/styles/html.css create mode 100644 spring-ldap/docs/reference/styles/html.xsl create mode 100644 spring-ldap/docs/reference/styles/html_chunk.xsl create mode 100644 spring-ldap/docs/reference/styles/tld.to.docbook.xsl create mode 100644 spring-ldap/docs/reference/styles/xsd.to.docbook.xsl create mode 100644 spring-ldap/itest-openldap-targets.xml create mode 100644 spring-ldap/itest-targets.xml create mode 100644 spring-ldap/ivy.xml create mode 100644 spring-ldap/license.txt create mode 100644 spring-ldap/notice.txt create mode 100644 spring-ldap/pom.xml create mode 100644 spring-ldap/project.properties create mode 100644 spring-ldap/project.xml create mode 100644 spring-ldap/readme.txt create mode 100644 spring-ldap/src/itest-openldap/java/conf/ldap-openldap.properties create mode 100644 spring-ldap/src/itest-openldap/java/conf/ldap.conf create mode 100644 spring-ldap/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml create mode 100644 spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplateLookupOpenLdapITest.java create mode 100644 spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplatePagedSearchITest.java create mode 100644 spring-ldap/src/itest/java/conf/apacheDsContext.xml create mode 100644 spring-ldap/src/itest/java/conf/ldap.properties create mode 100644 spring-ldap/src/itest/java/conf/ldapContextSourceTestContext.xml create mode 100644 spring-ldap/src/itest/java/conf/ldapTemplateAcegiTestContext.xml create mode 100644 spring-ldap/src/itest/java/conf/ldapTemplateNoBaseSuffixTestContext.xml create mode 100644 spring-ldap/src/itest/java/conf/ldapTemplateTestContext.xml create mode 100644 spring-ldap/src/itest/java/log4j.properties create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckAttributesMapper.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckContextMapper.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapServerManager.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateAttributesMapperITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextExecutorTest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextMapperITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateListITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateLookupITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateModifyITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateNoBaseSuffixITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRecursiveDeleteITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRenameITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.xls create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchResultITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/Person.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/PersonAttributesMapper.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/PersonContextMapper.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/support/DnParsePerformanceITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelMultiServerITest.java create mode 100644 spring-ldap/src/itest/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceITest.java create mode 100644 spring-ldap/src/itest/java/setup_data.ldif create mode 100644 spring-ldap/src/itest/java/teardown_data.ldif create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/AttributesMapper.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/AuthenticationSource.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/BadLdapGrammarException.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/ContextAssembler.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/ContextExecutor.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/ContextMapper.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/ContextSource.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/DirContextProcessor.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/EntryNotFoundException.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/LdapOperations.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/LdapTemplate.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/NameClassPairMapper.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/SearchExecutor.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/SearchLimitExceededException.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/UncategorizedLdapException.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/package.html create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/AbstractContextSource.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DirContextAdapter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DirContextOperations.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DirContextSource.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DistinguishedName.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/DnParser.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/LdapContextSource.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/LdapEncoder.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdn.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/authentication/package.html create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResult.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/control/package.html create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/AndFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/Filter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/NotFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/OrFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/filter/package.html create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/support/package.html create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/util/ListComparator.java create mode 100644 spring-ldap/src/main/java/org/springframework/ldap/util/package.html create mode 100644 spring-ldap/src/main/java/overview.html create mode 100644 spring-ldap/src/main/javacc/DnParserImpl.jj create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/CollectingNameClassPairCallbackHandlerTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateListTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateLookupTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateRenameTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/RequestControlMatcher.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/AggregateDirContextProcessorTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/CountNameClassPairResultCallbackHandlerTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/DefaultDirObjectFactoryTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterBugTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/DistinguishedNameTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/LdapContextSourceTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/LdapEncoderTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnComponentTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecoratorTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessorTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsCookieTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsRequestControlTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/AbstractFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/AndFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/EqualsFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/LikeFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/NotFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/OrFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilterTest.java create mode 100644 spring-ldap/src/test/java/org/springframework/ldap/util/ListComparatorTest.java create mode 100644 spring-ldap/src/test/resources/log4j.properties create mode 100644 spring-ldap/xdocs/navigation.xml diff --git a/build-spring-ldap/.project b/build-spring-ldap/.project new file mode 100644 index 00000000..d27922c5 --- /dev/null +++ b/build-spring-ldap/.project @@ -0,0 +1,11 @@ + + + build-spring-ldap + + + + + + + + diff --git a/build-spring-ldap/build.xml b/build-spring-ldap/build.xml new file mode 100644 index 00000000..0c3024a0 --- /dev/null +++ b/build-spring-ldap/build.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Master build for spring-ldap main and sample jars. + + Please execute + build -projecthelp + + to see a list of all relevant targets. + The default target is 'main' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + projects=${projects} + projects.names=${projects.names} + + + + + + + projects=${projects} + + + + + + + projects=${projects} + + + + + + + projects=${projects} + + + + + + + projects=${projects} + + + + + + + projects=${projects} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build-spring-ldap/checklist_release.txt b/build-spring-ldap/checklist_release.txt new file mode 100644 index 00000000..5439074e --- /dev/null +++ b/build-spring-ldap/checklist_release.txt @@ -0,0 +1,64 @@ +build-spring-ldap +================= + +* Update release number in project.properties + + release.version=1.1 + +spring-ldap +=========== + +* Update release number in project.properties + + project.base.version=1.1 + project.version=${project.base.version} + ivy.status=release + +* Update release number in reference manual (docs/reference/src/index.xml) + + + Spring LDAP + Reference Documentation + Version 1.1 + +* Update release number in readme.txt + + Spring-LDAP 1.1 (Aug 2006) + +General +======= + +* Update changelog with changes, including upgraded libraries + +* Synchronize and commit changes, including .* files + +* Run clean-all from build-spring-ldap + +* Clean integration-repo + +* Clean Ivy cache + +* Run all tests, including integration tests + +* Run the sample spring-ldap-person in a web container + +* Run the sample spring-ldap-article integration tests + +* Run doc-all from spring-ldap + +* Run release from build-spring-ldap + +* Run jdiff from spring-ldap + +* Add Maven pom file for the new release to top directory. + +After release +============= + +* Store source for new release in build-spring-ldap/spring-ldap- + (used in future jdiff runs) + +* Tag release like this: + 1. Open a svn repo browser, eg Eclipse + 2. Create a new directory: spring-projects/tags/spring-ldap- + 3. Copy repository, common-build and spring-ldap to that directory diff --git a/build-spring-ldap/jdiff/lib/2000/10/XMLSchema b/build-spring-ldap/jdiff/lib/2000/10/XMLSchema new file mode 100644 index 00000000..781076e8 --- /dev/null +++ b/build-spring-ldap/jdiff/lib/2000/10/XMLSchema @@ -0,0 +1,2201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + + + Part 1 version: $Id: XMLSchema,v 1.1 2001/11/16 06:19:40 mdoar Exp $ + Part 2 version: $Id: XMLSchema,v 1.1 2001/11/16 06:19:40 mdoar Exp $ + + + + + + + The schema corresponding to this document is normative, + with respect to the syntactic constraints it expresses in the + XML Schema language. The documentation (within <documentation> elements) + below, is not normative, but rather highlights important aspects of + the W3C Recommendation of which this is a part + + + + + The simpleType element and all of its members are defined + towards the end of this schema document + + + + + + Get access to the xml: attribute groups for xml:lang + as declared on 'documentation' below + + + + + + + + This type is extended by almost all schema types + to allow attributes from other namespaces to be + added to user schemas. + + + + + + + + + + + + + This type is extended by all types which allow annotation + other than <schema> itself + + + + + + + + + + + + + + + + This abstract element defines an substitution group over the + elements which occur freely at the top level of schemas. These are: + simpleType, complexType, element, attribute, attributeGroup, group, notation + All of their types are based on the "annotated" type by extension. + + + + + + + This abstract element defines a substitution group for the + elements which can self-redefine (see <redefine> below). + + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + 'topLevelGroup' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This branch is short for + <complexContent> + <restriction base="anyType"> + ... + </restriction> + </complexContent> + + + + + + + + + + + + + + + Will be restricted to required or forbidden + + + + + + Not allowed if simpleContent child is chosen. + May be overriden by setting on complexContent child. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + + + + + + + + + + + + No typeDefParticle group reference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + #all or (possibly empty) subset of {substitution, extension, + restriction} + + A utility type, not for public use + + + + + + + + + + + + + + + + + #all or (possibly empty) subset of {extension, restriction} + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + The element element can be used either + at the toplevel to define an element-type binding globally, + or within a content model to either reference a globally-defined + element or type or declare an element-type binding locally. + The ref form is not allowed at the top level. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and + group references + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for the three kinds of group + + + + + + + + + + + + + + + + + + + + + Only elements allowed inside + + + + + + + + + restricted max/min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all + + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS + + ##local - - any unqualified non-conflicting WFXML/attribute + + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) + + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An XPath expression + + A utility type, not for public use + + + + + + A VERY permissive definition, probably not even right + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A public identifier, per ISO 8879 + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + notations for use within XML Schema schemas + + + + + + + + + Not the real urType, but as close an approximation as we can + get in the XML representation + + + + + + + + + + First the builtin primitive datatypes. These definitions are for + information only, the real builtin definitions are magic. Note in + particular that there is no type named 'anySimpleType'. The + primitives should really be derived from no type at all, and + anySimpleType should be derived as a union of all the primitives. + + + + For each built-in datatype in this schema (both primitive and + derived) can be uniquely addressed via a URI constructed + as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is an XPointer that identifies + the name of the datatype, as an ID + + For example, to address the date datatype, the URI is: + + http://www.w3.org/2000/10/XMLSchema#xpointer(id("date")) + + Additionally, each facet definition element can be uniquely + addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is an XPointer that identifies + the name of the facet, as an ID + + For example, to address the period facet, the URI is: + + http://www.w3.org/2000/10/XMLSchema#xpointer(id("period")) + + Additionally, each facet usage in a built-in datatype definition + can be uniquely addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is an XPointer that identifies + the name of the datatype, followed by a period (".") + followed by the name of the facet, as an ID + + For example, to address the usage of the period facet in + the definition of date, the URI is: + + http://www.w3.org/2000/10/XMLSchema#xpointer(id("date.period")) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Now the derived primitive types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 33 from the XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 7 from the XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 5 from the XML spec + + + + + + + + + + + + + + + pattern matches production 4 from the Namespaces in XML spec + + + + + + + + + + + NOTATION cannot be used directly in a schema; rather a type + must be derived from it by specifying at least one enumeration + facet whose value is the name of a NOTATION declared in the + schema. + + + the value/lexical spaces of NOTATION are not the full + value/lexical spaces of NOTATION even though there are + no additional constraining facets. The true value/lexical + spaces are limited to the set of names of NOTATIONs declared + in the schema. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Can be restricted to required or forbidden + + + + + + + + + + + + + + + + + + Required at the top level + + + + + + + + + + + + + + + + + + Forbidden when nested + + + + + + + + + + + + + + + + + + + + + + + + + + + base attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + itemType attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + + + memberTypes attribute must be non-empty or there must be + at least one simpleType child + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + each (8-bit) byte is encoded as a sequence + of 2 hexidecimal digits + + + + + + + value is encoded in Base64 as defined + in the MIME RFC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build-spring-ldap/jdiff/lib/2000/10/XMLSchema-instance b/build-spring-ldap/jdiff/lib/2000/10/XMLSchema-instance new file mode 100644 index 00000000..94d6d43b --- /dev/null +++ b/build-spring-ldap/jdiff/lib/2000/10/XMLSchema-instance @@ -0,0 +1,31 @@ + + + + +]> + + + +

XML Schema instance namespace

+

See The XML Schema draft recommendation for an introduction

+ + +
+
Henry S. Thompson
+ $Date: 2001/11/16 06:19:40 $
+ $Id: XMLSchema-instance,v 1.1 2001/11/16 06:19:40 mdoar Exp $ +
+
+ + + No definitions are provided here, as + this schema is never used as such + + + + + + +
diff --git a/build-spring-ldap/jdiff/lib/2001/XMLSchema b/build-spring-ldap/jdiff/lib/2001/XMLSchema new file mode 100644 index 00000000..fa1eeefa --- /dev/null +++ b/build-spring-ldap/jdiff/lib/2001/XMLSchema @@ -0,0 +1,2441 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + + + Part 1 version: Id: XMLSchema.xsd,v 1.49 2001/10/25 10:25:41 ht Exp + Part 2 version: Id: datatypes.xsd,v 1.53 2001/10/25 10:26:05 ht Exp + + + + + + + The schema corresponding to this document is normative, + with respect to the syntactic constraints it expresses in the + XML Schema language. The documentation (within <documentation> elements) + below, is not normative, but rather highlights important aspects of + the W3C Recommendation of which this is a part + + + + + The simpleType element and all of its members are defined + towards the end of this schema document + + + + + + Get access to the xml: attribute groups for xml:lang + as declared on 'schema' and 'documentation' below + + + + + + + + This type is extended by almost all schema types + to allow attributes from other namespaces to be + added to user schemas. + + + + + + + + + + + + + This type is extended by all types which allow annotation + other than <schema> itself + + + + + + + + + + + + + + + + This group is for the + elements which occur freely at the top level of schemas. + All of their types are based on the "annotated" type by extension. + + + + + + + + + + + + + This group is for the + elements which can self-redefine (see <redefine> below). + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This branch is short for + <complexContent> + <restriction base="xs:anyType"> + ... + </restriction> + </complexContent> + + + + + + + + + + + + + + + Will be restricted to required or forbidden + + + + + + Not allowed if simpleContent child is chosen. + May be overriden by setting on complexContent child. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + + + + + + + + + + + + No typeDefParticle group reference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {substitution, extension, + restriction} + + + + + + + + + + + + + + + + + + + + + + + + + The element element can be used either + at the top level to define an element-type binding globally, + or within a content model to either reference a globally-defined + element or type or declare an element-type binding locally. + The ref form is not allowed at the top level. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and + group references + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for the three kinds of group + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + restricted max/min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Only elements allowed inside + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all + + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS + + ##local - - any unqualified non-conflicting WFXML/attribute + + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) + + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in selectors + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the following EBNF: + Selector ::= Path ( '|' Path )* + Path ::= ('.//')? Step ( '/' Step )* + Step ::= '.' | NameTest + NameTest ::= QName | '*' | NCName ':' '*' + child:: is also allowed + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in fields + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the same EBNF as for selector, + with the following change: + Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) + + + + + + + + + + + + + + + + + + + + + + + + + + + The three kinds of identity constraints, all with + type of or derived from 'keybase'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + A public identifier, per ISO 8879 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + notations for use within XML Schema schemas + + + + + + + + + Not the real urType, but as close an approximation as we can + get in the XML representation + + + + + + + + + + First the built-in primitive datatypes. These definitions are for + information only, the real built-in definitions are magic. Note in + particular that there is no type named 'anySimpleType'. The + primitives should really be derived from no type at all, and + anySimpleType should be derived as a union of all the primitives. + + + + For each built-in datatype in this schema (both primitive and + derived) can be uniquely addressed via a URI constructed + as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype + + For example, to address the int datatype, the URI is: + + http://www.w3.org/2001/XMLSchema#int + + Additionally, each facet definition element can be uniquely + addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the facet + + For example, to address the maxInclusive facet, the URI is: + + http://www.w3.org/2001/XMLSchema#maxInclusive + + Additionally, each facet usage in a built-in datatype definition + can be uniquely addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype, followed + by a period (".") followed by the name of the facet + + For example, to address the usage of the maxInclusive facet in + the definition of int, the URI is: + + http://www.w3.org/2001/XMLSchema#int.maxInclusive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOTATION cannot be used directly in a schema; rather a type + must be derived from it by specifying at least one enumeration + facet whose value is the name of a NOTATION declared in the + schema. + + + + + + + + + + Now the derived primitive types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern specifies the content of section 2.12 of XML 1.0e2 + and RFC 1766 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 7 from the XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 5 from the XML spec + + + + + + + + + + + + + + + pattern matches production 4 from the Namespaces in XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + #all or (possibly empty) subset of {restriction, union, list} + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + Can be restricted to required or forbidden + + + + + + + + + + + + + + + + + + Required at the top level + + + + + + + + + + + + + + + + + + Forbidden when nested + + + + + + + + + + + + + + + + + + We should use a substitution group for facets, but + that's ruled out because it would allow users to + add their own, which we're not ready for yet. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + base attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + itemType attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + + + memberTypes attribute must be non-empty or there must be + at least one simpleType child + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build-spring-ldap/jdiff/lib/2001/XMLSchema-instance b/build-spring-ldap/jdiff/lib/2001/XMLSchema-instance new file mode 100644 index 00000000..d7e0c418 --- /dev/null +++ b/build-spring-ldap/jdiff/lib/2001/XMLSchema-instance @@ -0,0 +1,38 @@ + + + + + + + + +]> + + + +

XML Schema instance namespace

+

See the XML Schema + Recommendation for an introduction

+ + +
+ $Date: 2002/01/09 20:32:53 $
+ $Id: XMLSchema-instance,v 1.1 2002/01/09 20:32:53 mdoar Exp $ +
+
+ +

This schema should never be used as such: + the XML + Schema Recommendation forbids the declaration of + attributes in this namespace

+
+
+ + + + + +
diff --git a/build-spring-ldap/jdiff/lib/Null.java b/build-spring-ldap/jdiff/lib/Null.java new file mode 100644 index 00000000..75a57019 --- /dev/null +++ b/build-spring-ldap/jdiff/lib/Null.java @@ -0,0 +1,9 @@ +/** + * This class is used only as a "null" argument for Javadoc when comparing + * two API files. Javadoc has to have a package, .java or .class file as an + * argument, even though JDiff doesn't use it. + */ +public class Null { + public Null() { + } +} diff --git a/build-spring-ldap/jdiff/lib/ant.jar b/build-spring-ldap/jdiff/lib/ant.jar new file mode 100644 index 0000000000000000000000000000000000000000..8ad84e348091fa8e10ef2e58a236cc0e807a1c00 GIT binary patch literal 417110 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

)Gp{tUgyc|7_JjE!TH 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

q=! z6i~F4(Gzpp2o2Ogxif*bwX`gI-v$#U=8wYGQFfse+v9dU6K)ftr3OS%x$#wQlfXX; z_{j0qHVQHCG2FP#g;wkE0+74SKZZ2xybxfY*`seQD}_`5GeJ>9m(U*M-2onwuZ-8B zwisPOI%8@O)Ga&yvI35YPkDXqFws2HZc>e_%XzR>S;|wMv@zNQkNP%KKe$`BV_aFZ zFE6AdhAA?WL8~=k7?lL~^y%4mS_$VzNr)gXwvW(@mZ~kGp<~yVL!!kNE?)BX%-u!1 z{9%;W4KGA;Rb5uU)H`Uw0}8=nQYpd{MNL|xSKD9d{A;HJ;j)QwCPs*OLc!AMfMhxy z_*%dc^maAdG0*(x>@w#s)z_g5ym|>TN28R--SAzfn90q@_Jk=<1zygf$4t6G~$sLpgZ({lA4%Yhe5H^nt@)CC#VUNTl9*_9noW(;oMu$YMCO*(h=r5H+ROe~K) zyP`dqlN*mMPZ-j~J%g`2Gw5dWqOK|m1~6x(Wlt--JIVuV)+SqbHTV@@O_-hVNd&nc zugjl_6;!9Sx_-ED2MP9@_?C2y6KwT%dL}x*l*sXTKS{m1h$&_l4B%*&|gczB3m`C1+@xjxU1%um1D&{p(~*O04cF z21Z3Q7umqliZ!ho_Y}M?!idgWIOeXLbtL2OM#qT5kH05*4aW`#xpEPxTN&#D_kvTd__Y{-RJlvCYpk*-va2y)!6-OpbW|W6&QMg@0C} zer?Z+{2G#eiy8<~PJhYzTG&my;mxAx&GJDWry^nz2cBxg9e{QOE;z&)WNR&P zr*UM6OaN3lVD3sY4nxVEar#Q;9SE2<%m<6?${Dh#6PHh=t((jYfOOMe!J&WB$mxT1 zSi)IEg02-oDMj<_pK={H*FVL>QRccaZZ*VhQLfBXCP7nXNMtskOgt}kHRYZwgJ-zz zi2_o+N?_6!$x-o(Y?DjZ7S)Wmi53s^+k$A7iPZ|MhR-~w_qNES2omY0rRIt?p=AgB;DGp zWom6qv2c+bZ4XUz*zt9ya$?b|!27#F!>-#)-EWVc(@#sZ+5AS6EChI=#Bt73Q+C$pcI@a!s6xb*C1&z5vhJc;`Z$~Uyj$t7oSPJUQ~85Ihs=l*1D+~`eW{0Y{ssyZzQA^-(~0DA*~8s<`>ivIu6ih) zw7%tBIeqJ^F1OimL6HwZX?eks#J~J3wYv|x#|`9vbaP0z7Y4ifTyVT|Q}Aax6b;B1 zxc=<_Mdeb#_#M;ORu08bOR}A6F!Ndj)??eFTBt#J{GzJImzI96%WekR`}sCRZ*rK7 zrkT+4D@3be(f16xGEa14BYG|r)=YFa_-A42cCFlPBRau&BJ0D=_}s({Esb2AeDdT{ zs~VDSWis{Az0GVf-q0<+;(?dvA-3WnH|7Lfo4&p&ephhx+ZJUhGO?bx{;;5aN>CSf z;dN;h-&p1~rM&8mS8OWBs|IZgnO5f%rh|w-leSj(3V?Sa;I{$OeMi||&BTG|S;0P&}(qp!wI4EFv&@FG8b4ihs;lWFhZY}n+K zb#h63_)On|)UKqyII2kZ)0?oj+O;1M`$Ai0R%Vh>CD^l&w9FK$F>a_91!ms8 z06}k%uvcUw2Fei&Z`x;#bZf@gInCqT=`F6|R`W{T<%RRgy&)7Y*S!X5v~(BQ;easa z$x+U+D|O!w|99x?FN0_mw~OOv;t}eR(7ccTQpm)Zi7!4u{PG2g_}?|q-2Z6<{pq-F zW@PvM6P;)K{{!>vV&xSEn2~|GprXKAfG}~Jh}I8^mZ~6OQCJm<#~{9>BxI>ahzDDG zZeb*#W5jpaJ~+@F|6TX-%kdwm4(<_=pWP7PK(ZO<-&IEcA8GFtq)E4K;Z~PztIIaJ zY}>YNyUSLWZQJHoHoI)w)~U7DJ`wxo{A)*?h`h+#%#4_G<{0mI#+BW8d2&2^v0Cu_ z&PL*<_>rnvQzL?!83Oc&vuW#}^<>_@PkPbQOc%bW1X82mE`D5kG1VLBIt<7B8N6RM z@fccQfcUDcowLsEIGU`wvfv(a+frPNb2@C|V5u{*bSkFl%E8rsD=HC~mlQ@mkB_aw zeto3+T*v%|Vakkc-{r%p)t*OGR8DhM+~D6~f_S0j99{wvwROeTp9-(bno7-q0rp!^ zUJxDs##!h|=)ygHzqTtyDX1FDrixha-gBl}Q%uO2P9EaOkT!5<)3b zDW{d=W=h(AqP$>9c&e%+=LQy=d3{Hu+e^IepL%-u#DGd}`1>ef7q(qsBTU3;Fif+(0|0k@swtwJg_XVV3=T`9RJoOOt_G;#BBY& zI(1NLnY$ScsE?g$i#KQCgJ*3SKqfyyhqEW$X>Et|O6b^K$}W}vmN*2seda`FQLai_5J#F2}d z5E13)kKu+evpM5-m*_^9QLtof8szv~)F)v<#&xXtK!YM5AW7l0dLHsoIxM2c?#OYP z6Nf{bqI2gG{oH&U9x5HHk_h%q`PpFE?}3edQOemy+ea=7dH{_sy7!mrM?P7+nQS8c zv1((562YeGYz#cqBx&Y&wuS6!$Y7dM$ZV~Pm;xYL(^z2BW`?BkoQPr2WonG)O(yiD zEQw-qBtJ3SMQGH*Qvg>Ia{68lAqG|l3%wFuC3U2fotmk6h8Un4KZu70ziwkJ1|~B+ z?wCv!lGvx>{#~%LPv;nHzeZWEE{O1;8w{^FOCA%mCd*lE=F+~%-eNN!eTE*3;2x4j zMehWqAHkJ)@|%rs8n?YLUtys(pNl?aYz{}IE(#6nN!dH%jfxjVij6nLzTMEgx+9YE z*VT~QZyV~1q_#C030hprvg$cB)Yp!(&Kel!k7iryr5>iM3Tv%BCf>q^C~;oQj*|+S z44gaakK(rIv4x0n4bgA<*Ae?d=KMk&3QJnZ8A31S3;hW=27?i>=~Zxk4Av0Xlb*XV4~`Qdwa^kCBYkc$c815!HSy%~&L4hERg8P1aU_&UHaz zo-v5{{05KRBr;#Kn@82cnh_>`$HEUef6at23Xk)Z1>fLTK?+Nh_;&77HmRGY+}!zY zcoz^jDB60q*b!kdhR~rH+{dI;XQ3iisb{ya;7Bt2SH0Fq6qaxs7N{)sJnyR=ZW#c< zrBNz)KH62TS!9|hTAVml@Vk>amBG?WW>4;`uY?9KNzZ2fmQ>I?wy`h3SCaT$zNa?A zv#KcRz+NA1v1_rg>J`3;)|i3o`uN80E6m!7ouwfnutxSwB)zY{FTRAmGa}g`-g%qy zRCRV4$1`FkZ^pDndLV{3VToc=^BnMls_|QW?lZ_|2$ASK)H^zlsrQBh+lm`**}s7d zHLuxW%<_{va2Gsy_UBd`J;UmX=RD~kF zgB+euRNe+N#4(q(&Lxc(W0^|_Fy>9|uwOW`6Y}1&x3!_Xau{1H5`X!-ok#)wn!n=S zTr+e_EQH)uyD7=#?Jf?^`V5zZmmKaG}d{-bkdxym? zJX+#%uuh*nW4^FgpR~rvCHBFADadD|v!JrB8;42ZbJKD78;d75zbvg=N|hK?L1}sV z#t{CxYK@s-hAo-1f{hPQLxbHT9Y#xXby9k+@NN+J!?=c_9ibvv5rHklnMCK|yRl1a zYX>FesY_hjN=>^m4_PUnC11`gjX^UHs@16Y>O>{TsfS3b zx4d6txlNl%SkyNI*XhrOHT6}43A^5J1McLx%Dp||4BXIuWF8~SN`tN5j~7Dy1Y$51 z%I=}WBCOQP#Gr!|_x(U~O2fW7Bi{U4e;gy4g6cye{5#Z5Q_qLiw{15xo_{nggO>(re25PUNUQtBm1FVkEDeA z*>wa46Lzo0OXRj@%BxOI+Q(8R=|agj&`VoerB$bL;bQpU(>5$y_lFCQ$V zqd{t%khytBLYPcr40fHBm^OUQbzt`nu&|EL1C_>?ipf<#R+Z7tn9p4jv8szY5#8a^ zG(_e>Of$YS6Y;s&6kBkMV)xqAYxT2F!rJXwoBM>fUm#A7>IjcAsE%<985e`t91j0@ zGZ}C|fb#5+?&_cUloO1ed-oy3y3!{}SXdOt#EVMKHgq_|z=Z7~*4!M#g&Xy?B}+!TO5Z4t+8doER8E60|Ep}8bx0`F9=FvtRUB45kQQZ4k}rzquI1Mp-l#o z&~`Eb2j+6|_taIbWwENGUEW2jCCS!D)#P`5(O;J`)hfHQx4L%CCe55Gouh62`~YYbCCEsC4m9+4VcLf#D`^3L=aU5DhwUr5*WfgBPxu$dh) zcM;1HW=vb_TP_Q%A&6J zzo&J@UN7#m-o(zv{n-TVH93pRj1`JOrYA&wcXjFx7iUrqAp1!FjP^4 z&F~25&&ZUPE^;tujS~;(=Vd@vJq?ME5m_yihf|iD>)C?VTq+d9p~3LXgmQL@LIZV2 z38{z6)BQRI4s}Z_FSAQgM|#_m=CpFLqoLYEfLU=hQ8w)*UaWDs(+z<2fSNwLl4gHE zw+D12{8qbid1u1`v{Sx&*DyF>Lve$aL;b*P;k|ZXoE9B!C11L-QTb0|$#ktApK#7C z?!kzp3}^mlGl0@ckcilyULE)#B{H9&WTI1xUk$=`;(qbrREq8rw-hypBa7NJ@h3$m zvyXkGS^;!JB21ymLIt@aG|W;v{)+ib#qlDziTOlsWgLhgJoG438lq!CTtHlYoDj*9 zTR9Qg+N;j-9MYw z^18`xh7!#axbaMs#yxQk?E;$92Ezy%d&kDVQZ8@CT?r?2z-#s|8J;lL$5Zk(sa)1* zN~r3LHPxNZbo-sR2NZ%h8F@9FkqcCTkwnjQOs*|;iC=42pP6*cu07i$%UF*;CKKMC zr1TG^s3#9MxH5rilN{||knw6W^hovxrBj?q=9*Qc_ie}x@I)t2TnXbJ{+d3-_4znA z2$UeQZ}#HAb!(HHb@%hH3$qbx1?Wq`b_eJoANmHe3F&dlAYk1yWSMAk1$eR*M1YAN_8QP*O zTB$x%I-XcIs$79q|A|FD{1Mo4mn3dPe*q?f+X^C)cHQn^*pqP-1OZ8BK(VvDTo-H$ zbtfBGvnvoNxm(Zr*(D)9+%iXvvZq>SZo1vLo63_WMLskk#4uTZ8y+6uLy^%u$0MyX z_MYZk-?n+d;e~o~!M{W3WGJ|+n{t1Ng)mFY@LeI9Zg5>oGYz8BRYOccc#QPNvIBN= zQZ3XYwvV_IgAwC6@vQ3B*~O*3m{W&KYn99NMt^lx@BG0|?)JSSM4FrxJoE}I&?3!| znRERIN%=E+7j0}mTK2WNbmRiuI$wZivvD%I-sVoTLe0jdtCvgGvqpMEBl-OaP4UH1 z;B`3_I%KR9Xo{=~qe@NvApt^v6%P5NHlw_&TeN3+{`pW+y8Gt5lWSWMy($jRvEA?M zCTLoE`w^eu!}Y0I#S`3lneu7$mgEZP`LUi66kUNe#AV%PkH?F4qm&KR*k2Y$@Gl#s zMy_>A*(sr>A-{ucN%g277gi0#5uHFxS?(WA;WK5D`pd*ks zxm>c#MJ;{t`FE|IrQ}Yn=)TNLCS`110;=?5_Yg|BacxjjHQ>EM_QX*f5hP18Kl6Wf zf@DQ>ICKxEYX)dF9lX_Y*m^Ab0VbYS7l<4SkJaUQ4AG$v;}d!OTglMeEJFi=8}mu; znLIg=n&w3Aq1%5&61KsRc4{rq zDSc1`p1d80vKCa6sz9`hyb;PHb62wMW0EF?9b{C~XsqI1DAkM$-5p%6pHR!Q7FTW$ z+14K&^3u9;(S?Ie*(PTQ_L>5%kB^Mp)La^1=XoPksqDN%pVVm%i8_=8l6B{0(vk1P!)PA7QEpw6SeR|m8Nh3s#zX>4>s1>E|#3lKzcu| zSd2`k0D!^~RJ4~s0MIMp30;9Ib;Pa@!36Z@-Nwm0>0ZxEtUn1IU{ zvXgsS`_24Dj>|RNC+nCB>(3vcUx>fHAb;@%(|?sVa^N?J@aKQtqJ za&p~mb4u_+Z02ux9+)dQZI9s4Zo>0w-Pjq1ym;rR|022{g0T_o8O< zV2uENKsD2`I0F+n;|0V6JjEk<94v5bC9qW$qKg{j3zl2t@tJ|_seq`t3h1)bvl2K4 z`OOPCj108(GjqMCVX%jp|UM$F~uRU++ z0w?amYhdnAMWHi+YGMa_G{H1H1BO(uyn-1NBK1_zv#DR3C!qq- zUcsxOosHD1aqwDN@%nt9if9NO{1USedEz)l4C*de$c(Z98W~bId~T(oOBr-12eiL2 zTJnix7^f9$^?o+PLVMr#sY@TXt*f$HW8G;;$9NW$r zt;J8(QTx}KF*X=fcZ*9znv}(%qf<7!8$$Co5TEyaeSxQ7@3~6dVX@I=95FX{&^zc z>n}@~m)+Y!-lX~3jb2>Bl9m0J=w6Ff(r*UV6mA;GhK|khj-!}%8~%dma$&ViO6nTB zD)6nb$h#zY-$;{ftK#9>t4Wu)s_HP-;_R3t{ta9m+Ozx?!Z_^Tct0j45>!lvpdxEj=Ji1P*RiR-#(KSiAoP zRoG$R7KpkPK{O&XNY8XiE;h6TJ7vx(WR|I5_P!nEdjs;xdU|Es3`GOA8=BeWb$PY! zh+chx{1B0P0R9b$I) zwgxvw{~eNMk)S(afS3abBu~%{q-LC|p`d>ua)N*{k$Mb>q_NOQ*^xppM=|_VC<9s$ zl0b%FW3O@vK5Sm@uUKk>U;}_cMLsflqB~<)f`BxPaAfm3Dfxrp<_TBY6b5-AEx{0I zKtfw*V-az!>-TW7L|1M}1Jg;W>89*yNP=@Q%$)2c85L<3zJD<-2l0_Lin;X_CK}{@ zI*MYh2Z7m0-tIzcqv-t&H!I9s@&ew9UF&9my95Duq1-4hpbj(cuN~&x>Eu~+mEg+q zrUUsCpnXq#Tp!em+KeIjn3mTX&3Ld*tN}Q^KnI+bin`(m+Iigu(wRF4E8~u8W|h}o znJz+^$Y)iIB_9v+>b4)j? zti^FpB=pMFS`b}4GKFmx4`)hhBbgE1Z9>63R%0<&3oz~;T!fFXs{&WE<5JxLhP~?m zXGg&{uKg%Np7K;}JHSmAy-t~Q6f%`+_*fj$Vy_8Ulk5y+2A2AG>S|!;prnPn+NI$l zE|cXenYr5O4AD{Hyi8g;*ehUGgJYXDI8fcgbFotsarc+qyD1EbT&^)-d;D%K1iU@- z19ZJh4RRC_^n3U_A1|(n$oC7gI$uoFGSc;%Fa}Kg_rK27!PD57Cv>BIPt;smMrsaQ z^gz z@Lq%gvyg^#{%iTNrhHJoZ9zDkN!&L+ubnU!})7w)q^9CzdpfO*?-(`_BmJ%~xtsdg2F=8*yXC2M^cZwl)w z6*K2FRsP*;f;#U+bFhANv4o;!K?vgGm~pJ?VTO=Tvt(Tr0q?P(Au%(!X%>lZwQzst ze&#H7>RVcb&Z02zWfeejGr}g!%r9;+yyZ|TR!oT&YvPB3LGHhBWLA*FePrAD(yANSy+E^VW4|C1l2 z(nwJQaAV&DoT_MF{kqIq5}#dJvi0wv)q zDWf;Ik9*igBDOcnia**HgmZnV(a5;`2En5m&8*JljCQeKH?@bPBL}ZzlHQ_t>PWd! z`f68Twhg2B`UmX=?Q7U4`r$cbp?eT92f`s*T-JiV`d6%^k~bL4+Vmc0LAJ@d*X-3! zi`Vla{sY|UsGd+bQc4OQ=|F`@ecT4f`#`Pl5c0bqEgz)IZR+*gSC*-tJhS{#;k=z= zAeo;7>#^%2BEFj&=+{@aA$g?VzddJyGII`vZ;{>z=AV}9|30++uVvcU#PmN(T<~{S zFEAr2kICnLlZ}ercF8+Rs0H6K~MP?TK9- zt}aeEN?KaT{a%k4WVLz126Hs?TxcN!xvzQajRhuUVJME)bCbz0lQ+?P5(N^&kO%s`$ z+-fnXFdb1FlxhWt5MDT%1iy~uA1!Odv$DJTG_HB-!KzEU$p&(Cm7f3oC4TR;Trz%} z)9?RiQ2+NYA#7r5Vf+6Y{z+)8yOw)s@%g+jNGRe7LDMx-b{KN&(y`kfOKvT_3cdkSL&Pv3BRW?|>AC zWZmGCZR~3()j2bTxO07I`~o`$9H~DKDCWi&V!V_2w;jYa9`9Ds&LzR$9ei|qJD?{O zluzFfZp80~tZtkEQB&Wr@SlIL#St@Z%z?IGw(EfK5ey-+A-CUty#I#s!yJgc-XnEK z9%khpj4OG$jtVi;*bgW04LC|YDyh8mfa8PNKKjwwI|2nqZ}|*nq*qRs;)~Tg?){t; zqQ>&B*_-l9Ns(Z|X@=Wc^pB}0d;L}u%E`_JuuABpadO<^Y~cwz);u24^0Lti0EyX1 zRLppwsj?7-ao%x2)|bxQk4UkOmAC#HPO~T14Ba&Z#3bgN>Y`H88!b)>KA}#q>$!- zqPm*bn_9PQi*+Q9$ggh($ef_C$(~-DmRo*7L_?YG5G-t_* z&5=Ow5GKuwn^J*0NNR}ERndR7=T+D3sv=Hds))B(Zk(2Am4!jvIN7(#R^ ztOPI>@2O-i+`ygB-e6ZFE!T>Nn?Fa#D6vnH?K?~Fa^fxB-g1JwtOsSdIPYX|w$J7n zvC(H8BdY71I%@sGKU%=TMFrGHn-dC(+~ENtaIBYbI5$C)44ViOm`LZV`&dn+h%;i! zYU6$?N!ONDKG>`XGyT$vwf0aRhHF*GwV4^iF00(bwisv4jEW-L-D@B#lQ3vSH}MGS z=S;U3gUtqxqIUL)jM>_Cqq&RXchYbWO6Ho|XG}j)k57OW6(Kz%`xDQ*HYUC%BW{`U zpk0khO#Ew&IR>evDv>;h*ilt~a{cx~(yX3NL^YkVc@TAZ-PR<5(F8JO5V#)HQbl8c z=A^KtH3V0RolZlwCl?CrZZv9Zj}{vt@+8d!QN6-h#0;wxeh>X1F5np=bN;$HhR;wF z5EbKgO$RqPS3Y}#|5>=_nXB$P91&*(vu+NjWC4qI? zQBli_RNRz~E#K6$+K1**X-rB%yryVCUdhw&8_R(~)$<}0X7Zsjyj2@|D|b(e?-QAC zN9c*?Czg1t){P`{gebBczCY~GucOiaBfo%)+yYMNDhZ2Shg<*Ml#F=3F4$Q?0zXlq zWkb@Wl7$s7m}1XgIb8R5aLDEmm~Aw0Ft+_B>Xp)x6943;d%%PR6`T7shzClLGHu?c zv0qmju01V+oL_?K!u_9)yiQgg58yxbRqN{A3@C35(|>)0vh85jG`X}p4O}^N0p--L zgrRNSkzJElh?h*3MIrU>zsj1~RUT8P!p?XYyhHcdCzIRz@rthTPOK$YgApsKB6ERC z4pP^4WH#rt=&tHhg5MEw=>0~Mx^S&TrOj$g#yj1`coL5{oL{tmfDkvcj@f!=M^#e2 zHRg^7f|L*_Uq_}M>GT_CVVjsTIS3zesAWGnD@bx=yaGPEdD&7*YM6{E&72b+L z9MiL9pY(!+8>eS80To(K0H^TFUqU%SI^+=1yJ?^tM|?9{JvsyGm6kN##AZrM1#ij# zDlHFV5|T<7^~V6DIHjJm`fO`V?ZWKO0oRbdA#nso&y z49cV0y{x&YEauT!x%ktzvZDM>Ngwlt)PL{m;|NrB!o_oKB_T2YY|v&GvpZ96E3mZ0 zCDoGAUz6k{gH>cQA+NdCfkzaIQ*?$Hb68hCTpV95#PV^(F1)$(2#tmPQJp5@-#q@TtmroL$ux_wFa zU~?k$t0X=u>oK@Dn}ygB8(5@n>Z&c<#ii+@AE>US-TTBJR53yYxNlVCbq!{~XE4W0 z*G-DnM#pCy=aw{&*PPfMxmOX;ug;~#V%{KAGX&gXL!C0HExi*s3OQG1e6cAeMU(IF zY0q>5A*EI0GfRncJ#zOy5lK|DeLW~Y#Du>X1xR*1UL!4zGzLFwDBAbbdgUze=;%E~ z%8sYS@AVu<`tXH&-i!vKk`v4yjRo$de95|sW^ zD-WPstJe}%l@}Pe&7;xD%io0{z=kA4d>1DmIaWG>mojiOotK5`e&+LL{rrLApBw&q z9?P^zIgacsWSG90#__c2bhV!S`TFs|rHBb=py4#gz%&Plz*;gF#v6dJ$*hkN1tOt< z!9^c#=bCT3!lMtdFl7fva)FbfUP#1ig4|v&k3^8DgC61Y73^*u8&(f#J^;Q z9j!h0WS!pHt^QMw+?FkWsg0{F8I29AbjH+N;ZSHzcyiEKHWs&LIgZkdy8b9vzUnVO zmu-=0=JKEmev~L+=5=H$z3cBEijKd-2oRo!N86|#U?XmcKl){BYXCiuZhAccRQIq= zDRkqV%&cUT`hJz}q+7^WPj8fmt)FPFAD`DXF`dg3JiAweSCP9*7uGr^B=;sRx*>x{ zg3;@Zj9|S)2azJlJ>Zv2?Vq4kZ*vMwvJSS<%m{O z_3{*@dTbTnBHOA{jEEJeq&uBh#VXQ{iFxpd@^=>(OELCHs>WCAVwRRz`cZi#BZY^2>W^O2%Qj@7Amfa}JR&Fc0$)<(gVv z2DU3o->?AyGj+PGUe6vcJ6Rr9j(^k zlj86!#{Bra1#kGFsx#eGx$4gu<#;=>gRg z4ui>ZBi329^9UF;+^@iuj~BvP7H1Iuni~seob~({@fIckTwfIT$4w984m* zVDg|`mkWW-|j}?{~t2wF)9UcY%nsYJ^7>(9v?2jgcovIV)#Uo7L z)Vkd@+;`4M&(oRiwihfmqqkk%2C(4~WH2@|@m5!n{EkA2er!HX4=vQOChos))Dh9d z2GnlRCVBh-?a_sAVX=;F!7f7_ox(|MMhnknSA&kN$R)rt3hrpXXMkJu&Lip~#M43X zb*)_3AOHc+w3P6m&Tbk0>ZAI;d`U9?o!9(LmprQ+zqyXGg&4J+ibaY4| zW$+{Gxz4{wfbbmyZ*BFYDc>fG`rVMr4E+qByQ%}zFX*bRo15X6qFfAi`>}cAW9e>$+ zHjuL7YW=t?4QkR@-jagr{bp$_csPl0%rdEpU5Q03*g7>NrK}ok+mdLF!9(42I1G;K zt%@6lJ0N~vDUJtq+gpyMAsC#wgXSoRMRN-LU?rBrH@m{?Me%!5+AKNOB)QJk5lRLl ze#9Ij-aD4hoPDA$`m`4WH}($69XR8qs?O|Q%#_n(f^(`&dRnAV^&v|CiDZXoBCFu$ z*0Z29|DC00IfLlMb_&=@>Cop`O@E{@%vkGnqur7Uk;1X_r(PIWaobHQ2mT$VTg*;m z{QISNciJNg4=ZLgm0A1{%DM-Tkapx414n#dN7@A^qB5zw>FN>MsUKi79%>YV1|?8SG4_apYfmhq`xS z%QVe=5szzXk2U&%(yZ1R{Pib-rJvz>1O6iG8+RD%WR?n(S%-O2i|Z( z@yc~?_JZaR$8O6ox#Lgo(OUj2ksjI8Xs3WhFtc2)^E=~!g@*ntN=;LR;}ZI6A2la; zx^HgQVLgZU>B!QvakDSYqgD}mBDyP}CDyChS(8ofgOL1lm0;Q#t#t$MdhO59ThfP^ zT)oRfNM9KCgh5H~NuE5*EP>latf`k@LXTy5qCJE!xU!aVD!v$R%%$i9RYl(hDG^`{ zmvbp~esXal4xQnqs~Og+O-e7c`Wqq45{v9}?CgQfx{ox!W5TbAR~X&zXz~-{>b$3v z5qtf(?muV7(ch5+ci=!k#@{)b|3454Av=2yV~hXcSx2jCxS^^be%dmnUBc25q7=Xr zSO~Mgk`$Dd3J8k_fRiK20D-hR7hjRckZlOLA&}U%Zg<1bMM7Y=8HTZo{LA^7z1$<`Sm#N~S^^14l3C6HQ+*P>U(6ujjd9Jc+5GrrOc` zz>y8`Mo%+qfle{VhSn327{o{O!s46y8_v;+;zrq;!S%GTr+Y57&AVQ+{R0i5d^x9A z$UPOrBPc$W$~|hBcWM_3U9R3eLX59!8w+e2dVq&*$)pX~si7l^M|8-M38ykZn>IIf z?hZuBXOrrAuIb$1M_m@pOTf>|q6IZ@4U9vYEe$+ac4_+k*1Jc(l{s%N>Zo(eIe}JC!@tcPCCur8Jx#vJ1n7+N%So-Bt9nZ8_)WZHAW) z*wH2o{n4}G)pS`5IzpE0g}2XbLaY*=;IoXh8pts7cU(I2wq@Y#c5L8$S|tEn?rQu8 zDg@5_pV|Cb*$Ao-%F~V8j2mtvEa7Ub-y`d&-laRl-qJTJa-sn8XXQRKY~Eo7Fg^2U zWWC8s>_w63L#4UDwS5HW30V*)CG5@(ByBa@sUb{vE{2kTrA&^CgQ^jeVjP+eVE`d3}SHyY#1zy&!Ip)v6-@#h^lyA*#Hc=k!Enp$wgJXLX4AvjmjtV*JV0TupzK<(J$rKEgxBoGX(TcXzno}TimZ;B z^*V;=*mf=LT8{MH5xmkxQ?4#IZ;f!7Uaaxa8+LXMS5pHz*{tT7%_yCf&D_DoasFi; z7J>vgbJ5n2V5?gGGg49R*+7LlLuM33UmURW(iLNIKx+ZMSRZd(CrsH&W$5y`xbxTEeV3r-XR2YE){V zFiw=5ExNIdx;vbU3zoBuBR)kgIWvRlDIXi1Dn*wbH%K%Gr5%ey6+=(Z|E)WBy<;w{ z+=TOYq~VMD6rO|+EvfCjLGkgYM-Qk*>+uVy?X@6%qR$x@+%zpd;{|O=q;HygS7Q5d z?OYK|l1UoF?G4fwDwIu@B!n{^7WM?Z5@VO-!I4epPkpC;Gxbfd?%)feALh*q&&d*G zOfvB_(@&^9;KP}wcub@}q6+S0T?Rs!6hq~6WT(tTRb>qXTs^R0yyltX(3IG7G>f7{ z#IBt@LmEj*OkA)$9dE4J9>Ev(!4gWP=yvSsU}=S$SYT-~aS7>HS;9ALwzduZf6lBT z8QD;&4l!LWD$r*|6t!06@tvf|8TyEMll}g6J9HdJs4}c~@s37MjKbtX!F`taCnEH& zdmpq;hsyrBhCEgfQe*<-$VkLQ#}?2=;-s8~Y(^Lhwj5l9S@dmdqKTwlZ}$(gKkoWU zZyR_v|LoPdA8NztG5qOUaP)Cy`~rdi3HCO6M@$qsJRrMHPLfT;mz!R)A$=w@oh6y% zE#TdFx~$Ye^(%a~`EYqGrrn|vS3A2rqu&G%*W-ea#&{7Ly|TMAih8+JI-igsNIiJo z88bT5UxiZgx;#*92G=-=MM^_R%Ko7FgK-wuitF=G55la1NyY_=TWXdY!q+}qEOrpR zlRtDoN;xl-LA<6{p+4n!Lp3lXa4$E<74_ru-%#(~eW>ZZ@4Ykmdwk>nd++@3KcfHI zJ59e6JO5(_DsL#EsG)w@09*f|BS5M|uYie&76_w#6q2X@nHNm<8?kmqvtx9VB+|fc zeFNwdYwEs;_r59XW;6|()1{c#wK&$t<||otdPU}0`T~&M@r`QoJIdVRd3wK@uIV9+ zLOLH{2+L4_)z2IRjntyC9kz$a5w%ajBU6zUVZbZeO2f<-A7+T0R`$jh!mt%(7(U~s z?g=9R;Al2<>V@gYFBMT-8l*9*Den`hn;d9@J{dhDpGCFh?NX!ZQOoO;Fj%Ps1yoNI z*Vz=(r0sqL1%y#*)7Oebst%&Wn53Xm;OuK9$_mif!k7)$aXTKjnye(di3zYfxX1{s zHL^&oWz|{N$*+yUkelsel>*Q7dn*3Ato4pvhvU=k*8(uS3rNvsu3MpP>N&Mlv^(C`sV3Regr*o!LV%-47C zU$94$fK$894grmnYOOSYOi|&UxrW21YUN7M)s&T!JDg*F4a=s6>6-aH&jau&)T*|< z+>1VaEyr;`PQLK$XAoocj${N&DO8fgQYnx}r<5Cu$Y8RjXH{vSI`ln+2Im0UNV0WT zHqNG+Z?UW{ISQ6#)Hd)6G9#D{$55940W1P$7L&lNLX93Q)X9__f;@&zV@<_gl%d$# zPRpZnu360{ndTsE8^8wc6BH4!`4(b?^4^-Wcd_=#2&Yx6A`Yj*{dfB}-L~`H-y?Jc zm8A?<+>_^f#IPxn7$sMHa`f3rYy~P8G*-B^<$dJv7HV1#qf;3LXQjyw75nNUqZnMY zOgjrL$Ngdo`34al4iQa*<*!+bd-Q%Z2_MWd@pki`)X22t+_Vsou1Xx*+|MJ#r$*Q3 z!5OXFtI>xo+=E#I<%<4aXxdgu$51LWkna;bSmwvr$mAbn>@$1m3J$RfwW($?-q4K^ zJDwUAnj%uEzPxwPA)CS%jqBx-8Q5XEmQACN!GCdCV(iP;2?TCHh7X5lH$wPW+NJt4 zCOYZ`qdSb<4@{q4PL9T6)}cZaqu%TLU84WwYH;&AVVDbrZE=4DKd-z|%YgXFJX=Aa z;v$4@kVCKaUVrxzDt6J(N&<4@nmo!s(BU$v-@(r^61APz(rA_Lze zyw=y2S~HoC2U94q^9uF#N$ddp<+a}Cy$<=6Gwg8_X(u_-mBW< zcQ+!}-Ax zMITw2op#@98uLFU4=Mf+!m<7TFtd|1y!4e1lD@JgNS;g`35^N1uN{GqZiz4{E%}iI z1LA{ngHqIwNt{r?$(R8Xppd7wRSTLMyw+uO&Qel(WjY&+&;l~lk6;}>=imIf3)hya zj>kG3t*1O!n+~0gt+ppwd_YjG-^5Gz)%so56UWvQ>6ZIl+tH3t);)OK5K0mIZ$72# zBj{|FYh|E8x>p$JY*l;BJ}fXH=qW1qq27ic(k>D?N(`0Tk1Z{f7k3PdQ%4LLF)hd?C;e}-o<$~1-iSb0($c1`YrNI4dPd|=Z5O7*0)9R ztcCXC2HuUqpTtzvzm@Ua9rLBX3&HtWkp3V?=4-wy#`#eP?V&LE)!^?3rBAA>c%1;` z8<9i#+&1>EM*18)^*K2(PUdT|t44K&hVo^*%jf)>1Ffq}`!(KM@x!_o1zZ;9+pF zIKl?FG~(;0f!$_(%eC&2K5-u!jjjF%s&b?z<`wj#jJ)}WI+l3J%(@0Fftih&oan)` zmT%eAI6Xu1g~zJIC|uWnoiH_CGJ)G?#x~Np{$kX;lH62`vXVUQvY88h^+f1IU6u43 zG`~`rMF2t6@h45)^*632m@3UI-c{`Cqz|P?QW>z!=mNhN327;A0f07sV$-^Ce3l0> zx=1Xn_+CVjl4}FEGnF-EDvQ6_06n*aX(1SGWAb{fptQom zZdbG!a+9*bZ^ZLke5F)TdS?wItk%Pb&E(bn8|#=jn8=;prLJZsBk&T4e~^w9h0`^2 zr1jI!x0&N5kV&hIK?~>4qO<8NRwZCsRD{PUFA3QaF|4P!PMdeL{Jd;dT2W^bm<{n+ zzPwZ`3WOlOQBQpTYkHDIxBI-3a}qNXa@biLt#{GBTmU9tUbnLNGg2%|oA3I|ghQg* zCgR>BTV17gLHWJWTv38c9QEcL!CK<6p?Bk)W>HeRxP!J613`0yz$#C#Pk@1C{uZUb zpAfg1;Wsh*rJ{XHfEVifkI$KYE{7mS`rMdcuNyj;Crb7RH?7v6p>SzdquiZa{a)9< zx68*RT%-=ilR|=MH3(o<7@#jTN@RaRwd)%wk;IFe0u(wzN%1eGiZAS4?MRShPseWZ zNF(>DI0evQ(52IrL$qy1ku}P3%4xhqsuL{B3_@by%1N6POGw6P%2E!JwE;yeBTWHm zFSEK!Tk{2)m2oZcQtT@jMvNkWcxiP9>J_~HI_XwEv?($`dV{e?mScymt^Ua`(zm_Y z+H`S{0s|Xb15vf`4%Yrc05SHi7>xyL@<9LS|HIfjb!Qf6+oBcQcEz?`v2EM7lZtKI zw(aDLZQFJ#JXxo;b>Gh3_Xo_kImhgyj}GeTgeAv9QuZ-yA=?(?>Z-<~@L##Zd88M` zYXc{Dd3gp>UK43)@koz0&d<@nHxYL1Q^}_y+I_ zK^+$XS8)bdkZ$p@LOn&qu?d%=knfc9g-t~wg?08;0DQF62f?&OS>%yRSdW_9gaYpL z(-I++k9aknOd>BcGmezqX>pFhTXzoV)jZu^k=WjKsYPbuuMDEPdggXx6 zzKo_rS=`3MtA>pP-g%2L?jk@!nDbEwgw)R^O&Th-Rk+N=nIxr&8275x#YVi9RH1eL z$2^w-GM5@5Tzx;bAJ#>ndBYQ;SqJ1bJEzy4&e8`|)WLF0dS zeWl+SyA3^EB?rr8u*LqpG86$KOSD#G#n6+SDlyiJfcrDWqR2UQf^mFqlTQXi)<$zk zp==%Q!;vya4Oi>dw74rG2IDY^W>$q4rPQCu`AyNfe^8@x=tKPw+O^_plHjn7&nDL3 z6)yL*5OVC5Tvujk zwE}pB$}`%&gg&;OxFr#r2Y=i!9f{JJ=*L%5lynmt69^ri$;Mf!zuHlK&4ySm-_1>-#7%2)4NiMG9uif!=|% z$J-B;O@I1Tduqb(+t=$aAxyN_6ASsLo*2sW-lcdf{*JOJ)xb)nU1lYD z`QBVbE5f7LemayUU#EK92is7hPW)>cM8Q!{q2olwn6Bcs(_DCz+7hZp4|{^eNp_nD z=)uso578yf;v4+~L)z`Do=fOML>Aw8sgoU-$Ec4BgtAKQQhe>_40zZ@YVwwRZSsJg3p##~j3ZT+{BU?Auq-FYd&8ywk6;c2jCG%-bi? z-WT>X^CvOP_r-$_;PhJFc1V0fOKQ6Zu&Zi5=-#4P0`b7PzoDgwh@6pBMt%srPTpN*@6nAhXb7dQ;J3iWAS~oLCXk@z?;|*@5 z(U&Y;4NqhpI*dimx_-K6e}R&Twhg0Q%(d%>ry0u`qsK3HS(gMQGh$>4@nA z3%roJTaN4FNjD(Eam}KJkL%RRX~TN-Hw#eNy!m0B>LT2j>>+L0()LwSI@dA86kCEJ zyhEko$0}F;Wl*b7`4h!O&{PM$ptl4<8iFCmSO)iKDTTw^G8nctVVkAL-RASyj7D{b z=~hoftHoNUklPlFx`uAmPo|&?Hjl)MpWHQ9AtOcuBO?hHak#tC2%)5w^Rh6mCCq_y zB|D#Z+cpIiu9>JfhvrtCMo7Ou1Yd|IuSlP7Mw7#lRo$s|Nc<+u|2VbACMKKp_F&w> z2Hnxph5_Zw(q4)}Q z+x}|gl#nwFON3@F`l{_~ zc_G+gv5v^*nC6&ODkWnxdh?q)3|FNiqZm>HK36;NFN=POcBDr`z<8~2;O1Y}258y_ z>}*GrrFUF>rzN9HNoVpL#AEcxeGWEvF}1=yEem)<-BCR?3pSp}7NX@gG$!X^e0$|@ zf5n%N@>X5w^2FYtXFx(+zDBzRV!na%<>6dM``j+LiU(vXYs#xCc3_)=jvfkCISaOW zWONDL5}62xqBnd`5~Xc}vtY3<96oDN!UyHugojx<%iQG?ODEPsF&N?6Us6Yy6sK(p zoO<2$Itey|Q0L!Ntwy=l{ePYJ4b~!*wE5{a&Jt!$uE9k{Hp9j)YEJCdvQCt958@LFMG}m@ zHa8Qk131t55~h~^kUH-NQIr!(%AgjMrh&vta#HU+GhO;_>kxLP>v+{^bfk+YTq5JN zJnsIzG$9+dmwt9o10GBmSULRFLuuiy*YFzt*r;K8=fyds>LI*5x;0OzutxYYj_;BB zIPQa-ScshJHo@!2Z*~(OdI;npjh{5q&P7ZRXLb~LpK)q(BA2~!dGHPKpZtp}{ZT!c zpBq&M{{O_ak^k>2s;kp~^&WoSN=s66HpXR9%ba;lg_;|Z z)at@_@m(eP7P@1x_ePl=xnCLko6fFWSz#c;>j8UJ_b@n*WGTw!N-ja`axZ-evLMZw5mdpq5_61*lsjUbBF4S~%wdW+q;NV^f*i z1ICi2dqxkXqOo$lo29$bAAR8j`@T6>X7vaZ?uZcXoTDWD`rz+qXG0oDi!57piYaH4m&FOXa# z5|n#0-_%OAmr)2(glDt;B+kZqsaW@us9i1kb7+7;x9p$$CowfFQR%*=E`^JgE<#$| z+m;cce*3>IS0sg@3d@B4Su%HdvgY-weMoGNv>mYuqCp-qz>c}-(QM#C9e;928O+^1 zrUpJdll0+<@h>75NW@}=qr(2!rlP|(hu~BtA6)8lU~-3g-zis>2t9@51|6{{cGKQ% z!+917ZS?JvF5|_{Nn5P$FT5KH5aSk$D90|9`cU0wU82GyLoS-GTfeX{5~pGrd!$l)hf7^Pys~Moe?FOsy_}!m!FAYK$fZek)a^BPl+aXz)r}IBNn)nOhFsphcm9H}ReA5vQCL<;9feNqr|Qqn1P0EpXK z;z>C9H&m(8#X<;uAtgm%+#yT-EBx~`;+b6jedIt-=2J$yz2T-vql=WreOC`&X^r(! z5wxQG0aaV+4&tZk0JSXPt~9K7tA^%xfcTNUaK=Htti`i%*U}d?nb1-|Eia9wRbdAO zaP~Vp*01VZ^wyK~dHkDH@e1)Zc8G`eJY=X$YE&2QY)H%L%A2s*-{xQEJ9EM^8 z>7rVrI(Wb1$@XqTG6YO?yE<-+;#OHZ>#8u%($`NDos)ks5p0+quQ&SSObe{U*fw$9 zS9NE7STlpF!D5V*w$Q~F5VX@|JriUx&{a?HcNq@HMX!pkvSr@k@Bwd`HGK#2tM1)NPE>;cJOoG{#y~0B`={ z2qW9WBsT5w#WRj7m$4tlIuZB|G^uVb5?i9ud80aTW22P>UU_3r?!-X7ibKSEmcxg5 z;aZRe3gIcU6k45j`{IkF(?KzzIu7(EvQ2QL|aD{U9|cW zh0lF)Rlf9a_U+Bt775+hN>SEOBNi7+A*)(f)b%JWp055Zrz)L~SBp%Z`4|REfoWTo zLzC-K#(@@f$~=D_ZD>kQ909^`D@`cchWhoc$stgH8RrG&cr_lIUOIZwD(yg|Je~{Q zsiR!{3sW&ZS77S`kN}T&IR6J{`X~aO_l%$l?4@J zd^!j9@Nd+dqw7*)VBdm=U6OT3ZqyC+#9833~f%2oA1gd@5O;@-Q%Fdj*%}2O{77)nm%sp@(WVb&2%OXK{>A12* zb`_OEHgi>tB+OE|V5pBoc}0bjiXp6>*Ib4-3~z5H@#ktS9FIC$vmFTl<;(8lw1vJm zn@%w2cl&h&<_t$##SvbNT5M8t1ht4E4pk+dX8;);`lA1AOH-LFeNfco(0q^2v3b9z zS&Ei9X4}y)b1f=cZOF;JmYryN>2e(kG7_v*R))^{_)?Y*0NGc$E8+D0&6lUGX#I~3 zqrzsmMNtdule4AaL4=0P6VF&XmS^+NT035&1F^}G3{liifu6yPM%_W z^!>A|^#I;#1UIFd+rH(d2)Wzb_13CCukg!0-=>hC;L9H3^)S+#n0!^%u~2 z3_%f}b=X^V=;(e?TJWGDA3hQ*hhPc;+Qlh>>95#GiX6n$0|^JT9Apr8&C4NXLxLPM zh}$f2#ZVvEnZ!`~I5+w=)Gq1mZo|x&73*R5Y##4Hwp{Eky8CI_p5zE zJwZfgsK{P;6K?q&JQ2B|hJ$iNveaF>vcl;Jy(t~`*KSIAQ1nD! z9rqv2Mp8}oPf)gnvZmIq#-@hUkbHrrTGDdss$WyE1aN$eBFcQT+d__e|GxfT^E&P( zVyXbtuU}{={}U?v-#vIjs!H+(PX9$_sZj39OIRVjnL(4rn7jN2JA?QQ4L4rDpo|S9 zAP4!RZ4>+@$R?!+=;*>mOPchTS|XZ*m#NT_gRq0vEd>@eE8A{5TP&-Wb#C98B|xQp z#s?pIUUHnSHNL*HCc8^#w%u^+#YgZlz=^qm0vVJTrQ#2SYhXM^S2EWkIN>K<^mAb7 zjJXx^=$s9EI!1#*Y3%zBh6FKS(K+fz!-vZP@4S5$Q&R5^B?@^K<`PN6q~ zk(16<(g$vaBrzbgj)eRC9U-W+Pitx43CqfqU-8td2ZJ8h>Rj>WDybkU@YId^_bTCM z;J}H|k)2dME4$Ny>_jY%yTnKJ6u6cH8s~A~%Y0d{GQA=e%*R9#9{F0a!!&e5|Fu#3G=C}Lz%_{j#_Xo>ixmeu_jYQx1xU> z>L~hI@1R1(>D!XEwUg6Ppn?AOC9OmWoWW0Ylj0WYnKB{ojEp!ct(k+6%uJvx(LB9NTGxzK7Wu_n@e-HLDabl0%ro+#hh9P zqt1}hv;51C5_|Jccy?FAR66}uoRxhpn9mG2;~^Yf73W*kSme5b}M=+)_ftkg-D zy)d0=)+9&%;DBUTiiVhtbuA4GH3opi_ex6)KoLQU1e4ZaJ|T1KtKR=NH8;zGO^fXX z3}8a9e*Rg+*SgEytD3*cEWOl?u<-R$Al$U>t88>Q_JT0VT`1l@o?r2qAD+<5DP%SD zi?D8X00T1Q3I;svxX$;NSg|Qr-{;2JM-BA2U_a~IN@0&eSM4ND#w0UAY8G!C)=fs% zlMxKeDq1lYCmjt=_v?!j!(a5Uxx~pzOy0>Sds#HP!Wmt0KHL-StGgB9Ju& zu7vC&lr;^mM4cj-HIGDoDR5?~mw}`3tGJ)|JQGe=ZO8ETuV-&R;ZrrZTbZB9ZOI#3pxt6Go4f2MPGIN~ z1Sa;AKw#@qFRQ!wCwCzEQmYf?`3{bESx=x&gi$WkbruHuf3 zy{Zoafx?cJy{1o4zQPJ-S4E8p#&TtN7>dPF4P);)-v}+o(4ZrBc3O_BVwR z#ZS!AlCRAEh4Ybi=cgUGZFzo!+n6^3aQd=bWAP<9M&)y6>EbsF*L>d)B?bP8>Pp|3 zaz*|b+5%sHopQay6#3pE#7ezmbk$y>OqE)ug7X!37&eT(9!mDvAYgGb?<-UE0^ufF`vN><<#&aL51%e9(s0@l3vIU&fSah~M;?)9&otfneb`e6QfaqL`dL?&Z zyvIfROIsM5+s~gCeiNck_d3VNJoutr@7ds&t^O6NF>BOprWcv$&W@tuzm(_C9H*t! z?E(DfMq{cH))l_z{bz{PuisK7>^pv&!&f)P??N=~MPE~n0Jr}TWbPIvvP?fvOb+pX zf?`zvD?uh~Vr}wYPgJ*>mpkeYN0xngd3|Z>P6{qj$U$V-ux3n2v3y%c2pSdlmqb1Q zwR3FRR+OFF!7U}U;K@It;MEtj46HnQiO;*fTrsd2eQ{m&qOuuXuesXh`_$}x>Bg$J z_Hi?P%#>MU_G`g!y8C7Gf$t=T`C;BK2R{J9<&`6hbQQDD&>C64ks$SlpG}(pTP5m4 z1JwRC+sEf*GJaf0$+Mn>gb%AN!?9dGkFF%#AaNV#EQ>0Fiv z?{>3PT9M_m;4dYLN=lW&Egxl;mO48DRo2vKOogywF|t_?F!2^Qn|O6LIg2$(rJb93 zp=*iCRp8q+>p$FG5gB;Ku~*V|OH-=UqNOq&(ABxbVkoMA-YYj&_hcc_f|)iVK67D4 z52J4|{?1b9o)jl1n(Hxli$!OIBTf$&Rx%yh+$=SrL0M;AXfV`v(~Qi>AfAaOa6()! z=+<-^mv%x-N=DyH!%9zBra#O zdSD#FRL?9%qc(!iYu45aG~TOO-c;|ROuH7p4b&f_2|z^#UWu}8Rj;8bb%;w@mZ;KG zpgHR&2RzIc?0Va4$U0-R1r)27r@+(!V^FA5x?TbEgyvG53Tg`o{>49qrUQ^d zCjdVhW(S~hp<$kqROu~t8JajL8Hqg*HOuNG&nXkvWbkHGygZXW*={Lk11mm7VK2PR zYqFa$tJZ2ZDXX?FO}o zD#=*RMU~%E5B&Ad)ZY}ccEC_plAm!_Rk91#MUkebc+1>XwR_^8&ajp}9lYkQjY6M!F*rVB zs?tw?D+N}&t1=MK1uoNUMP6dcJjuSVvW-VxF)+OMi|REw4!Macs2yAV)hY$AQnBC; z(#S~lX|+MPNsl~h*4Q|aQROuHf|8q`3S%A8gZCxHAYagE`?0Akn*El{VBM@0jelG5 zN24U#zwug4a6|Em7enE$_V?wsCjd6>7zB)9Uq#@-3yffI)LsEYIKESEPYT)K8>F|Z zD>$fv5q?Az>?4+DfDV*3hs`rxs3lh=s@0!|@x{~D1z(3pZ-?RNaX;t&FwEjkdMHH* z5-+#Pe*g83T=3A(I@i_6t|fAH=_OKrKdJdp7&_76NyCXUUc#s?(vy~0IVR%V45n*<9gXXq5k)FNM@SePAeul~#`ueu=sJfYyrAwFwZ=Q?7A0_o?kt@+VwsgT zI@6!VJWN$#6(LOtZvb>w_xpW|B&#<4ZH8s%=~I=jprnx8#=5CDJAkHEWx}`s%H~q~ z^Mf!hK|7GgSQ|J3VYgzg+$~x6&b&j9PWDJ{i}aWA7uj+66t@JdjnxsMO*KzxwM%<* zN|=RBHFdUAXLCy6(5_iqh8*}e8)9vvP+%V7m00+%oLM08?7-XWQ2N6)gx+6{qpbu$ z^)MktpAlNFD+(o%p)iLut*!XS}v=pbIYy$AVQ(rzaebCMus4aP`doKqHYz+e|Ikr$+9S zLx|}?G&|m`^hPbjMuKG#cxD0(VSmcC`j)CbuwB12UB9?`G;%Q*44s!K_%=>6({IoL z+R9nFt_wTEk8aGzR$*L^rQDDHvx&D$$9ZiUt`2jTrm%ixoHWds^a-{{b2I4#FJ+M@ zK&p+gjNwKPQEm@BlRU8uA^ae*!_56t4;&9X{g_{t&hD0YZjv@R>jKia4(2>+)VHwA zaP@x!qh#SX5r?W#d*+>vsdp^a zj#-rh?vMQ~%Fh(g%W$BFwJ|bND$J15HPw84;KFpWzB5BfUpe~IjskB)MV~Xsp^zj1 zPkuer29h?fp~@LXk87-5N1)_Rc{M@;qcIRhD z*;j6|;K(s0DtDr@b_VO1)?Wcp$1CRypdfnR=2N>7woa=6$TUy3NFu2&X#$qlkKcSi z;)-wuLDJ&Y6uH+E>SzP;;Gtd+49eAM__43>-W^)PmSraoNq09uSm~>#(T}lA>Z8kE zCUN?(ktQl|iDnE z&SyU*c%&@hV14@4s=tf!dgm53$lq?}9Rc|j{O^@L1=)Z!Ss%{>ksNAcEHqRcaDcj7 z`~6$DP_aws;Fg`L&@n^MY>tv8S6NePp)Ar=K44nEnzbo-WQ0{&YJ)<$lS1&_oQzkz z@szTJQ~IP%#OVxjst_Ul-AMCKt|BpBaWJWHq$E{Y@J4N#&Jdf_{!E`Q)#3y>f32?U z2WR!(U>xsEUj9&cL@m#ZmdF+Ni#5LOson?d5liH5OJ>ELT@7&o6RFH}>gxWSs%) zBveabC+_Z%)nlV|=>XB|{Jm>JK3bfXxao7&3}&bXXf%Q2Esja(MAGPl(Kf-aEO>5? zGp3FPzt7LMo6{`s>8{p(i<`u_x& z|99^42QdE>hyB;Qp|Yc-C4&0J)+=EbDK9CbbqS^!OoCXfPFqb8r)(i40O?W|<0+A1 z|CBIsXd4&9_gcuz_Yb1U?rmPoL^KgA-D1ZXz%TiJB_l{_3>ceSYdrBjx#Zkg>;8AL z!=L**jL{o)1gxmT9{&sz@My{tAq`vWrr<*y!$7vr5lO8nZFy&ks&>E-7qLg%-BTUC z(!_=~_{4#-6}F#^SM&StDpP+-rk^DWdUeDB$*>1so-|^=# zM5lg<<&(J34NTC|X+tx0DWLg!7WuAd{2Z2-n7(9IL7|;Gl2t^Vr}d}T zVBD2D=Z~6-Z9DfoLS$`Qv!%j0A`me(o=UQ#wpjr^b!%mVIi&`ZJyMB3P!|zH;uJ0I z$+0PPdljcCI$N=ZWk~w?eGiLG?7Qn`n?;Q$-ybTAbu>ANN*3E)vTY1Z*UF=)W*ani z6VdjX1Cy$V@yTWDQfK*^K2Bs~O-Yq2mli|YB_5L+sYD+H?AKop9Zg!`w#0V&0+HOK zFpuxX9IC}x8V2UYJX#y8an`RNmLkk%RINH_4-*BBl`m_%L@BV|VJ0Bd>d#oegXWYT zyF;XaOE*Yn=4uR?*+4%=;`n{QC1dFBiBO(WM7=T;LkK4Z3E}7{qV}0$xGX+bG2mGgWhzumsXv zkLd{lc&6TAhiis@h*p!1+2zkcFdvopjNRC_K3@Le4dh33j!)2vC-J5*P8jbJfU5(4 zzqAD1FNj*^YKS<>{E{!K8C>=`r=qa)%p+VAkM|1IYmBYvg+e&D0uCkcm?EMeURP( zKqYO*pmC5~{TR$w0qwxkyE5J+QWV2ND?uf&mGNLGNo3 zTUKJavochfM+Y9>dhm ztS_IUJ65u_4QQX-U9IO=JU@P1=arEj(J}~z2og1({~Mt*Rp@-x^;5Hw_hak&e_Og} z|9@=J_9nK*N+!<#6`T0jqncrT^LCD1ZEqhVE5d8!89)^UfjW8vp8p&YqxRn#1pZcD zx4mXNJl(qT=!B4{Y*AS+m`6aPDW*k7Q?g2S$b(>2()=8$cWLsK%YF+zD8oDBh>3dY zeDZjqbCc)@OCNi`e)s;$*?IS%?|!<9jH`#-S)7fYg5Itb7&vB7%~NC15^hvs*$6W1 zH0R6PB}4PUX1SEV69D686|UD{=~VU>AGE!kvuEb3GORtdD-ZoH?IP;3i{52ZhkhFr zCn`1ow}t~*E!CHYoyXR!(_?9+9yK=~Hbv8zJ5lB+n6Y|=geHop>|2=iFEIBW0ilAA z@D(4fi{Mt?q!cAUn;Jp&*6!B{D!V|1k$49<1Fjo+Q)f3jcewP2BXzk@b}YzwOY0J5 z)f>-cItOUZHG+Lw)E=y=ps2|5RnD~6wPfNpFfK_JtKAgYHl9kHo|g?J-a+1RekK>TD2C+TFN7zwfJVOTw=^%s4RFZjO66*m2l(-bn(IiHw_$)AzE1o+~?` zt$XZH-mh;7)llTpe^ZGmUlMX_JYtr#7*JT8bT=g)tT**g5yBRZOmDQK7M>$-o~Z}F z*awX9oV&BvtT+UkBNu2;W^_8l#>nj^2DSUouAnWXE3>j1JZa8MuBKe1%TBYYwX5u_ zX3FMsq3^0?x&o%xIcFx(*SdDt)+GOO3!kQA4&%rPbH=gzhxMszdsGAPCmLNgBj3}Q zN3O;-G_?9Zx!@0!p!uo~m^lVA0?)L^IZw~se<7T^Ln2VWR>jQhJp?UR%5?-3a>eYy zaN+kmfW@A3_>Vw##1dV-nsVWfpcITJa`jNmNpPkTfVlc2ZkwPv z^2nxf0qzOIfuj8=5v}B%$7q^%7e zdPOZZF<~|GFqZIZ=#=!nQE3wHYv%ML;q4%DoS7!#1K z4+QIa^~klRpob8w>TVUiZTb3)THn!gv3-Nz*m=(+!%8;mXIE@X_=&Guvwc|2q11xw z%*iGdUN!dWAKL)4OS9LJ&vT0)6TLUV9dq)`4sK5`r=zw-BmrkD3J-{?bQaH6#| zA-|>6j~c#p>kH9lw8EgNm*JGBk?*H)e2!Byu_KCr_6cg~JJZJw^6gHXdZ7PLi_P(1($44N^m3Ymp z!?FAsCOSo@Ijk9Je?OA}l{m~gwsL@Z3Awo3rK}FlQKwSDr07J4=%arg0BG%6u2R@X z+h470dM}J$4XLFBDILOA(+2G_ZGE#B?>2($sJ{}1f{$LpC41*@gns{g9-SFtUjNpF zH|ftf5Y91!o8Ea2%@ow$t7?5hEOWjsi-^laR7llA!Zqf-K99in7D& zHmjrcSH%>O=vW3Ar^JvMiAZU<{971*^@tu`Q=J@JZX8|DLaH(xhxOq?0eFtt@f$@M zry!Y+y}(!q9%$=l3)_@)YR;fsKx;8AlL2)|_=O56o7$OSqgx%ZJUjpcl9KmPoTw1} z-vj!{h=X$IcmlCV)g)FDEN?)tIWL^JMTL^TVD<<6?%MQOi9kQVk%nuJt1v|o&QKSk zAy?Wft5m7a|M3)=dx*RZ>(-!eC{VXB=Z|g0->J~CG^r2ODzZQBQU&)PQawp1ahfuF zP&JzHVS^IDsqhu}QW0~d$DX?LQ4x|q%rV5rLJkv!0K923M#Xe!oPoRXrlbUyBn%W& zlqD=Af+|($o-kCPCM?f}?ElqRHliZG!nK^N+-yDBzAfa0EtDFot2=;eCXd*wt-ix$?u{%)k=dMmKa$-ki7Fm?<`<__|xsW zU=I_Vd9?}i_v1WLeF@j@%{XKE<$v!sEC%#S*t~Ww#`sB2+|gU$ebK`0(o#+}5GE82 zy6bob4a^@DNt99&@ruCBb4Ezg%O^hSSf=O}m(SZ#lC8uOUa$z+mZm$BPbGAkw{!(a z|MRp=_A<}$Mrj^{Fz?}+Y#3amBq$Bz5p?*6rAd=pOnU#&r2NH4o9HJtaU{j_MXlC8 z*E{{XH2!__Kwl^G4fY=fUnM@Qmhi`cd5Z8qVUPb^;wobB|HZIeC@rd@ev8Bz8=Q(LQ4u%!)3zYOxYSHh|IRM^jPLv?yR1f@w=5=Pba0nRcD_O zES+)U=;|zwFl=Ue-E;RobdkT$^!j~-LpSZlNAPl#>~3Lt+H3biZF{L`z8Q)a=nZSa zj&e{QBta*~mwFH!nuzyfZO>GM8K?uisP;L?jDnIyJ+Ms2IDNTl_kp+7?BhuZ7<$X~ zrA44qfcpm=z)%>uO4FxITj?mx+*{$pVU^Dv_5p2b?y~ zqDDiqiNyc4V082Zv393UN-$e=j@fP?L69hG!PsrkN~t3kDL|<}Tvg%WC&$H4l0Xt? zK<=*Lk7wa!PDUS_b; zC6xvU9c!_sJn2?&V+x$9gk*Gu2nN|xa?_V{T6~1D5k(?lbuGLAjq?bS*$Y7I6=*vx z7d{#!$Z2T;2KRnTW}=eT6J-InVxOImO$3lPe??qj^$ueDPw+k*!9hq6o=M_jd?TI} zAraJtWcS%TZCNBGH>4KpPlKiFQ%q1c zy$T7``aG^>+XQH?1I3HI7T^TCN52KmM@Q(2miKc@_>9wa-1tSSoSVfvoEy7mUP=WKJ%*SDYsb7T7Gg150uCYFGE&2udJC3vw_cmVnS0j9fz<4MVE&f2=K!*2#U3)0 z5N!+~Uy9Ru0c0;snSw@V04Y0@XZFf^d`v@-{mCr2 zKu>0)yvcXT71t-KD`T|7H(pTAeG$)p*6Fc#@_m+6JQ+Wu|40-LkE0?#(aXf^A28x1 z@_|4C*F|vJK~#Arz5GmH0>HzcOeO8cMmdU*ip#{z<3viGmPwami*Ww9Xv!$$1o%wU zDZgS>MZh8L);fPyBn4c?sbG>+lPrSk-ybM%{Yzw(V-I^$XJV+Sfgwj+!t;r>lXOG}59IZnjrHG@?17vY+uVX|ACBX^SwGGqB)ruuz-TQhip zQf9k=hBiVfG?Qfq%4ru9;Pdp{0dgNk+l5^vT=sJnsEzT=>ueDDi02doZ-3;CN=g+X zq%G+MD9?!2J&LUWv%_2*l7N(7$JBfgSC3B{Ao^gRb9pp;bHl|tAwwW3%b(8cVvga@ znuWi{!fM?Epow+=fl~Vs=LfZ#M;9h6qclCwk8~oio|dxP723oU7 z&MT>hFOYE7{rwJ3qcWGnl9Bt3(A$dGUhG=D5}w#hT(KGQXn%5dDIk(V(aJ3Eo~|D zhVyjAdB{pm+fL6_9g!aiW9G=)fY>Rj*(t+YDNx+b$XB}yHj;yEN}HYXx1!ozm7<~d zi*u}WjJ1_6Bi@w@Aco%JigbosuD%fdGr|!EzxQl^+5voic%}dM`uM+(aLNCU@ND(} zXyMSl>{8NG$B6s%|Nfo;RURNQKwSaXh9qH415Nq`w|G7=DRpnpgkrXhC|I4mu3BwV zjaIq8Z3%)_t(;y~)@D@gRjFcSrPjQpdDYYQ$ZwY-9Rl?5Zz|Pmr}JggY36grZt0HhEI9wSLNjR_k<#K5bi$zF^V5>Hmoo zC+V%+^CI$2#9_C3?cssrNb_+k;x_6Gn=`=akMTi;p!M=XcN5GF`MUZ@m3khZA+3zoOpA77F*B*== z4j^aw5FShx+Qg_s9!OOj0j4 zi5l?&74ASjX8>_y!;OH54#BUAepJP+;UP2?leSB;vuE_TT#kq9KvCl&M-v-aRtH$c zqt#!cphj37SF2KJAj8dt+*PX%S<5}Tq}Rh2N>$wt$#|tBUARhTsWY#OYG_yl2}%{j z+g6ezF$)oAF2<~x&h1;QW3s&4P-BNvCppa^iQwDLny!bSovGg5$X)37Vj)yDzYW(U zn@XOMa1xEAkY9cUb}Sh-d%F^_)%vT4>IgAdf}}C5F*9yXgwCS$ zYEE+GjkIh~pe2S#=;+anv~b7$k@F#YwtNTSL9MYg=baU^au*WAUavcnzB|BSjprx4 z8qI&^4r50>N$DOT3YAYIfJSyAG@o{Q&1M9f8&&FqOb^G0=Lg`P{|FYo4K6U<#0X#K zb1Fn@J-KklxM{yr!}A;5IYRxOz2nTvXCTE0#0?Ff^b8&Z0C?lK^AIsJou|*J8bj;$ z`KTNEA+_?sb8)^G@94Wq4|ZM=Knh7&_a-1G3}il11yYOG?{SNn)kH{gUoXpI#i0JZ z-TO1$@w0EQ+yP-8nb^qSMP6vFXM)&zmmLsyL~BT$ofd2;$5WL6X;4E%sR!}pg;xlx z6_1NlJ>V5lvu`gaheSg&Gl8?guOIKLPh#R`6Er}m_a{GRq?u%rB$tmnA1NGhRp$jS zyeK4GP_W9Xj3(ScLzu+Qx3qN^w_BKue6*OhX5>|dk5?M~3gnswZ)YYXP%!-*n1+d# z6@Pf|*s@HhfmcknWz|qqT2u}`C!G`KIIOGQhzRmNW7XJHit7~^p_$4YyX&a!&@@oZ zIk{&&tB}mgE`cvmS~m7ZVjnb}WfS5H7Kw=!v0%u8Oy?U^gGAo>Q;T-_1gE}NS3B{j z!5eQrslnG-k_+|Q_6_-C0^4Hs(MoN=_0q8EJ!tL$bS9b$S@1)0L^lZE|Ov1+h=st;6ZW-Kb zjGsA)Fli8w6~@u=7k(`1F)h%khLTfPsSzvCGREEvg|GHN+ra3_KQOEO-pC~DL(6t3 zpnDm-F|d`gyWQ?w4bx1r#g@e@8cvlZrK2*FsNXzn0kpg17LG&()JBoEDHBAq+ZP>Q9YLz?`ZM#1sxbQD%ei-vUOmD&RIM;S`f3X?)+OP%i*1k8J`_=dfz@NG)?=D zU!=J?Ws?I?wNX8QUsZ>=B({cEJV2iVyL2furabE)`44z?So+p7Kv{$W#UVY-t1p6~ z6&Ka47zI^BHTkY3ktl-*s)6aCXgmOA5s{I7UB;j>)<1nFm1RjCl;L$Ft!v(Kb9@-I zX)$6fXYI{2SFzFgk8Os+lEE}s67m^5`F=OcV2o)k-ZC5O!!oO5gQ-p-MKAn1U0TBL3Wu?BUL&Ps`_)an9+ByzK|FaEd(O`9_! z#XsW{>So4SZG4*Nf+<`KTK#&?_EBPhSlbmx$)wdJM1JaKbO9(SPyC#Z4^2Yj{88sD zM}_v?L0<8&;c9PV3|H;4^gT5HW4KfP@TGzF&P&Rz|LCP7an{vQH$U}?rEQh&gsz%m z5ZbpmH$pNCK);lnR9DAW?ZVcKUhnqLDpY~3Vf!GeMwD{d{*Wf|-bYW&u#dYx$Gh>?xhxg!_$nv=G$X(S!J++s_0 zYCAe&W*cLdBMNdST*94$d)x~FKcVc2oY4bA>E+GJ&7i_^GrB@HM;{9x?xqTR}rY?kG?q>EZTfzk=H+exbD~R50_2Q`}t3vLY-AhhLqGpJY7)gb6klk5M=$x&s zLh_ZR?E)`QH+9HBh{DF+&h7dr9325Xur%dIbIQPv-meeY9c%WUCs>o1tnQlV_lP`F z`rvsTsPlkehXG|hS8!UjFdysiJ?PpJ3qNgU*)fhK2Ri+pw`GJP(eY77)8don?G}mU z(DI|Gx3a%s3wj&_dI1jlyd+u)rCTKj4k{5(R>(X(18)eF>rA10R;_5*UklI&^7kr<~x?+_}?tsYfyj*U$Ne1AyHR|(@pxJ>qlt?^AX*Cy{rIX+3ozfh2enAejSLTM-8 zo66C4B}s0Vys#7Ao>bV`tOmy=MnxZnE^XpXHD>xKiL0;;?^ajhb*qW9UO6T83@yDe zM-Np*m#sX&U`k-mimZn3JTQSPg1n4Bo4`_?PJ}A74=~mZnUMR4I6N@Z85l1!l##r% z3+)`AXr~6a%KAGC*^Cu(;o4<;JlG$ZVilW~CA5`ZiOMlZt_7oyuVYB5u_P-bUknp= zy(%I@X?Q~{PP--+a1ZJ|A#)bb*ubXGXw+3QA~uq>OiaWqi> ztlZ+fkkc~R^ie-;zWl$sz+X)OwWcef+;a(h`NL!7Md(zhg9nunog^7!6pGCi>6#uM zdxVnrrH=(-sZLLKL9}bT)=H=#*HE@b?UuloX}BxB-E;KhG5e_3at5c;p%yK!NGl>D z+>GD%kv=NgleqqP0jf2kE2bh%x_JC4hRPGhor$OCe0}x!uNmaKL4qh>yLHRPebB4!n zPqwf4w2kVe*lj?+-2e-IC^#2#N{i3ZR7fO^f*}bV)R^tSmp@MWD=Y!Vus@lhZqOcM zBxjJA7Xw->*dUHwn@a57mReLqd1AI zR*4c~;_;ofLV<4uh3mDR*;3x3ov9fl%`byL($*^|iox#=>O~NCkV(ZymRFJ1@Yw7L zqMbu)ez$&U(R%v&_$q62a?|70L*QMQth6*)0u}IX*>iVWDK^@Wd;d;!~nQ5e&MJFNt-2endP{VzW|wNMXQ%RsSH9b6=@x;v=TD!b zRIl6rU^LG1e0J}jxiT&aYjP#=@!=)$fxI z{+yA@*japtE78d40n*+(^4-uA=cbxEl#c*A-P@mwopCFwijI$(XOD{e<;|F2#V&JDM5Ru`p<=0dy5q#YF0k{89|oE@2B06o z&3hEgBs$k1Esg8)Cc!VV7u}=K2fJ6K!W|A4a|mV-gBoSbEEeYy$~2FNd6Z`)voO2x zY94Adj50Q;A08XMvqzgYX0C@Ct-LJJ&qx4+cA)i3HTEpCShblM=-j zbJ9~61iq74{EltP@$_+MsLIZB(0n`gmnR;3=9^8J1&%}yNGFaUM$0`bCT11HtC{0G zFF@J8I7Xqnj~}%~Aq6;PL?r+vC!DZnFLJhq>C3%7Na~Wpl4*gyz*x*Iz0+jRuDqLZ z<`zEA9s`_C40sHPmCu}7b!|wY-+^N3ofSt4^P=C2Fgewaq`JQ=_DItlp)Y9DS-*qc zL+u|*YIIAAs!2H&QGBN|b&QC-{rUEyLJP7IA?#gvsg-=^@YK5S;v zBwy^Ee*=4Oo0t0YC==uKaOwycCw7Tb|b4AVD#`r)BC;5p5kWlfihJ z#I!>{T&G~_5z63l*&$i%U3{a9zFm34Bbz-SV`gjQh_^LivNU95*1&}=RWyx|;37_7 z=R{&n_nhTr_4ai4CgIiXDb=^|U^l@-m0iJCcosrP%qJ4IfZGY^!6l) z>3#ysH!V@}cuH|5;q;ByNR1))zkys`&3x8}2I!Fm7!6XAIlps^bgBh4st!T{r6hY@5~oSv4H#Eob45&S&G9~w!GvBrMU`INo!HTY5KEeZz-sL%O z-$FVh)eN;qk7R`I60bC79lyzB5(=Uoyj+*V_9P@TxNz_#wh*WZQH#KZ+H=JjdE3tl zw4nZw%Y1o=6YyUuN$j-7_m}-bRPl9LM-^8u&-ML3`v6K4p2CkGttwS?*1`H<25}!t z9Tx1aZs-Hran40qBhI;zaX7GUVS4N*2p-EhqXll+SfYu)4FYm=bRZ{7P?&tAhX*&@ zm`^M`!1&a0`Y@g;Im~Aso+Eka7O4W87NG)M^LO3exg)RGUjTM&?1Ne`I}`9s(KO~l z%$h{=AKvoD8SPuL1pf9|2bwW?nC7+;#lVx(0D?9m1a#DZS@=%(X_#YRKiu-f54P5A zIG;8p3pWF~^9ytO16V#%2efRGR0b;|Sen4+WX$?^LR)Z*>cYV1?tL%+_QC8170y7% zV)0Ad;{R}FhV*ZGFoUGq%0?kWAq+}&C7zdE*kARrm=9k71H=l8So^a$%5Y=KwrFM! z?HM%8Pn3x3B*G-TD06GtRR``7KT#^Z52QtJ0}GaPEEr>Lov)2?jf;0QCkDZ1V9S9I z%$s``YxL@Y!1^ZPGru|b23QRBEH;dE!uTfm(VNRLg1(?~!uVzw2|`X+5>{(?3Xo`3V0rBnsRq zd@X*@v3T-5<_**0DbK(n#L5 z8j@B@1fYWJ^~J+K>u4A4w0roV6^1pW!>VLsV?AgLvH35Y97tkq!u1-clZr9?Ki zo(EUWkWe?OqT2|7o?s7}0TUKW(t=3KZZUiaeF-5B{T|7aBVhw80Ve?8oV&1w(qLEj zo`_=WJAK%qPzNK)QGA5p3BhL~KGyO+Af5;_Tb*7dFvhW5T_)5Wq zLTy43>WDP~x=qo#08>0U7Kq3r(fcP!?IfazQMs1RLybkpNAQ^tnPquX-iHJOW?Ex1 zYNd&TCmp8MHQcU3{W%zGz6@!Z-pnhzpGzz4qSo8-p%zvpg1-zb&ypYLAIxhX92r^> zA~+1I{5veGxGb|eEaQ?q>r`ItIkpfkfRqxTFg2_80a&i_9QYIA;+@YU9L0-FtbNQ&ooLR_xpTl)6-7dXUVD+-xv*8YI#hscv8>fsWd=26BwB)LnjPpd@D3$A+1KYyW`HT<$@(C}G!=QfR5I z^?eAM&L@@bDXPqP6;TJY1Rh#~xe6R8mUamj@KOOhxYCVEG7p{~IuwbOY^7=A$Vo3% z43klT4Pc2oLgEXjLMW^`)|=%WmqiXKnbDnSPON_EiOK7wxuWYd$xwd|25rba#;_V4 z#ex6|?mOyqhH&K7EgKsFlsIbwyz1M(TD&~u$CMI?Q_=EFCV_@s3dJ?lXZa*iPq~{9 zTeKpcGpu#T%U3*K?~H1KofBuVFH@VI@eWg;})CpoEr}K@0uiPGxCh zAf!NZ!x4ZYxat#pU@_Wft;$^1Myd|L(RwhUr}k#lW@dr|X-5aF>LN|UyIN|jh^Jk- zxzNbaB#vkqARV}VL1AR1Vx+e zJ~3NTF$i?c0o(Q@ksc9#6!WP3NmW(*=%C6iZtZa2HHluQ4AGI5ptQ74sYR@ynwz-+ zq`*?^jCed=5X@!#DJSW1q8}tVP4PL$LUq7}XPnIe@4iX&g&mY~k!xEg?9vpd%tU9H zF1L&6Z%Px&j2&f3u%e5s^FUQ^lEO@R5H*nqPU0`^I+!7bz} zOgyME^Q0y%p-7AD< zM#Ri+g;}!jibBK6&?!BBjjrQD(aU^-v6|mT>pu>aZWEgbp0!EEE3Zl`tqHFLm3}EX zjUT6tyY$BQdQE#F2$P-28)|nhgd7Y+oSbdJ>}OljRA+0_zZpP3(yFN=xKz`05%}hK zqcOC{A0@;Pu#j#xrQ4WwUV$Cy;nx79Mf|y#LZYU|{%!Avx%;I|**xE-zh6yZaCyTh zMaULNwD}gwa?F6EO_{pW4=g}kR8Keh@1_@<0*hADH3aA)jE|!Occk0PibqwO$^En`lWIAtx7*r`Yq z5cjQ+7Rku;aA|Ngp)=aE+VyU(C+3yy%0sr}StAB+$^oRWp?Q70o@rgwM^N^%QJc4s zjZY1(J@P{t%p@)!%Di9U*t&4v(K?q|D4EMbdraj#wJ~;fP5?mt+Blb)ItA8Cw^mr~ z_@N!IBv9x^l24Y0@XT%Vl-(HC+GY%EL5i#;zS3Ax9NJXwWR(-Ld;$;HpnL^up8;?67L8AiZU-9aDW$&1Ok$cILc!HuT3)L3)8 z2}UM0oCq)-utqi&0@1wGlEGPd?DAF6lDY9KI08pS6g&C_)9SChvLg$I))hUFCw{I$ zxJk-X72BHGSP^ODwr_3knBl*)s=q?rU)^825VT>sEzNJ04yxy^O1ErS$QM3b?cd#Q zK_72Co#Ls(M)}+F^>TWF!3Vh5pIfr4&GQ{`^=+^lgxcNN;_Pe@QeQ9q=#`JF=9aKe_0%ekOmct!cp_qU@|1!Z<`_dE)f*%hF-5BOx%b8c*EQu z*#*a>p5Q?$;pcqC@%K-yKGJ;iFnwkY&vv=Pd-f=wSn-8+?O}aJBhSEj z!A0IYs@^zVA7rjhHr0RjZueo(@7ZpqV;%5!rb)lZUJqN_`Fclrf1;$`sqxCfz9*&w zRS@A7zTMNXqHn`-PjCw~8ut!y8JJuL-)`*<;V(8}~K}9tg0X zy{e8``(UeR*n5mb7#|W@839f(sZqkIB|$4bSMppv{tbuqs<|DbVZ@5cm+)!x|B8AD zQ=3zdSunOOImao~z$w*~oimhG1TLlMx9EtIE3K?+iJ8sIe3$Nsoh`8OX5*RQD@=XI z@eG_TbbIq&yBKZ?rT4$qnIL|*#v4sNW%b3`fY;w{!K%#P+EITudYR+xt?b03c1^%^ z9F)Ko#EPu^L$t+4dvB#h(GV;P>#<3(ElZv9#-l|+H83OZR5o^t1~{}b7p@U8NFb|b zBAb;=bO$s1tFSMWP^YRufg51**w8#u`g_E3eMK^jlQ2|pln{41&V#N&xPZ?@a)7~w zAlZ#XRG+i4cBzZwPE#?J?NOi0|IOGH67jByHMFYmx3-kA3$CEozvNEF8KkxpYlr{w zy_I1%(}2HKKFO}Qu|1mZVDnsZN8AnAmYjPJv?o;e__H(Yh4>?tR&&YE7!}^z?vL1p zC1G2=d)BcZ{w?8dJcWNc-%^LcafjiFmL#)G6(-nXDEVwscJSg>=iWg)bZ6HTFc^_YmqDH(%u zc!L`+28KwfJnq`1GRotv1qz=`@)wTG-l@Sl{hYFIe965OOQN2Cn41!AuPCK2u-Hcw z@9c&#me@ny>SXHzrqd*K>q0tV>2A9ZZFX?>Gtx8^(%}O*Z{?i234VI{_3jk_4z_Z$*MH-fX0BZtSxq@=^`?@6z$v3M{ z;`0ZWJtJyP%3zx3ARzs2u;Uum;bFuuk`{IAT=JeJdUA@En?G-yZb;3<+_Fs>SGLx9 zD#k~4*?kRQEM~{bZC9*sa{lGl%#X8A$cj3W_9migg*_~}3LxHSVm@4nq6-A*k}#E8 zqIpAxv{=O;!5{)|X~_bR3kj{#B4w4SGo;Jr`DWE<%`p1eJiLc){Iyj5;j*G%ZLt^k zFB(k~Jn~Iu40yy&U8?!onYhOe%HtEvJku6+p*Ul^EkjY)Q7dG_+EQ0c1+fg(q}&6S_bB%H7~`!Q zEt*IV(Yy;%*A~1qV{Dq1^g(p2O3;?v%0>_iMQC=k!N8{9%<@K85z$!#o)M-l;E`-J1DP@$&=TV-KIR&$&#VVD|d!QB-o3pT# zaYa;kvWv0KxtE1g%OJi5tMjZ>l5CZyokJt$d8lOJ%NEOYNY5dc1!v2W@6J`4w6X>4 z%9zh>T-baHd`0ytoX)(SA8oNF*SFH`m0-WCtkZXy3nXI1YQloD1d;@jTiQvhw&wVb z61Mg>09l2`-E5tua)SL2$;kr*kieHf8S0?NYw7aiFPPZ-j@fULb<{uLeNtJ82H`%P z;n{z6GF+P$$S_B4sy`g{P^|k$P@%Ke+@wNo`vJc=Lq&Y^c1!3TV0GkY(2^TnZ3S*T z@n_5qGl^vEjg1{qR>kCd?`})$LFGQJtfAP>|#sYnIG)3Z?KGf+aRIpQjWCG@(#=yXXtAARz>M;QHf>I z(~4;M=j^4B=FVju9pfiFpWNhmX>k?fC-m@2`c(MoovwJ?M)cdbN@LBjXuauM@1Tm+ zIsRTJa+OV!b<;Cw9k58-O0q#7ZY|Z=A#}K36kFumWW#vq-}hoZ}xhl;{i{ z7DI(b^u|v3R#&m}urbu85nuE=5MOE#+$leq)_@)to|-d+GolB9JgxC!ydvHULad?| z!VDtPvg@!it~34SL^zdL0!^M6h-Z@QlAL1IXPoTXoKor~XydpEy5)tSlb_9Qn8P+Q8}^0Fq}o>rec-dp?O$9uFd;DxjF5uqyY^I7hzk z3N0QnXbFkX6bFlBGqMs_ZNXpDwBLVvls&F|Q06cI0JMKQR{!_IYHa`Otdop^t%a$H zlQW5cv$Laxq04{ML!wo7<+NN-{%PB8ZtC7Zp+)>fsolmYrln?bfr2T9&=fP67y)s< zPtm=bakRVc22C+92IX;97A>52`v;&m{Mh|1a9%UM zaFliX>OK4FH1nSI`_a#CZB4)^fNbR1NF2N^j_HAK{17luOc=%p1ahG+j)|vqA2ARf z>U&}>(HUuqj^sL&$Kk3D zL$V42@DW-`b|quXw~G};$<^fnVOd6*WfXhu0i`g>Hgs?f7T8IooDrPRp=;1`)?gtq zVx{qei3m*s!-^Tlm<-xb(yTrSxSzVJ^afjXCYi95WQN&=GtlhZ0cL3$arGgj&=xAM z^7Rh)ZgLkk#s-ryw%Lb`90s7A)Kj6(Tp~E z$DewkH>v8d$(E=*fqV1Vc}pla$`(N8sSvVBjZo`Ppi!WNV#&5agHw@Kf!1EZ7P`4% zz`rPI9De}7HgQvNy8h6`JEL_lh(!@F2Fp-@jaMLHBhofk1x^ZF0=3YF5Vo^5IaT!c zFt!taNyWsVvBVq8A>+!ooTrX`!ggKoE`h$xvmuR#ygv&5EL3r$hP!<}c(y;kf~K~` z`Pq4AT(N@|EaOfj?)wHR0e5&F+fc9#3%#`f)D?BVT+ll(Es3Q0_5ki`0b@^T5CApD%As#h z5L@WLtiseE!hPDIdp5iwE{xGmFZF17G!v+SWLXbuJhyn^O;3N$Cti&Y#Ok+D@y6c~ zKh2t@EuNNpl8KSCg`Mqx^@FojH~moD zQ2+fT$hbD7$JLQg?ynGTB~0746!S~unI{M)CIqEuLC~&^-x#~;yOCw5lk#h6R#tbL zS8Fzhch6&2=Ya-ClWN|9^5W}x-@)JY$9}w@mBxOkbDNpEHU?EI>iMQJ|62QAw@%^p zw0~fd!}cv9wBjL%Fa<%8SkD4RCfyOr5h{2jIYDs61l2~ap-0`*jr$LgWa}0Zo85ur!0u7>WbYqXlyVFpc8`uVAa@Pl?H(U+ zm=WGRyhD?_`kK(wUlbAOrQU2I5O0?yAa@h*B7$zE+*JnP(>_Cye22PfCEn_Ta>d^) z5NeqXB1lUD-_rlGlxv3A7Fqk>?IAv=Va;-QlJ)3Gv6nQ95a^d_RKL*{VwJz)jS>NV zpef>V#vJ2B7iCHoeX4L>ml}B5wp0 zW`c>_!1`BInHFQr;XMEyZ={4Z6-_m zZdjC-K^y$H^SpU`Od(2nwK++DZgiDkxg=xD_VP8SH@!rro{(rrjYfX6bzm|JO?ueF=_;MbEwN z3{=&vQnX8qAy>sQMMXYJq)hr!c2fZr06R*Cs&spj{;YT1l zvHhwVY($jUU0D?1$`c|lTG%!7n*A^%YAY|w=A_N0P~y_IATv(zXE5#IDLc-P2IlEq zWPqQPb<(|*H_;(C-PjwdFYO@_++^jIwB7ToX z4ggBF3H5r`HHF1<+DV4oyd>3V*T?h>dJ`&_%?XplFaz$eG>KzM0rm~DMlu{Pj#_Y~ z%hVuWjg~W|K8Yx6qJlKK1tHS5WF@~yD-ppN!kR(424?T!o(&Dio0Psg#|c~&k?_T+E*b8iCnkGFb5$T&TA(lwC3MO-r;f#?*~ zAl2rA#cw6~UgCW>M8sr-R^}D5$7D?=hQnNT!Q0J;HlFWmUh7&$8R%#wl&8RHX3250 zShCs8lAHph#aD4q@?(4xYL3qY6dsOK$wU?Y{2JJy0D#V4yn!c&{|3#ZkX(&G^9)@Se+k!iI@ayjs)!ht{#F~1bHRQ6l*4O zo<8NkpdJSNcMb@Nn&C)OUH}fCOs2DLvvrS210nAl1=|akuwg&uQhln`N__%b=|P=4 znsWr-)}Rd+o$$CmC`uRc8$}AV#&Dg1QHt?Lu!UyUXc)q$LrMQ*BsUymObC-V5X=y2 zNIRZeb;LVl_A~$~zm8wHUecL}>}JHY90p&pZR9yIi&bO>#=1Yq0&X2iH;iVn8*!33-_q`-LQA`IFOwjUmS?+@JQn-t&!-+6;8+_L7|X*)ZV*~;;D%|g|t5&>At?)!G^H&7^8X;_@&%7Hmg3x*;PsB`>K*z zl-37%=tz9B60^JJ(7VUkn{VE&YA{Kt(j2$-RnWC=GF@g+*pkWCZ@H2)`g5=HQ_FP@ zP`Jgwal-Cfo>)FVj!a5F}X=sB`W3-^#T2y%w??7_6K$s?V!--H|;887uQyM>V(lE>{am1kHF z32j^#Hg?S0vsM+2GwOu3oxoG`NEGY=%(a~rq;rbNqiAYc`B48b*wu#Wa}b2OWFh&2 zvF^dvKgk%oMQBf03J!F(sCNcs?|EOs;m2MUmjL+4k}5XWNAKz~B~g=H;P46-EQ)+k zSpWTJZf3KMGN=6;x#<6oG{^s4E&SiP+5d@JetC{czZeQ1^3=o-;NYgDkV%NtWHt%x zwZ3SyKN|^xEi5KB=I3iyaMKn@;<6n_MRhXUBI&lAC*O+nN~NkOfB3}>mixDgusQih z*B;OKZtfq>8hIAQ{^9rRj*l0U%HG9h-Fo%jcK7zae)eQ}{R>7n5Mjdp|nTvF9fhf1Oe-x5)bZBP%MuVT*P{=#$9e3%T;m2!6?v;Bg+S4}NMC5BRVrJ4lA@_Do^AkTQ-THFU?tk>Y|iD|W0DNXuh3asxZl>0F;L&agL?(zbPf6z+P==`Pwl1WUb?-#hJFgd!0G3C zNV}36vs_vgBeHCYHn265oHlQ$c%BTWu~1iBm_uK~vV^}qdrnoJqP`B<==^3z>+tmI zuwkE&?;YMQGWFOBc{dXZ)UPwWQ<7R3@V-=`$-T9V zr>BwK%2Es&ZvQfbHf&%@MoN6aoXn^MCCcDNR7jI#Zd4ZxX2cm;Pf&-Hdj4`|EK~SJ zWLY0Fx&HexFj=Zoq81}cnvZv9$y6m0IkmIx(!Fgz>A;+rnCRNiSVj$Y4o)dbh)L)= z)jWPw{9JIbF@yY%C_n)>E}{9x;oHC0$tEHKgAPPfsmm)LG7V~~mS3x# zu1=L1)^-LUVO8VfKzov)L*4$IOxM1bE~QFL$6DO3D(Q|`T7GQNfDQ?1_I678r8qFT z^=cqY(lr3At}=ffW6h07>9n-2W>1_>T59-!vF=#zdDVMRF>9z95P%4&Q1hWuMx>i) z57%3QG!>&bV0YIM^w`Eveth-O)Ip*>BoPAYb6-YfwG=x&>{M}5!8(ICil>{nEBS^S zR^IYArmNZe7UeHnV`1AGwuzR1PD9>lYTUZqerXsNh&2UQGKv~cvj`^cm zD@K1Qb+%-}w_@k1L6uuax<0PKT?(7oi-6YfjUNBDUQmU@A`6S|w1z?(XElkEk>vV& zYh3~bhnWn8rE=tXsmI?M>4u4ZafOrFBz|R?;$&Hl$6aUnOReL11rb{4`@ru>u~~X- zCR5=NdjEpfYs(_$5|~?)vkyPnYe`5%=HNE#F08MH0$^1sP^Hf^ojftK0^+d!6)1A^ zVCLrw(uzmjV?bXpHSXf^jEbw(FG$kzvW+X|-m*bq%5;@ecqR?pMCNT}d?6cAdSVq} zoa63zf=Vl@q#`CHYe@wO%$P}A8m{HCGr!@?kU$<}Kly$r&nD2bctw%hG25WNIiaM# zmIbY;^Oxa0l~Fas9j#F}#GKlq(89O;e(`vD_}dyES+;~eMbu)gQ*XnfyMzTmPdTP6 zHTH4=?YIMwXc%L;~uZLvKrb#qT7Q&%2q>x?wUst&dp5e zgv~Sp+-wIvuYTp(0Y3InPGCHVab)K}uK1zLnS)&jx$G5AX}gxL8M6cXt{Lq}MlOI> z&C+`grKI4a>{ZC_V{`P^A|G)sWNKtted6vFsV(%hmkUR zxT%F|^=Y{xqph*D)+!Xq#fGu1hjjm+4C+H3dyr4(d zZW)Jv!Wyq^vdsKONMF#u{J&A{61TXn?AB!1s*~P5w?y&gmQ!niI?CFBqN#Z}w%DWF zmCP}mtI~xJEhdam^``Q}!Cv{t-N3&k0KCA7yiyy!e*IH^XCKo|dUAXnK(N<;F6xN+ z?+fD40wnkSls0FBVSQ8F}AOH zV?wDUe>RvIS~GY|f`%<}M62t!hYbg41YGBmsq9#o$?!SRiH-jdknFUihvO;wj3s|J|bG{&Pb+riN- zSqHtp79JU=MW8HhAMdvq;<5VSqCrR2X_l4BXSeC7N7)Q0TBD~B($JJLs1eYy@FTD6 z8RR2^oBPV!qYItZ6{w{+m~Kf}eZ{UkP+Av-X$CIM+H?i}IlkM6RPS6zd^mq09OipjeeyhCk#LDb%MJSHsN@Gq)xu&FEfyRh7`~i zIik~qhS-vb!s7+gN{?;Jcj5v07DwaN8d6+MyH`Up>oQa>qm{O(7Gh$;x z!(EWl5Y`3~8{uXJ`Gm9MQ7$NsJ{1~y@2t-|j2uF7#sB+Se+&|!LA@cX+Xc?Gryq8~ z&*vBIL=cddXCR2uuSF114Ku*6<{=`XsQ7&LB9=it9Y!wm_WebGiNi(B z$qe`xl^uupKNY@N|DQ`kBJM^e_Wyrvi0j#Il^4tuOb1Mtj$n9rrf+(tZ*Z*7G%-C@ z!*FzrpkhBUSv{pJH!&@>247n-DLvJ;8gpcOEwT#RpO_YSRBw&<% zs2O@%Nm-Xk5QiaeI5ZdNv6lgC;pOqhB}5iCZ@Af^x{i$G!iniqKnj{ z(^Hg7@{{DVR1!3^(xMX7OQSOrV+7GQP`Zh{u|5!IP6!4d!Z~Ataj+vwz~SH0O=ilA zE7(Z1zK1KpI4GJ6c*P??ggwBzG)&fSZvY%3iWG}{?)QN}{Eq__O#ka66EQNkBl(Yu zw27;U^?yaB!SXUvNBjsr*CdHk?7k-7Kf?EU2N|2XC<4L)7+u0ad*#eZBj#5rvS!A9 zQw@FwJdn^Iz+Vc6q*D?gpLZ1(3eUPKz1{!(M1c9~S45%xL-Bb_e5T&go*7S#b_NSV zQT+6FZ>gCqIW7gIL(ce^&cLC{z{FQ6Yudz7Fv#sFEyJQ@{`SjPPX|- zPAm;p^wqFgP~aQih6q-==msgS&rKZE$gPT~zuTzJ6$2g*f`)jUN>eh8w$nsh{Ozty z_T@vEEPKd_YFgrJ=rUE*+%Y`#vZ@+9t*zOC5O!fQ3avzq2`KD*gt;FI@53-^B>Tq@ zV`RAY0WCXS^Ffahjx9hOk=++=_{YAm4U?sC4Z7=Wmpr=Hnq6a4)*#&|Qv)AbUGVZh z(RQws3osX!ZsoJ+IDTbNkqik8-15K%8&n^n3>JxD$08i^B={i(;o}kYobGA$J?9s z)1Q}L9Kp`_ zZ5e|yiZTi+Noa%$IsHjcF+YC2%|4uF$SI_pKPNT!Y#9V-`In5*%$P=q&bZ7+jfL6= zituE~aJ|hmaGMV%`*mxVmhyiVo)fn#Cg9cOw+h`OPE^<5`k=0gv5= zVHK|y!cCGwoQO(2L4-@L+Qyuq!jku5eYyB!5MKwCrJ83Wm4-5@1$*2|ysu&=j*Med zFDXMt4kQ^y@j{aNU3p3%Z8Q0T$7uCYRE9!TMAj{PN-DE8-zoM^bpnMK$NAtn#i zMv;f}H&kq@d1 zu2Y&?ecmA)ui|}ujGVpNXlYqRTj?RQGU`y!C1=(>M^9evV~ABF3@qCj=U4%Hb9sZ4wk!KWWvFr(2|TVGsJ)EMmI>gEiNYFc!_sk-z|(7uxn*W$LpJUlgq zu*IinT6}AePJA+ZucW#8JQ!RW5ILj`P z{K@#UNl8TwGyQH&kJ(gWY&dGQes6=p?HXBGIyy7@8WYCC1bPadKmB`@h~1RO{oE`w}wk-6XS>oMqU`&ywU$eRmZ;^~c46RVrrzb=G!3+?p~C zQH3gcj_;&IeU(GgP(jonFv@+dN{(|_xtHt={i^GaDtlPHqz|73=>GAvy#;z~)$CLU zhfZ7doe*Y+E`+nooc_nJHXI;?<5)9!`(Y!BGY=$C9(dvxDijaR`s?Fuh7EU6XOonC zV?`UOFykarVdi+!A*OlKA$$jA0a-@`v&~sa;5mjc*Q`O=EHQFMQ2KgPEqSM4nDHuO zUx6pNBBm?iuTgAybjI={wYantBUqC4;gtMiFA}i?B3Nq+e!s99ks>j*IvY-@CLhdA z{8%30tG7d?`5eBySC+Z@u(k5F*?FqJfndcu0FE&ZUw!1&2BJ!?RRfby6# zIp=^50OQ8WB<$?``q_JvtC^H!&hn`b7g9*vPxs*qi(}luKF1 zZc!b9=a1~=5C#-%5?YF&6m+?krT+WYgN`CZ8*~9G68GP&BR1B|jrePVH^485H((!8 zB3hs!VtDSlg@=0}h@d8VXrLE(nykzuRYPilqNyp|*(nZYr|Z#w+g=c`oAw)hmg*M9 zbG1W%kv5%SF6v-ej5__vuHaX^m8T))?1w$EYT=`_;D(8k4>N@fA>4eN=qrVWAy`l`1Y&T;vrP86tbiI2#6r z!&NcY<6Q&UNXcpD8HJ-^%_`>?O5!lrgV~U+6l@RCSKKhfT#lt<^g|-^K;4kE<+WNXpefGeFPTHbK%$Oe& zrQTDHpn7aKNZm+9|7m{KYu6HEx5sNJh2V1lx8QVaDZR` zmpV>eRZ>P{5}ZopRpCpM6e#ZahS?*qx0xc(m6t4URc1xkTC+Nv+m3mm+Ux;g9rR(* z#Fih~kXZ`3Vo|VTF)g6}%}PR34K^*g9M^PHcs}66qKAGs9_Eu&2^zNY%qiqt%Rj9Nfm z);g6poG}cQBDd2fm3jB4*E>gG!9rfWcxv-`jcr9oVq4^;`tfXAT;XRBZYOaRylL*H zPfYe3xsVt6R`100vhjA%z%no$)Ath&Q13s>phd|W=aj!VUXfp>(*J!g{y)SlzkBh& zOQ2fLI3~FNd@^NBnX*f4Bq{TQ>4HnfLrjy==qUju#3uyJEo+N39U8bKTDG$xxf*3E z##E{)l-ns@0?L#tY(U$Mm9TA;n^c5Fy7qPSyzk%kBI&aZ?_YDbWm+aTROMuQCja^V zGu3;49ak#rr}`S^|08-aADl$PWwLH!FL61BVZUdI!J20zJeu8LW^x}iiN2BLzm2iT zNSDg<{D#15y+`LQ+~;=LCN|pb*gMH(Cno4Hi50P-gBfJ$Q)4Yn2C^%ZxCL%*k78(CZJ(ZcY#)A^BAU9rOd&JchxvT8WuDl3Hwr}*oLS% zD05t0HUUJ4$Y36(AFSbXvw?DVCc$=5jdefQ zdS*Q}YgYMA1KPDOa`Zq#3lu%{rlj81RQzSG)WaOxvs=(kf0yF=_|daiT5#xuSP8TG zY|9_}=Edd#LisMsDPwgvazv`NcP}+**jByT0+L_VQUfoor4|&Jz+Y~Y%6|jTycHv- zf#>;LWKC;=*M;e{!I<>oAU<^tLt|(l;bRc<-N3(;x$Hus**d#ygwiRIxghviVc?@= zH;#%D*ngiTf5`1exly(N{M^^xH}R>BY`()IkDfu^)UB>3;o+n!n|40B3``$`YC$mNYTM?8L(_cW#? zyN+XGtk@rRzvhLf%lQ%r7-Dh3Mkh{?k~E5vCc>)bnX3}d&LVNo9JeKOV7+^mX5+oWmNdaMsAUMr)r8|96RQmxH!QZT%JP-?qRJg}h45WOYV%;q(q z^yS9B(x;AAbsg*M)|K!bkCIkuq`nk{ugQMm*2kDnA25akgd|8lzP;RW~`!J=Y-0Xs~(r2Jl4`hNh-hg2AH&nS)r23%Ufn zY58M>@Fh1UOglXfX5QR5rHghR{`A*p(m^wdXZ+oBr%BFn$pM{>kG;2t(@)yJcSu=i zhG~0P`X6&Ssn68r#(xbB?XI4q8`AgBAbmFFG{dlU)%j5U#DJ0OD~<2HGE9HcXP6lm ze^6mDBDZHw7d0d6gQ^&;!$W(Vcu_}9O0MTggon|w9MJUHp}ohH_+nKE+&apmYU>+0 zY28jCqFT4Az5r^TwRKXt{E2dmi!xAR1CzMS%=)}S3rc$2`%+U6@tT$W>wC<7UEgHG zJ-VpM6l6B@^4&J7e?NOx-AmKZT1DlPd;qMW_+*-S$Pr${Of&gLiE_)xTBBO7Haddy zg?4~g{i*J$LVTIFb+_NV!9HpS`Dhg^9nWZ{{wUiH_`JC_G6mWN53(3&*XclM;rV(2 zJr*S^DzODAwwMF6&7+hw#MzL50rTlP2=S@0-q$$tfQ178m=*gW&ial#2fd~)TNQ1 zGgduK16Y>bRmE+g)o9z%%ycw!OUzFK)>dBvEuvebh7=7+fobuKQrZe8a3(l-8NyqE z+Z0Z}N!6vyQh=BB5m&i!08}I3MaH9B)>@Jd7$;%_YzIJ!6y`PdRmousY+J|vwcGWn zA3Q}~Ju2{bm%3d99Lk=v{YB}B2N%T`Mh;L zAco)LDsx8VW{lDMJ9E84=(a-UMGt6HC#qyKmW?^3cj3HL^mZuR4F9=g#8+Hiuht(9 zxvclp`~&y#YY!0lPJyrXcgW;Yj(6_aix_n*=x0z!Avi8H-B5BNn`bn-fSe6NgfFkk zs#Y}mEhW1K^8B>1#bNarS@O9?m`dBX`_M~?fNW2a{hx(>t76|}WL1fSu z@6=P2(ZnQYo#V&9=BZ@Q(MqN`7+Ob=5S8wUyw*^s$2PhCV#$=l)?FqB5>g)tH3eck0O%y4v&K6Y&!3e=jBn)|IbS|0pbAsb`p}X1*j7) z(y^G3e$rxCF>-uVtByD@AF}uGc`}kve`vZH?sy<9SV(XW@dT8RJoJM#rU)=6tqEv3 zX%G2<8wXusj2N)2dD_7yi5k-YE$sBC~O&MOyOw@ zeqC1+hLK<|Vo0eHUvak)DmC^wG zd}?{WLunojDQ%7TgmwPav0g+W)hZo!He-!wzg@;$pot6L+2HXouft=?t>cvXp$hK_ zw`%09j3)&}xz`jxji+3h_YN~n>R<{a&8GYnNhHO|t=vH(bd{c$W<5#|T6>|Y0FDQ> z

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�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 literal 0 HcmV?d00001 diff --git a/build-spring-ldap/jdiff/lib/black.gif b/build-spring-ldap/jdiff/lib/black.gif new file mode 100644 index 0000000000000000000000000000000000000000..185d95b110bd7e43940311158ceb8dffe9906667 GIT binary patch literal 799 scmZ?wbhEHbWMp7u_|5z>% literal 0 HcmV?d00001 diff --git a/build-spring-ldap/jdiff/lib/classdoc.jar b/build-spring-ldap/jdiff/lib/classdoc.jar new file mode 100644 index 0000000000000000000000000000000000000000..725416399fc2c3d7a2c86f704f2255fbc8f85b73 GIT binary patch literal 42559 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 L@DrL)0I>TP6=@RQ literal 0 HcmV?d00001 diff --git a/build-spring-ldap/jdiff/lib/new.gif b/build-spring-ldap/jdiff/lib/new.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0ef7a4744c9fa07045cf1ffb866b9e6c1a2ea11 GIT binary patch literal 116 zcmZ?wbhEHblxN^!n8?Tg1P2Zr`2QcoQ2faP6kue~0dYX`3{0*)`AuDlcOF%qzv!}h zvf1zdg<=j94`ik-ImY>X@-(g6%bva7wbA0x#(t%bRU7V{;pjZkbx_G@CxfS>?wO;j PPVh)?@eK)LV6X-N(#0(I literal 0 HcmV?d00001 diff --git a/build-spring-ldap/jdiff/lib/xerces.jar b/build-spring-ldap/jdiff/lib/xerces.jar new file mode 100644 index 0000000000000000000000000000000000000000..e75d486c8d99854f26476d9dbd21ea3713a310d1 GIT binary patch literal 1802885 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

tRd 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

{nm4_ph?|ud(;9wf8?_?|;_e~G zhgaK&*Vu>G+J_&p4?k)j-eezs+&;Y1KD^sLe8N6lZy#A>A6aJ~dC)$x!9KFlKJtwI z+h!lBwU6wukGyIhUu7TPXCL2hA3tfISZSYl)IPDvKC#(8xynAd+CEvM|JK_lAGA+y z(0?24ll(ntpM1tXNwTf>$y)p5cKhVZ`mfGD$=`1Kr=_C5@n0=bR6Z)^-KC|9F^N@XJ zmwo1dU0-9@ue0kPw(B?9^-tOL&*;C+cKu$vp0~&B`V;&$tlrkJW^KcoO$}>~Hq@-t zf2$j6)-=?tZKzq_Q1g)fd$^(Ik%pQ_8)_bJs5!0w>Kkh68`iGWe~&b*0+U@%9<%YHV)#<-o4Qu(^+puB;nazS z(<>WJKh<#h8x5zoG@RbnaAs}8nFkxrY-~8Qso~5s4QDp%zvmjx@V7<(ZEZMnrlEdi zL;c}~`lAi?ryJ_)!`gp^~2O80ur#^l8(;YzybH;w@jHWHM zt)eG&A&OCJ*X`F7qt&z`iY6S?G@

;EcWdj6(rhh4s(ad(K4R_%DOkFOIVfZoW7^ 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

>Ai#vWpwO`n8K9%Ba6Y2lE7{|loN|D{2R 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%0A(9aMz~ z_-svg66r-YJyM=?j;2Qv>7z8A@p5gjJg5Id$W+|Z-^TZCW8?Q}7FF8&oPH*L-`1Oa zPww{X0oa{=Y`-36r}Gh+5O`GP1Rg`ugOzdMaoHGnN}27Yw!s3zjQCm173mmC- zWVIt}99ipVz}}GLXTkRu=viSF%h(7dBb5|ok~T`oXeDQ9mN81k>g6~+8?U5T$pj@O zTC7ybM7=DF0=%B2WQLMiQCTXJl}u%1%ao{8N<~yw$f77~4Wvq@M=>Cn8Y7W>!Dx!1aFPwTH{E^f3#s^-@%Rvz+x`|!wBF) z59pN#ZUKZ$s&3u0NgABM4k{8%mC6=Un1UKiZ!38k_*@F+ECG~C;-MN+P)SLsQFn{W zR6tKESf0WJEBzeqT$?afNlhaWhtU6fzv@6*hu zv)go8TcA6LW>kZ#20yCdRzW0F1n1|FGKwqZo79doVkceLp|~2jip=Ms!gr;YDx_gX z@d}RNp7PF~9cNbeva6ZlYJ6owXiKrtwm-U?*-ClYr7R7DU`~eVQN@1Qs@zF?hFk)Z zPkY-_!?<~mNS+m0+g4kF4*?`2D4=6rJiKw(%1^;oUgc9E0yWI^+J8!1>FYzv_YX-i z;TlRK`qQj_DwI^Nt3Payy~xpvu)VOtZKp04I4YSZCI$yOU#XcG3e`-sN{gHf6|Uw) zkhJFNhG#(JVHs7T;s%_I4D_~g@xpd17gLL{;pr^G274A^`dU`-SR$KQ@3$h>Xh0ay zgrzEiSo~#GNDKFO;`6Fa>hYV^EFJvUN&Jg0xd#7PH{ulFHo2O(YuCtroCL&QtHVoK zLahNgH+5y)Gxv`-?8SqS{#B5nk6&A(^$p!~R@;#$gdpvwIjcAcoISX0nC0cfeR@#y!MY2;b zTlGeprnP0tXxWvCD&r%2?$sQ$_>D|40_wpyKlNmM=GEF#}+YR-j~rk}+~~l-=7$m3%VF zhVw`iXDpCoN_9yC;ff?Bh}S zn(U7vSb8>!0_w#mny8ae`IeGzYc1cA<59%kknbsZRmu0|nJ6Li?iL=od1h_Y$BPw_zyVKYV=96KaSNwz#3g=znA)byhSEZ)cPf>pGq85Dl1 zd+(xoYD|#p-s()oId{|5;_7wTQjHt$LYucV7M(M%NIk`u`zr+)h55ofYAr}+tS{>3 z?6BO( zoxl=}03yfJlHho?jw%`-uban8Qz7-a22`hI13gBsH~Xe;=?R09(=ˣBd!*S1eu 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≷6mVH;8DP1fyV<+0xkod23!Gr1n>;tS-_RR)xgIB z*La4|allJ~j|V;x_$1)dfX@Iv8~9w{3xO{Nz8v^U;MKs_0A=l^TLNbSX8~i}%Fe)DfpdZLfO`S=0qzIfA9xV(VBkXF z;lLw3DIme;X*=;C#NuK{I4fE~qB@Wz*3gia&Nvw7EC;F$VZPRZmOG2f;_lsVPN_lDs^cdb1>FAOEiLiXhy z*2fx=NL`|dVISP>?)?{#Z|&ZXfV^w>z5|rJcJJ#>`Q)$8VZ4SWL9&cP4r zk@6M9vBRQJ27DMXhr?m`#9*}0I7yYue(q;}7TVWo}=d)C3oK`tx_L@w9vc?J)M?Tq4?;YoDY*X`(aSxaM( z+H*a102*);WoGBH#sQbk&dm#Z!Z<*B7#}+2>pkjL&WB73DnhNc(%|j)?r=|W?VjOC=6<=8yVvf?i9Q83cI$eN1u)$kZ$P1CenT{^O(C zKR$33`Qz1unm`A2O@BO8za~(qgql{@{=xSjD{^kwm+z0&=Drt|pA0SM1~2)-{&jml z$CyZ-osUt>R&RMs<>ustlkp$GfIJ*@3G^UZ{Ev3Ef3!i)hDP5Xo@g!}6k(NbX6v!J zg$~VEXvAFSq=!Ly0?|9HB~#}6(4fgAgImkDFo-d*yfWXerP8pKZ~sO0qTe91`VPYw zutRg%n8(oC-^Yi&t6_R1Hwgc~`US8#&LHeZMm|sd(fr<}_Veo8GZb4oUNIao{6_(}bV4mO=u-6J; zw|nRDjnb);oKzf(cT#)l)KVuEDpF2rE1f#lNrm-nCzS_K%4$7cf~)_t0Wn{&>pD6; zoU(>a3J2HFa$RgRPSE33!H3zfTAHAfraMV6-GZb+I%%?#6wpcCbkam8DMcqWLlv0x zhvm9PMLqiepDwlk>Buc->DM6oJCyuJ(E~3@lWx3L(O%a+!l@lR3i|McPAYPez)m3P z4V^U7Ndi-Wq{np9C?^S=4w5$Nq%lrXC!KV?PAYMdzX#odl%oUvmrrYd`G{XCKW-n2F{N?7z+aw4Qc^U@^=baHNnxP{ZUYdEYboF} zWO&{npXVJcv;Ik8&xh33^EsAN|D+<%m*9$iz*6W(a6LcME1qAl?D!SSjsMVxp564h zXAhPdd+8^W=vPzG9@8U)X^JG%5&<(wq?>-x+)Nhj%z)@?kS_KiupjjxjrnW`*ov9x6MVGh}yjraZ(vS`IR2 z$)V(9o=CQKEoG*_u7sy#=jht^Tlnc!z@_2KpJi%NhSDDAlv&|Fb zMdnI*sdV4f~-G0%{XwpnYWn70|t%-f9&^A4kf`8T7pd6$uA z-fi?W?=kwA_ZoxE&Bh4xK4X-*#Ta95GbWo48x`gw#!=>WW0twYm~ZYh7MhP6$D2&(9!x0-Jox0&x78xh}XerP;meq=mh zer!Btes283{Fm{G`K9r>`GfI|`J?f@`IE87{8!BR>|gGm1>d7w1nzl8LE@z zQMs0>`U3Z}ysE$osL@tXO|VkcWZ)@QnyRqU)hw%-s2)kdwd z+NukHFSgpN%d9SHot3R>tsHfSm8&*dd1{N*T|Hn8Qjb`J)f3hb^%TO-TEo;UR-t;` zDpK!TBh-i1T=l6{t-iC4QNLRA)Nj@TkFaVyUSPkq$dh6n?`dtV@MKvhcsf`odOBMx zJ$cqio_^LTo&nY>PoZ^|XS8*;XR>v^=TPe+&k=|pWnJu`5dAIekxdr$E>r-=w^_jWL`rLfZ`j`2N^`-f`^_BU)^|kq-^^^IT z^|Sel^_!)vKdfYHx0Mdu+}dMhS$nN6z&Oxk^|6Ij06f^1)=1m1#sg2Zl~rMTtfPQu z*`_tmwyed#%WT^^#r9ff0iSF8tjp{qYc=q7w%@wNPPR4x-)#r1`|T8KJMg1+(0bNR zwO#>!-40pr*=g1%z@OXc)^~Q;`W5(hyM?veZfQ$9(^hsHJIQWq2kb06&2DEmv)d!o z0spynS3A${VRyHC1NKLJpxw(Jj##nX#~y3{^s+0si7LXXkLTnyG`IBzUVf=Q`JS*Rn7$TVh9}s3Elq5_A+b!VQ^rD> zzO^(Uu~2&y3gGY_kbfonlX-v+dcqd1zobk3xj7r1auZ+?wkwT|Gv`@LRjE8T8FXUwh6zD&N$TS?jfw z5zWRI){_rtz|DK#1j5>Fs*~$R8V`2Nj^?bTc3~@Cm9@XBtkt}5>r)Zxw3P;J&k19- zHWaflU^qT0!a{m8EWK|c+rEX8>{}@So;lUNjoR3^<9y!T)C2Ls_9hx(-%I1|&3GR7 z<9R$thuhnz+J1-@*^kl*h@WFWK^NLj)7AEibiMr&-DJOv=W{onh{Ul)EWEWQRe$P7 zchx=Iomq43tu}@c{|@rlA)AJ(qeeB_raYUv+w8&_$BSZ?=7w8rgl>dI#SwdR`T$W9 zA0Vsf4ht{q=!&(Zd5k`Bh?da!}H9&9MM2ipi9$TsK(vXS9| zeA;LbYmE9F!)EK1F#jnmtj~X04}va3?sm zg*R4)(k`icxZP2+W_MOsTp5O~Mn@B4zbBsl%n_$1TJT9!GH&RIlydB$HLTJdF=ZFk z>^|VbPK_RXw|NVlk9i#AUiZNt5dCw?*$30E^I%=)*rO*>lQ7#s01A>O_~QmqgIQr> ze-A9x?13XUcshu=jrYX;T7?~;U~?I0KcPD8ON+A(0A-(FDY%)DDtvRG@uD zrR`v!Rw0f-7?!?+d@#>ix5{p)GMhp&hq7chR0ir3snVsAoWv^00Y@d7d*i4immniZ zR3!T?n9l^RX=hciH3#8~84|4A8*(hqwdB+7Y^*G|A#B zBovQP&Tz_cT{tSwhvu=Aj%Z19mpb!gD*I8A?2m_20EO^@IIxOsEjfgWfmHEx=Oz1snGm38}m`q0eLI6ch2p(s#az2gA&3==0AG0Q+@cv2V$3|uFj zIQn1F)#Zj-GHAshlR;|+Z5Xs=kj0=KgZ2zMFzCpj6NAnSx-jUs=#>z*khU;vp={x?g$YL77Pc({wn(u>&=#q-2-zad7U{MK+oG8*n%km^s+^7TVMgu*A|D^BHtGMY|-Bq18h-Xi-EQnWQ)PJ7-ETOmY8md3QHVniNh>$ zxFwFT1hk>o(S1H>mTY0LmBIZ!C|*3^g*MBB47M?Nh{3}?fJeNzy4^=N&<+MW89d6x z9`g$yJ{g;}=uu1;3afiu~dzE-{nK z&g9V1^c;>yWo5x=L00Sl&*1hr&634Oc{t?Ff&vgu!Eo5l!q>F4(g_|vw`QIW3S5Dn zG88!z*`J6;vA&3zdOz+{_s!@;RG*vV5%n)RC3oPu(6Wct`UU^N0q-D3)0e~Pg9@jY zl<_gH8HJ@q#bxCaCUbIT{p1-FCeL8g5PUi8x*WAg!Re{-bZwS`)0)N8;&ZQ(zl?cYKv359TZxpw_SC_|6&^O_#ar~5Vk#QBf)6xm$@d^X+mYh$`RhD(axdB(B4c)p{@#cKqLGgi- zHfU<$Tw(>jo~x=?M)b47OvYswM!H-LxM^6z(}`VhJy_QOiCvD+w3hK^Vk9a;+!Fd7yU2lr zhZ4Io5gdc-eq!lN@e)3bDB*M6j++8vdX0BVUx+;M#QZUOnDF3Z{4Sq;=2x#&=>gl7>e@0_b~eU%AUq9tALD|S6{-lm~v0CL)J zYfM!W21l&67;#N_m9fhcaAd~yDr4!+@tcOa7ddy+(51-P8W(Mhj(!(iYlsZGE)f^qv2TRaG)Dj~2g=jER zrjC(B_WG_%Mh{*%Ql`X*Bd7_k+Z#Ci;Yx}&)2NKfoj2mL{h-ce{F$Q_M$J-)$UF;q zcwl{`@jO2Au%yQ6KP=4Lf)yS?65c{2i_s*6A2AjwWr$pXlk~25YgZg507Q-}4if+( z(-ntlGcni|huJid<%+|(iU_#kFgYOFxZ<#;CEB{;Uc@`N;&6p7I=bRXh<9?uVWUrU zcE#bxMRaq;1BiEZ#ZwUP;)(|m&vV675g*`+hY-(q#nTY)?uw@)-p>^eBRPj|(;ARczbyCUAq74L?4b5}eY z@fNOl4&oWEcrM~CUGY4`Te;%h5pVB`_dq<`74M1o5Ldhx;t)&V+h_?Hef+)jCdo1j z{$^N!p)sTxz&6A`UYw&AA_*5^>;Y*cx&?bZOzSI*(D`K*Dzvh!!V@~LtilYPSXN<$ zt}CmsL#LEg1kKQVKr3_-pdC6H&>K1(&=)!bFe$VO&>uPzFgbJ%U?6lhU`psLz+mVC zz|_z+fT7TpfN7x%0n=s%E zm>oJEFekJeFgLUUFfVihVE52zfIULz0`?4DUv@9urDe%tI3C$$uzy6xN|+cp3C0Ch zlHWKPwggtffWRp*9k3Gi0#1dcfRzwAo(5s#N=O(_hiq{rWQk`$intO|!&Q(MuB6_^ znba4!zi}2701truk!puud-4G%s}2-U9Vtz9qPD6t<*6>zPj#b0m4yjccLEvq4V?`)`E7kJZ zfjd_T(F&TocWL?z+H_G#nvW0Z+K03<^&T@nfF5uuXIyj4ib9Hb!2WRQvcn%(^gTpykrGx!AI8z66 zIe4@Vw&UOo9c;!ys7Ir3NgSMj;Q#Z-E7oySgSl04B?qCIjUeBDXs8aJ!oguWxP*g+ zI#|uY;W~IE2a9yDjDsU|a5M*tb#O2TN9tg24vx}69xb8KI+)495*>uj&&JS11cCK9 z>34wRgx=(m(_JO|@3*9G;E?@hbH+R^;|AuTf&b?(h4lL$xP|WJ?~q62`rkun9V0SE z#zC@92Eph<9@UrLQTg<->PMfc0rZV3pzqZn`b`a{-3q7N)G%SI;UcJtM4BoVt<*@- zMvWGoRf*`P#)@8Qoan1c#UM373{{iFC%tO6{o4gpl^GGxIi5#R;#1M z!)lKBSXGO!)G^{4HBbDa=8NA{jg)Gk^r%HLSuK`9wN$oH%VaCHTy{_^WM_4v?5=wKOgUMdEe}=a$l2;#d5k(wE>aiBrRpMilDb%)sxFo1 zsLSN}>I!+ex>8=Hu9i2bYvg*hM&7Qjl^fLcaQ?!> zs+E6Nx62RI9r7c!L4K+3l)tKbj7+t~C{p(uW7PvjsoG{tRSy{z>Jek6+HTBNJB@kj zQKLpdEmT1*R6S{&uAVZ^RL>X}s%MQ$)bqwQ>ILIk^^$RudfB*Dy=vU0UNi1dZx|1# zH;sqXTgKz+ZR1Jxj`5;;*LX#}Z@jHOFy2)k8lR|7m0x|X($yELx%yJIRbQ!*>T5M$ z{aYBv4J9Vo1UR|huR`;mi)!)@_^?}->K7xg|FI6A)v&T?>s9u;B%U~ABnX21H zCVp0$$Bd}e-Sj-GxA0XDWGjbBAt$rjo6m;2S)pklrohsWlQrr;HNDlfl+SJe$@h#cm~R1$1qYuOHBRDlE_wdTWSqHy_m0vQKAr-Eo$9D zHw)9J&WGA>KVDR z=u?Y6v*>e+zVN|d`Jq0TmIcUS(1AgFI*ii}_rXRkKqt0|)tSv<W^uAqv+9KJA@FTgNXCpL`Li49|QqIo`QOY?oyjuvpuH4GLq zIF7+0A2dW3`zVtQW3{2B+>K>e>eKOD)p8#=xD^~af!ly#tWFHNGU&i2vNG93)>^hh zwU#bqa2bQk8C=QWDh5|GSj}J!gX{gYg)a8fR=R|(Xr0I4Qa_v*oau-6f@|4;)*Wm> z>pnK1wSmoMoyBIe&S$e(0MD@Lt7qu~Hk*a$^W69woc1raj`by7;fEVsbmQNA;TyWf zPv7#@@3@xlxY+k}5&W%auM|huEQNuRB{f+wVyWhciK< z*&$17Wo1>uas`{Us98|Jd0KYq(M8ubldbSn!r)028|CTJqemA({TXG|ESR?Z`AOES8u&rUnp?T3 z5`y}eU8RIQnuv~V<6AXx+@{s)S!lNLX|E_*u%rf?la=!qE?MEs z6|NZxw^F%iQO%+POjxOys9?0+<=U|-_7})Y5X*?#~nRD>A!idD^-N>3n6C(zg z|HR%^GFxMGnJ#O1FUzGz-LMTZ=R?M}bo|?P1~Xn*-6Y3PTVmeGww0@$^0|v@j(0oj zVRGMND&8SmGc)H^E||m2f|@_G8rw|G=2vTbTXBEZnzez+1$M$!_d{UDWnVmqqsP}+ z;gttgxJ834uUv^?(x%QOSp33$X`X0NO%3+Xx*Xta_ZJxt|L>T6J4knM2cyaEc%}OD zZbJT?4*s9Ab9XSe?I`g7nQh#IxM3GTa5jNcpc}gwwhE(*1-%{2Isc_M$KMegePtbAy<~1y7yh)w zN-X#~VcE&*{cN{wGnU;qBIel1yQNP2=7hN7B^dH5UVv$g)tIhHVEuME>R68$Yv1!0 zTXXC}bibd*^VY+N?A-fkWH!9mPt?*Yx(yk$^>~;&SMZr((J?T2e=H2X%){nHl|Dwu zhbQvzdxFjeJ( zLQC8#7SPTO+n3_@!x%o{ZIsK#lW*h9z5%m7o>{qJ9N{m?PcriT+Aa@HON_^z@ObJ7bVMZnp@Vt9 z#lWVn0e8;^_Gvipet$UF=<%bz%MT#0t3G-kAIY0x-x@wXnO6}?+e&@6XP8^4JRe3) zqN(Ye8cu$gatZ<&W(I6S6lGZ3sB1+=0CsX| zu1?kuA)LeqTBifSIpriEc&8l0IrZ>L=HbQW4X{B}7%~8~aS>Mxk5b3*>C))c+(t&qRw^h6;^ttN zV@R#&2tzQgKI?YI47b8#g|k6? zUl@`Ak&cFwSF<03NOywV9VcrT9qC_?s(Tg8z_TkT2%%T705YVOE~?+9pl-b{7v|>| zYYzuk(L8%Z7^c&3TigfzfenQXif}L=jYQfHMcdy-?JL58a4?+8{ph`w1{9>}u7ol$ zG71XP(G}QzL01g6;v>(}Z`jL^-u2!)#U25M2i|7K$Qy&Lis=38()xYiP}RT!jFiax zz?;GQNalf6P>_P=a8zoD&fQYw`|IC-vXLLquO!)dB`{?&IzJHRnDa^k4Zad&tM^L$ zkyoO7gmDphB{1#7uLSQ19ZSgwa>r89F&qHHKv`A4ODVeb#8<-Y)qN$nv&2`Dl8;8Z zROt5ca-8<{D@hKg;H97+`jy~yp)08wA?`{Vx&liu`WeyBT;7a5QG^EZSg-#?*@(|6 zVIRzE**DTM&?h#^0t$uCvDrGRbiGXHBgS2W0z~q+Nys0Le&}ee?{@BhbpRdUS4yMw z@IiL2J4$SDSBRp2PRn8Es+*!94{NAx2F`w$N2~O40o_(} zU0V`UGCv-iKTgRoQ86XU)&()6!p2^PHrInJvDqElnLNC*i;LlTm(qZmR0k&s{(KNLo=H4ttaq1Y`Yfj!=GW||6RSVz3RIS3->v?v9|M0<{Z&7s{-)nl|Ioiw|I~j_|I+_f|Mp{ z*8xv~wmd~T)iYJ6d&+ds)2cH)n{>$2t8+Y8=)s=P>0HlFJ;Za94tws_!#xk`JkNeT z!t*Pgj|Y)FJctx{{-Q^Dvk}=CsYiQ{M{Hx99_t;C=*A>H#XD2a^3Kw;y$kdl?-D)N zyN<9`&-1qFGH<(H;N7Y#ycg+8?`QNv@8|U*?-zBIcc)(Ly-6=YRHWYfplZRW2^>XiPdWH8pdZqX8dX4u(y%trsGksy*+0UeXu%Ue_1;exfh({Ze1z`?J2( z_o2Sb@5dgcrLXX3W0NvZf66~bf7(9@+mzF>O?isG)?bBv$_D*e|C!jR+@QbUKMOmR zoAplrHhq)-JnU3np>OqHg{{gjV5{o^fRJLdppV}24xSU%PtNp3mG3wd4mmB!b&FEPEi$*Loz93MSuP&}XV;A0DWHjh9x zn!kZ56EAM+X@>3?-&xx0uqz);#!-AXpne-r?*-KF0_y#Mc-Q$uKz$HUe+;NU1%yBO zmw@_fK>aPC{!=_AFA-A}fHVQ=0x|?-3K**D<<|xQjRKaYaur)9<}jAa8!IHqid5cM zDXtS&N(QS^iCZmTjeyeyoFQPXfHMU&3BYg9Q1RO{RQ&b~74~GRuqRW6J(()($yC)Q z;4Bdm+ax|3VNVVc_GFf@CsTzz84~tns<0&nI`PXG+|E$ zggu$A&P~O~GEB)7VM_Yd`SJr`h=8EFAXVk43nc?w_Usg2K0Ade`IxW-AG3LnunE5^ zE_NOl*FH~5lBd*t;?M_1<#Xy`;YU8=@FSlW&g2W~fN&;v3up2!VM_Ar%aZP(+AB;+ zIGC>r1M)Qi-xBa`0j~@A4`G#lM_7^HRo4jflDIbn{7_h+Z_3l#0^Si{L%$SW=C6dc z`D=B5klm8Fe+bj`p920REYL%0e~_X7si4;CVgWp1dnGvsF-luMW>#U16MBbaxG^Oor-0>{{gqsLVpmUXs7Xvu~bSei7IYxNcX zB%K|_xPgfJ3t7<8+&)XHKePWYJEWfIt8t5Pgc(GZajrg{o=fV}=@^-qwMkq$C21a4 z#n(6WG>KpK;swsbvZnSnB0IZgtrG6)vcq#G?dDC^{I2}FSr9ij6*rh*VOP`U%}rf~ zhk4P_GEP$NR^D&f*4ecw(oxlI-90#jN|LlcMd&{pbw;wn_WeYgGn0zVrfI4Mm7kWtaqN3ANy=KW?;9>tc>5#}2qiiz~BF7^8>=@OA8=XuF#cp$0 zp$$Dv&6^mb9}6e;BYB$ltQOt9HE`jgd|Ss1Q`FB@T64sC5LAAQGqp6q!^@8J^|Hv4 z%E1|G{({ctUf~H>b~SBqoMI6hWfZ5hoZZ{hPCgl}_DE(b_87lBc&_U0GR~gh>N49} zs}{ue>?G`1tJQ9Kye4Ht9wW@jXhejK>GD8jOPa_BYC2603tF}aFLH2e!^Y0u_Vs;= zC48AG7}DFtWl}s7I31QQTPjV^3%f%Yz_P&#TiEdy>?G)ty_!!t2_l?dVGqj-MtUpq zwsGerd#uedj@z+KF{m%^xi(|eQ{y8Rw{Uz<0;GG z%_iYuOO(^rk@l2&)!^1hO2_)y)*bDO|5+AvdV5oMk7*@gHAVT%fz9Ub!ccMCH@ggj zrFL|7ZDtG$!zu~qHtDXc6_R!vikpyJ+SpROy`>8QrsDX?{V_3j$M^k?Yt3{HcFxH| zt0OaM4|5DWnr*b$YjI<4$`MPJ>|~_XF}!2Dd}GE9NEvn@{MY|G*vuSl<=BK=rcKDTnb0TqWfOkGuy-SDXYu~BQ{4bWjS9A)&rocvqVZlBs*VToJNdwRibm{HQ;H_;gJ%pwXaY=Q z)aa&q#Sz9}BBtj09#?6+GrYmrT9qi_8{3IRC9Wv;IN5ph?NbwNYLb*}l3}(zK{+mi zlJX>EjHl?Ory*871M~J-=;6<)m5>(JLoe@CPf+eBa1rM*^SXgeKl17SQYA@sN=z>>R0gH zW)oATS)q71jkX$6su0G;i#p+n@)0nfgv)TXzFdtYEb@qZ`=|MkT|YO$?)X?1rZX{#=<|$nl~B`QB6q+*&|~OS z^!(7$l%BfZX_1>vi_kV}Ci&La?nWQ9#1A**GCyvfa(%bi1<&8qRK!n4r3yWD4%3v8Xq)r+yQVgTT zWVI|y7*ym>Xw34LGeMZv1IA|K>)h{?TIosi8oGhcrJ7>2VBZEjJSmdE-gtwMp zvK>qu!A$gMk#Uik_yZBanHFmSV?`6jnh%BeR2@_yEk+qKQ~`{(vBXV7S9T`!!q`fn z)rUs@g8|^Xmc~Yg!pj1L^?iFlr%Wml4&c<>l&NA$x{_yHuS|ohD22*RnG~6ZDNMsN zYj=BoD@7yqUR70!Dd`N*qFnn&`*Bj(dg?YcG;BF2DGT?i+LT)ky%9^WOU(e`OTI>% z$$43-&P~ltiA?KMGp&i(S0AQcmk{rCc(&9lTO)xHtyi|G7ZJPEO7pFgNxpk zr6ovfWKiA_NNV_Vb3|6-f?hPg0qBI?MY^Hi?r}DSYiYXw_B0)2_yv#d5;+ zSh3iSV*cg2R((d-sq6F-wOiM-q&KMjDE2+3SF7jr8udK9?{5))pqtf)dV@~Yn{-fj zVx46R7D>+53v`!0O>fnWdYe8|Z`bYm9NnwW<>@?qslG^G0sO4KQs1mUrSH<8*7xYE z^fUTu{i6PieobGaU)R^`pXkr&Kj|;(f9Nm4XJd2GJ3Yhnjh;OHWzT4RlV`lX*)vVw z;+ds)c^2tgJxla$o-_3Ao;H1lXRE%`bAi6gbFtp-`I5fdbBn&mvs>Tm*{i?ed0OA^ zc}YLud0ju~`GJ1O^S0g#7k$6y_vHN-{g~&F{;D@!Kkgl@pYRUVPk9UVb8yqAdZ+5q z?q!Na%h_~vA?u~EZTCA1c{S_iX^U-VRCDu11ZG0Mh;p2|csvVq!E&?2pFche)$!xR z$N~2C&FUl;`**7urW4t@C+&iLoP}oham&ZcU}F7UEU)LLg#AzX*54+-7MtZ?I-a;& z54~tcif*cJ|O&(c%+}SJaQF7=)roU^yFqZf+L|}QQvR_P7gFPo<_INr6ff;Hn zW{@X(PF5#j3VEJq76*dasvdL5D?O*ER?j@O#Z#uX5r2ti0f&JKb%SRihk-@v4&Hmn zb1M6b&A5Ijo|D;m$M;@6iCtL!rqG1_xrf$vvysX@0Ge$f~=@8L`yPWl|N;0h&G*@d=upCj^LLno39yn2?S!Av8%2 zS=eX=tK?YXCmhbS^2_ouIPY(+hsH>qpZ?l&JZ^V7BzKm>=ES-!vhK@|H<&z`a9bD zj&w)iD&c#~(1y-lsBM*P?U3t)*dAwbE?T3IQ5vb~>}W8oIfqQy#3U>0>S{U%(R6th z1{;qpwiXj4izM?TH)+E}ghb-Y2YI*yqG*&7a%6Jc|ICzv$|J)0%q;t+A@hp?!ytxn zD^kpa3?(z_p zATRAh&UU}bm|K+pq~cnh1`;gwnd`2QE$}51_C2NsY1LpZzuZjTlPQ}T`;fVs_^X(w zr!r5gnWu~K4_kwy=~^62*Wn|!R-NpxS93|DRUx1DsN>@2?N!;H{Trx-{FRfSKU;@A zf*ca-7*?`|-gOJRI(rjcw~Pp=p;)Igj#*geW$Qp@DNR|jVPr-2ijw~ETH`)yrdi@t z5_^zGb^UR4zTdQdG3DZm!!UO>0}F24&&~!GH&Ig?&gnpByr-?%o^H;z6xd+1%#%($ zXM;Khl5vy_KIbF#E1lP~v8{W|WM)NV_X$ZKGOA?9kr^@!!kGLULahADH9}XcNOX8A zP=vTJ`DSKJ8WX@L6TokepsZ>IC8h-V#hYcc>Z9rySw$kzA zcvJ1fVV`3R%ipOaJofrV2J!s%&gM;q37oJiF`RP)Y8WG0O7VZka6aYO2djI+vYQQT zxF3Chhx)cB1aQ}=PqMS5Y;Nh<*cszV4P>M*_&9oA6uTm2i46VN!7Fj-4>dy{rA=qZ z4|hTtuKgeS+0M|Pj643Pl-4M|C1oXWDeP2ND3Fxl`^!)+-KtS&e=zRgbKcEi;^rHd& zSU`U@pdSzDCj$D(fPP8@7k7$?ARt>nj)1`eh6os@ZWNOxfT8NklI|vXx>&JL@M!i0e46)cZxjWU6OdWpm)m?AV=LJPk2U01)gYw;nB+0|_#v=muN;-Ubl=LCFBz}E#lFW?0MFA8``z&8YZQ^3mt4hnchz^n4z*Q5mB67X#S zuS?v22>6bG?@HYFr2D5l0Yd6u(kcIzhWJpxApnaBKnsA1K2&=tn)Xp< z0Ye0Yv|r*RHis8{N-L5|G$Oj)gG1@#(9vPRbi_2~l6 z(1UTIB0n_gOuVOPE2x_VtQXLtD}%aKe%&DMS2oHUZGxU9V3W=YLa^a!v(63b4gsBl zZjq<6_0S;1oq0jsts8>6N1l3hT@YdqV4HyLdSMWHPkj)A58x9Lcb`tG z^#X3tIYCH8V}g2z9u?F(CGJK6U)B?X`X+h0S!W0JEjkp`x60G)0`8C>?hcava5kEAK=tV*Ow4l!jcvepqFh#&r0n>u|IUNq_7xaiA+wPT1L>Y0N}K*jz?%Zz67XXIKN0X# zDaOwP{9LmM%BkW=E^UU!T?b>gJudr64fV(+sJl37+Q2d8f?uwrsa^N|hzL<%@yyC5 zu@rDl)#fej(L1OuuAAKSPW0k;IMLczyt%U3mI%mt;W$JH`?HBQc434A&1n0qJEpvo zqP1*qM7Xr7qqUQq9N}FFxR(0IA)6@l9>OXy*kgoxSIN^XqK^E@n8bx#T%!U(<{ohF zQQz)1SKeYyB;5!;Q{B!Eb6=4nH*v2=`1L4Nj(y*e&RUEcJ?V%c2n#1AYfVlnMI0wP z<7Cx^j8L6|9e9vwJn?hOF*@*zSi|iAf68|IO*) z?@=bPOxUDC?Zh9Gcdoch9Ez}HegrbwF&fD#Oh!j=k8%0j=%XbvE7O@rO~n#+lojg; z(?gcLg~>kQ8p4Nv-MtY=l?F^dNgcO(H7hYdwz1W2J5~{rJwNtc-Q20AeH|k<%*{w@ zcdS;|O5PvChGO#n81i8Ynk`m>@b#2dzG!L9X=@jkH6V?iZX*qgswx|!KQ&aXs$eIx zb>|YLV=dI$bwVI)Xn{{MlCw$krllQiXZN<$ zAqd)rCO~B1bH=3cO#&=}F0Ctr8D|s)+y_X=yv-P|YjF*FiLw;{fMocWmb-Xl`M7p}tUPZD@w5tuJui83f z>4{xB87_PzAxcac#zi^9e^_FCtj9<3Q~6OAkRg&LwgSao7PXc5!7VBB_^a6cxp%??Y#Zn+C@pC2@2{xYOBFcBL%Iaiuo# z&V-HsLFR_D%8rcXlzfs6CqYytDoR{&svY9T=!}Y}ib>x_w4D-Pkg1StBF1=|<6;yO zBYa@KRNLEA+d5xtba%UKOeD8FF*24x4eLu?Cra!sU9Q($%q9Db!laG8(-3E#(;Qi% zG`&bd*FlE!f4h;3NM+}b=&>d8s*3vFOb&M{Ke{5+kwu7_ZRPbSbN9$X6;A3zRd+al zeM_A5C?CJf99j7&_A%G|IVLTqXstdf%lczt1RetqGOD08|A;Nyuai3`TC){8bKAv^ z#ALnE%*#S2DQ?Gsn35P3+b>4((@{4YNt0}|$uK`ek3DQH@e%H=CE*v>))N0qbZa3x z$<`vVN7!2U`LJ6{>^J)~JS0BCwf@Kd5L^GHdam*7I^`6_|8nG&KHHtxtkkUDadGZN zI`+e17HJY3ev#(KK8tiNk;xWfw+5SImo&Slb4zv0))pgmDb2<{JJ=n!uxpDG9Zf1N z^gq27*kG6vc3dA3ae!`aF(c*RPIMnH~ zk*XiLPp#x}2#=%osZ~4<=CNR(T2T~u9-;Sr=vVOodtWumLn;pyk)LWJKh;Ja>gB;A zO+)0NI`VLuJV=I%BM)_vhb57RMUe-iuU08aYYPONO1VU-3n{qkV~?MUJzg7oye{_m z+1TUfC7Y#1A>eXR7%LTEROBW^zFB2tlJs2K?Rq2qw+z9ICL|ZuAs5@Mj#pi%19l^6 z(SvuJUNwhsp4zIa)HYNEwyV|Z9Mk~MRh!i(h&>OBW9O?Yu|@V-bhj{BgazL#P>%d0 z*2Jzv$@0@^>|KTFp{vE1kovK@M*T)zi#ff|Vj$>x3{VR|sDDNt!-0LOL>>_Fy+OiU|2{R-{F1Uyoor&P zeM+=zR^%c8Tvn8qYw|dt&Wp8ykumfhhdsgq{6>ya!@Y(0h#alPd&l4t@_04JdjdWn z$EhXWJjw=t-6`8aMXm5^LUe3Cm21VyTO#s0p105d__50H`~)??pQ{r+zfe;=Z=)^tjw<*3 zQdN6?jpYAt)EdvbYQ5(@waN2$>aao=ICZ$2t`+6T^?6y=xh4L*Y<1{@k`x-}fSR{F z&vOUUXRm6=^@|4Ai$=}WMjlsLOpyGB$JMZv%+l`*v-D;ud9<|tWuWIz%r3HlTqHF2EbAz$&GMbxSgtfff_Prj4mscI<_2C88uO@m^807&q%WJ9m-ZVU&rmIG85Rayq zJ>z+cH&bo*X5qOs8;_+Sb)7c{FQtR=PMS-@AU0w*jAt&g_b9jMtrWU+hYI9i(Q{4L+0n!NX!LAd7_P6zQ@Ukj}CVp#jLR?;K>)QUCdSU zxTC~pKWwFc?H^^N(jCPmzFdFShr1O0<8v~V?kP42DQyUatX$HV;_X&r<@H<^C$m_{ zP&MV3bt`G{$l-)&eVxLPyAwq@+(f6aSt@OPrUEhaf_5H{VJ*e{0H65){ zhGbJH)B7>sctEYvUsX-|an;6dxdjuX+w@bYbUm)l(@(1_^)u>v{VeP9bLw{eyt+@n zh+5Z6sC0cpy`o=M-_r*%b^40>wSEngrr*YN>FbEWen(qKr(`0Wl1Dfa(Uh@Brc7q% zKN-1{`3R$&s(*m_0P6XkIVMo9dm!fHwNmdzKqb`b84| zlz-y^wSAvjWTF-lwJ;L3&_q=cRTYVXr25;qUuc45~7wwqL!GbdZOwhdDWXJX}$&%b*>!2 zB(KxtFA{Z{iK-^5IucdwbigvFsYPKqiv+aAh^!B5MLC(Cx%JTRiEETJPpU!knF{+k zPo8U>cX_OJC8>8kH`vcvlKeE+bG7Svu{=MKCQ0gIk4v0KXAIyu z-k13M2JWq2R)f6<)mZN!d+FEJ4)1^9GWt8}Y43N{>)!9F zcf4=l-uWf%t#epOzIM5jcfZ#M~xiXt&aYb2}4%Jt=$?2N|92;cf! z552!zZ6)U^MZR30`IM-`&o(-eq|bBKUZeGzKVrSS@!oFi|BKND^SduGzgR|?s17)( zQtVU#of{w*z8YI|b)i~Bm#o6B`Wk#!uf^+l6MO7B74|lBnp}_f@h0}$wVWzj@i@K_ zLltc-+-IrD-c4!>_;liDdN-?bZ>Os8ZsD|fwp!@zQj5T=iLdqcsHNU>)pGAAjMwp% z-t(E}=i+(%LcES&gi6}Qcpkq*wRtba`}jq8AHPtY!#n4BuVUZ68VeJjQJ3MF{BrNL z42`SRRd{^929M;Q_g=4Vz!Uiw@j|`>59B++Zzlde-n$=<<9qQoE}q5@;AQ+VJdA%8 z{3+tU;oYTP_TH*q@!p1~@!QpF;NS7yftT?+@iKmwdW*I4C*Hg9Hh!mioA}>*zrtWa zG}9h3+#$Ri{*;=RhcWsYMRM-JnED!79_4tyS8bWV-!3&I8u29}zO+mE^Y;|7b8kjl zcGsbAdSZ*Xu^-?qQ6BFM<@e51nfPBQ@RriLv(z;29Cb4BbG@hV{i~v-nCX;aaGr;p zJ)BiIouRA5?P7H-XJgL6JAqs$vRW3?zmv)3YHSsl10l*!q5*-Rz;KXrCjJX2PHoHC$)uC>nhFjyvp*tz_A=}@FKU{j|>+j&+sua{3;o8XYf2hhEI{z=lYdl zRq_l6lVL6yq66d^N`~TE_VZe{Xz2>~SU5GY*RYwRzmRk+lqQaayGe?uvXiT;A#W33 zxA9GhweWn$^R1i`OhaN_-mhnat)0d`zCr9p~w8MKWIL za~KBaLQy%7+MKU)^aZLwU#Q0Gi`7Z`5;ad>t`_P~s#<-es>ineYJDvS+w0V3{aJN^ zzMjMEwdxBRny4IpxWI64ieV_cAV1!O{HA(4yd+LD{Q@JPEUs43KdQkRk@icm~J>2FOGPNHGIs zG6Q591EfUN=o#t^=IMHVZ3KoUvSDc7? z#bihaGtjV@%ax^yyU0qED%PS-u?cO8UX&>=-^TZ)ZIuz7w?I)+(`dPqb$qM)^1$>SIew_k7PXS*bL$qJ|Q^3X~1yp}w zjr}VG(*I;EvX zPfhZ=b%fVZJ52HURHhFigQx~2c|G+AuY3Q^*FWUzhZq7V6*;eq)j_E{#6~&)xd`00 zp}M6i;A!NIujvz=Hwu|$Lgm1-1nh?xjnqy*mZQ!Ir2Kk>t)j-0T8_Hua-=L3Fh2H@ zX;)7nFOBAWG>Q*BpZr6Wv3Kkbjpv;r(xV#X6in<6K&rrmK;DD{>ionP7DK(oPll*b zIWN?ZT+YCSa@IUf7Rb5wdB#_ie?Xlg7mJ1Yn712I8_Ua>0Kr|G-}5R3eobY2zJ&$A zZ)3&gAbF#m)&IN~CC~do@_vZCA13cd$a^n&KR~W1ef2-@s^obG$$Joav({lwZ>T4W zyyg7;O+CrUJFa(6jn&(3^kUwZlrKknSJF%GrkLJMOh1zJ`Q(qTTA#8fG`CH?A4Hp1 zNZBVe#PYJ+d=q)KtDt8yRu?-cdnaW-i@Z^RbMlTK0GGxxunRwr0dNX0pf1<{!YoeS zkmpmF3ns>wn&L$@9K~ygy0aSCaRq$otdeeK~of+}HoSmn6>{ zn|Ge;$osS8eLZ=9j=bTP>2I5@N^T>uNpaW?s!!fQUn1`vlY?cFMFhAvG=@0rF2 zr;`2+jnnca|yK5`%{3ix3)n;5Y#V0!9fa6fj!A7y-u% zI6=Tz0pkRmD4QPHQW~r}Q>TydwVW}rA^^~Qa zw$wA0de&0US?X(+`nsi_x73T4ddX7Xu+%p#^|GZ7TIv-`y=tk~EcGo*y>6)=TIxrZ zdec&GS?b4@`iZ4}YN?-D>KB%J$5Owt)UPe|8%w=wsoz@aJxl%0Qtw;p@0Qj9^^bu1 zXF&Zcp#B|D9|qK+fLKlN1T>t(?dmgWhz4AfhFpLF*QTlq)pY_sE8zMxgatmAhP1%v z1$;rk4U+haX-E^`)@Zl-vVdEI+y-t5sz0jl1l6C^cY{a^{65He^7bGH%3T6(3v#Ty zImn@RXHcggH=uL@;ye)@<^;`+NVE}nG=}PaWsk@4axXi;u1PqAxRS+ zql24CNes!kRWwDnQ>E>%yb-bc*(Itz6v8+DK9cRSGBu`$6YTJb=^|Te!qB4$UTeje5 zqp72r@8l)?R@GrdSDh*+zPY#;Zx7~eL>KKh9q~SQo{8FhL8sN6rWh2FQgra45qwE+ zQ~Of%Shj5G>@v-m75PPKWH(#Jg5E9dZOy3aRJOIW(*wb11U-dmyC`aF6R{yxwD-`$ zwH@u}RCO$F+umY4h6svsOC?G_=*`4^HDq#L+}qyMhQgAuV~@CDrM$VItrfMMZX;LN z+(U8sKK-+~si(3DvvE=!W5%$p*{RzQM?Kz%e7Z-7C^=?VwYRryFa{c(7LvG*=1zQ- zG)HAQ8Dz0Ix5`PT(^vCRuCf~^L=%|uwshCDwYQ5MJ?cm#f`b(uoxK}2ntnwjG2M== z6e)4$Iv7pVCsmdmZv@I65%?TCiqtJ#q<1ptYh*7h2Jq;D&W=c}d2|{jsg|Y_>7LhG z4R@_9eO9RK#SIJB&M#Yl*6FFW_2sn-DyXc)Ro2$yS7~i!SylDYdLn}oxwve_T04y; zXiaU6Np7ZCtz*StW1Ebq!8Od}mi6|4k>PERmCTw>rqx2Iy(}isV3GV8N`EZy*%f@$a$gF-Ue6`TI0u#IOy5nq+>WU9a37& zBu2>&l?!_dw4WncNWA??4AF1w>Df|RT)b`Dwn^Kj8MC8}^~Kvaw@lEd^7N694~eC>qauEZhMFIG=*(iLYWBj!24Q|N6DzSD#vorm z$#yj}$#yj}X><36NpT~K=1HQGA=!0{H@SoZI-17)k=c*?Lga8ylOt#yX>ylekHA)u zW3J^c#QAPJmy8RzMTDUg{|C>uLycapAe`hl@p|MiM;KP$6XK%tyIf4(aN!>Cw_Lav z{3RFe1K;Dq{op@#;VIz1a^V=WQ_r|?3;aheTuePZ?ZU-8*H2t{I`~grxYz@J+=XMO z9)Fy%`ecAV@4_>|-*e$v;9qg!+2C)w@DTVnTzC%ni!OXH`1>wA7yL07J_P*NE*vf; zB;8o~hJpXag@?f(b>YLo?{ndK;IF&z5#T>_;rZb2y6}%vb2f6av#f#2=I$AiD@ z!Y6<~;KC<@KjgwEfxqLzi^1=8;giAdap6%g=1=4{nmv~2jB0) zOTZs-;WNPZx$v3bdtEp-k6{(X#z!gm4_vs+PwrpLTM_fQ3zt1wT<0KDA;e~-S7x33 zq&jz{H#EOtr7yI!VWmIR+ORSuw6bAkAT+OGr4`!Hurezpv>6x()dQ{2dSGg32{0|R z5ttro0|q%Gtjrn|ss?6+mIE_GUBIkR88AE40t|�dqntfP+Ilz}(Pjz#*Xy;Ly-A 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

W~ko&(yTY^8lxCnFEr=!W4sWtrn;jk#&n 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鎋td~>C)6Qe+)d^5i+x`QK4_C1{m7j} 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


~ zJ~?UkDLhZ4Tj6_-V_+i@`9kIu`Aq5_@5nq!FheT8t&t7;_dqv5#Oq|&3r5h?8Zrxu z41E!Lj2;>L0+LF^$H%0X%`mfoD0dX4l_x9kNKovw7ql z9b9gPDbmtqSDoky6e6C@Yv1EYin|U%=^35AN!c8A^QnlAKqBHj!JqHz&`kX=3G3Zq z)t5!1xQLpvA}c)2vCw8yDO9LwMr)qk7Wy-iMZ{;yhd!zZH^e!=5J%RVBK}#tf5BRe zH$;tC0>3}Q5j`;SFm9CBxVP@x>c({k_pfjWLBvrbF3V9poaAO!uMVE61}z!HmAL%6 zf#J&sn|Hgs{k98*OVpDU#hL^;F6N7+PIp=X<_u1EBI_wVKgu~BI?*TdD7tc@mW)#l z+yrT8)E7GABnN%r!ym_7LcdAGK_`tc12y$WI{itjJ_Q)Pi8$z;qvW92qpuE;#sczM zlhL1Ug}f2*f*x382&x`bTA{2(lV?tBBq`rew8XI+MD5pg$*#_Kthr$Nhe z+I9Ks?-XD#AmVNoxf?i)Dxz|fW6#xmuLI + * Typically used in LdapTemplate's search methods. AttributeMapper objects are + * typically stateless and thus reusable; they are ideal for implementing + * attribute-mapping logic in one place. + *

+ * Alternatively, consider using a {@link ContextMapper} in stead. + * + * @see org.springframework.ldap.LdapTemplate#search(Name, String, + * AttributesMapper) + * @see ContextMapper + * + * @author Mattias Arthursson + */ +public interface AttributesMapper { + /** + * Map Attributes to an object. The supplied attributes are the attributes + * from a single SearchResult. + * + * @param attributes + * attributes from a SearchResult. + * @return an object built from the attributes. + * @throws NamingException if any error occurs mapping the attributes + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java new file mode 100644 index 00000000..7a8874c1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * An AuthenticationSource is responsible for providing the principal and + * credentials to be used when creating a new context. + * + * @author Mattias Arthursson + * + */ +public interface AuthenticationSource { + /** + * Get the principal to use when creating an authenticated context. + * + * @return the principal (userName). + */ + public String getPrincipal(); + + /** + * Get the credentials to use when creating an authenticated context. + * + * @return the credentials (userName). + */ + public String getCredentials(); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java new file mode 100644 index 00000000..a7d55dbd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.InvalidDataAccessResourceUsageException; + +/** + * Thrown to indicate that an invalid value has been supplied to an LDAP + * operation. This could be an invalid filter or dn. + * + * @author Mattias Arthursson + */ +public class BadLdapGrammarException extends + InvalidDataAccessResourceUsageException { + + private static final long serialVersionUID = 961612585331409470L; + + public BadLdapGrammarException(String message) { + super(message); + } + + public BadLdapGrammarException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java new file mode 100644 index 00000000..6f42103d --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.LinkedList; +import java.util.List; + +import javax.naming.NameClassPair; + +/** + * A NameClassPairCallbackHandler to collect all results in an internal List. + * + * @see org.springframework.ldap.LdapTemplate + * + * @author Mattias Arthursson + */ +public abstract class CollectingNameClassPairCallbackHandler implements + NameClassPairCallbackHandler { + + private List list = new LinkedList(); + + /** + * Get the assembled list. + * + * @return the list of all assembled objects. + */ + public List getList() { + return list; + } + + /** + * Pass on the supplied NameClassPair to + * {@link #getObjectFromNameClassPair(NameClassPair)} and add the result to + * the internal list. + */ + public void handleNameClassPair(NameClassPair nameClassPair) { + list.add(getObjectFromNameClassPair(nameClassPair)); + } + + /** + * Handle a NameClassPair and transform it to an Object of the desired type + * and with data from the NameClassPair. + * + * @param nameClassPair + * a NameClassPair from a search operation. + * @return an object constructed from the data in the NameClassPair. + */ + public abstract Object getObjectFromNameClassPair( + NameClassPair nameClassPair); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextAssembler.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextAssembler.java new file mode 100644 index 00000000..da2ef350 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextAssembler.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * Helper interface to be used by Dao implementations for assembling to and from + * context. Useful if we have assembler classes responsible for mapping to and + * from a specific entry. + * + * @author Mattias Arthursson + */ +public interface ContextAssembler extends ContextMapper { + /** + * Map the supplied object to the specified context. + * + * @param obj + * the object to read data from. + * @param ctx + * the context to map to. + */ + public void mapToContext(Object obj, Object ctx); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextExecutor.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextExecutor.java new file mode 100644 index 00000000..70ac8790 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextExecutor.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface for delegating an actual operation to be performed on an + * DirContext. For searches, use {@link org.springframework.ldap.SearchExecutor} in + * stead. A typical usage of this interface could be e.g.: + * + *

+ * ContextExecutor executor = new ContextExecutor(){
+ *   public Object executeWithContext(DirContext ctx) throws NamingException{
+ *     return ctx.lookup(dn);
+ *   }
+ * };
+ * 
+ * + * @see org.springframework.ldap.LdapTemplate#executeReadOnly(ContextExecutor) + * @see org.springframework.ldap.LdapTemplate#executeReadWrite(ContextExecutor) + * + * @author Mattias Arthursson + */ +public interface ContextExecutor { + /** + * Perform any operation on the context. + * + * @param ctx + * the DirContext to perform the operation on. + * @return any object resulting from the operation - might be null. + * @throws NamingException + * if the operation resulted in one. + */ + public Object executeWithContext(DirContext ctx) throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextMapper.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextMapper.java new file mode 100644 index 00000000..a9effe00 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextMapper.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.directory.SearchResult; + +import org.springframework.ldap.support.DefaultDirObjectFactory; +import org.springframework.ldap.support.DirContextAdapter; + +/** + * An interface used by LdapTemplate to map LDAP Contexts to beans. Responsible + * for mapping from LDAP Contexts to beans. When a DirObjectFactory is set on + * the ContextSource, the objects returned from search and + * listBindings operations are automatically transformed to + * DirContext objects (when using the {@link DefaultDirObjectFactory}, you get + * a {@link DirContextAdapter} object). This object will then be passed to the + * ContextMapper implementation for transformation to the desired bean. + *

+ * ContextMapper implementations are typically stateless and thus reusable; they + * are ideal for implementing mapping logic in one place. + *

+ * Alternatively, consider using an {@link AttributesMapper} in stead. + * + * @see LdapTemplate#search(Name, String, + * ContextMapper) + * @see LdapTemplate#listBindings(Name, ContextMapper) + * @see LdapTemplate#lookup(Name, ContextMapper) + * @see AttributesMapper + * @see DefaultDirObjectFactory + * @see DirContextAdapter + * + * @author Mattias Arthursson + */ +public interface ContextMapper { + /** + * Map a single LDAP Context to an object. The supplied Object + * ctx is the object from a single {@link SearchResult}, + * {@link Binding}, or a lookup operation. + * + * @param ctx + * the context to map to an object. + * @return an object built from the data in the context. + */ + public Object mapFromContext(Object ctx); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextSource.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextSource.java new file mode 100644 index 00000000..fa104841 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/ContextSource.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.directory.DirContext; + +import org.springframework.dao.DataAccessException; + +/** + * Interface used to retrieve and authenticate LDAP contexts. + * + * @see org.springframework.ldap.LdapTemplate + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public interface ContextSource { + + /** + * Gets a read-only DirContext. The returned DirContext must be possible to + * perform read-only operations on. + * + * @return A DirContext instance, never null. + * @throws DataAccessException + * if some error occurs creating an DirContext. + */ + public DirContext getReadOnlyContext() throws DataAccessException; + + /** + * Gets a read-write DirContext. + * + * @return A DirContext instance, never null. + * @throws DataAccessException + * if some error occurs creating an DirContext. + */ + public DirContext getReadWriteContext() throws DataAccessException; +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java new file mode 100644 index 00000000..a7eba9e5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; +import javax.naming.NamingException; + +/** + * The default NameClassPairMapper implementation. This implementation simply + * takes the Name string from the supplied NameClassPair and returns it as + * result. + * + * @author Mattias Arthursson + * + */ +public class DefaultNameClassPairMapper implements NameClassPairMapper { + + /** + * Gets the Name from the supplied NameClassPair and returns it as the + * result. + * + * @param nameClassPair + * the NameClassPair to transform. + * @return the Name string from the NameClassPair. + */ + public Object mapFromNameClassPair(NameClassPair nameClassPair) + throws NamingException { + + return nameClassPair.getName(); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java new file mode 100644 index 00000000..6c27b5c7 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java @@ -0,0 +1,96 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.CommunicationException; +import javax.naming.ContextNotEmptyException; +import javax.naming.LimitExceededException; +import javax.naming.NameAlreadyBoundException; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import javax.naming.directory.InvalidAttributesException; +import javax.naming.directory.InvalidSearchControlsException; +import javax.naming.directory.InvalidSearchFilterException; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * The default implementation of NamingExceptionTranslator. + * + * @author Mattias Arthursson + */ +public class DefaultNamingExceptionTranslator implements + NamingExceptionTranslator { + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.NamingExceptionTranslator#translate(java.lang.String, + * java.lang.String, java.lang.String, javax.naming.NamingException) + */ + public DataAccessException translate(NamingException namingException) { + + if (namingException instanceof NameNotFoundException) { + return new EntryNotFoundException("Entry not found", + namingException); + } + + if (namingException instanceof InvalidSearchFilterException) { + return new BadLdapGrammarException("Invalid search filter", + namingException); + } + + if (namingException instanceof InvalidSearchControlsException) { + return new InvalidDataAccessApiUsageException( + "Invalid search controls supplied by internal API", + namingException); + } + + if (namingException instanceof NameAlreadyBoundException) { + return new DataIntegrityViolationException("Name already bound", + namingException); + } + + if (namingException instanceof ContextNotEmptyException) { + return new DataIntegrityViolationException( + "The context needs to be empty in order to be removed", + namingException); + } + + if (namingException instanceof InvalidAttributesException) { + return new AttributesIntegrityViolationException( + "Invalid attributes", namingException); + } + + if (namingException instanceof LimitExceededException) { + return new SearchLimitExceededException("Too many objects found", + namingException); + } + + if (namingException instanceof CommunicationException) { + throw new DataRetrievalFailureException( + "Unable to communicate with LDAP server", namingException); + } + + // Fallback - other type of NamingException encountered. + return new UncategorizedLdapException("Operation failed", + namingException); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DirContextProcessor.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DirContextProcessor.java new file mode 100644 index 00000000..59f873f5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/DirContextProcessor.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface to be called in search by LdapTemplate before and after the actual + * search and enumeration traversal. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface DirContextProcessor { + /** + * Perform pre-processing on the supplied DirContext. + * + * @param ctx + * the DirContext instance. + * @throws NamingException + * if thrown by the underlying operation. + */ + public void preProcess(DirContext ctx) throws NamingException; + + /** + * Perform post-processing on the supplied DirContext. + * + * @param ctx + * the DirContext instance. + * @throws NamingException + * if thrown by the underlying operation. + */ + public void postProcess(DirContext ctx) throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java new file mode 100644 index 00000000..9bd81eb9 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataRetrievalFailureException; + +/** + * Represents that an entry could not be found. + * + * @author Mattias Arthursson + */ +public class EntryNotFoundException extends DataRetrievalFailureException { + + private static final long serialVersionUID = -1268390922996332424L; + + public EntryNotFoundException(String msg) { + super(msg); + } + + public EntryNotFoundException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapOperations.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapOperations.java new file mode 100644 index 00000000..8cdc0829 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapOperations.java @@ -0,0 +1,1350 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.directory.Attributes; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; + +/** + * Interface that specifies a basic set of LDAP operations. Implemented by + * LdapTemplate, but it might be a useful option to use this interface in order + * to enhance testability. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface LdapOperations { + /** + * Perform a search using a custom context processor. Use this method only + * if especially needed - for the most cases there is an overloaded + * convenience method which calls this one with suitable argments. This + * method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. + * The actual search is delegated to the SearchExecutor and each found + * SearchResult is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * The SearchExecutor to use for performing the actual search. + * @param handler + * The NameClassPairCallbackHandler to which each found entry + * will be passed. + * @param processor + * DirContextProcessor for custom pre- and post-processing. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted as no entries being + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler, + DirContextProcessor processor) throws DataAccessException; + + /** + * Perform a search. Use this method only if especially needed - for the + * most cases there is an overloaded convenience method which calls this one + * with suitable argments. This method handles all the plumbing; getting a + * readonly context; looping through the NamingEnumeration and closing the + * context and enumeration. The actual search is delegated to the + * SearchExecutor and each found SearchResult is passed to the + * CallbackHandler. Any encountered NamingException will be translated using + * the NamingExceptionTranslator. + * + * @param se + * The SearchExecutor to use for performing the actual search. + * @param handler + * The NameClassPairCallbackHandler to which each found entry + * will be passed. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted as no entries being + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform an operation (or series of operations) on a read-only context. + * This method handles the plumbing - getting a DirContext, translating any + * Exceptions and closing the context afterwards. This method is not + * intended for searches; use + * {@link #search(SearchExecutor, NameClassPairCallbackHandler)} or any of + * the overloaded search methods for this. + * + * @param ce + * The ContextExecutor to which the actual operation on the + * DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws DataAccessException + * if the operation resulted in a NamingException. + */ + public Object executeReadOnly(ContextExecutor ce) + throws DataAccessException; + + /** + * Perform an operation (or series of operations) on a read-write context. + * This method handles the plumbing - getting a DirContext, translating any + * exceptions and closing the context afterwards. + * + * @param ce + * The ContextExecutor to which the actual operation on the + * DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws DataAccessException + * if the operation resulted in a NamingException. + */ + public Object executeReadWrite(ContextExecutor ce) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the search. Note + * that if you are using a ContextMapper, the returningObjFlag needs to be + * set to true in the SearchControls. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + */ + public void search(Name base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler); + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler)} + * for details. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + */ + public void search(String base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler); + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the search. Note + * that if you are using a ContextMapper, the returningObjFlag needs to be + * set to true in the SearchControls. The given DirContextProcessor will be + * called before and after the search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @param processor + * The DirContextProcessor to use before and after the search. + */ + public void search(Name base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler, DirContextProcessor)} + * for details. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @param processor + * The DirContextProcessor to use before and after the search. + */ + public void search(String base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. Use the specified + * values for search scope and return objects flag. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param returningObjFlag + * Whether the bound object should be returned in search results. + * Must be set to true if a ContextMapper is used. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(Name base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. Use the specified + * search scope and return objects flag in search controls. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param returningObjFlag + * whether the bound object should be returned in search results. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(String base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The default + * Search scope (SearchControls.SUBTREE_SCOPE) will be used and the + * returnObjects flag will be set to false. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(Name base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The default + * Search scope (SearchControls.SUBTREE_SCOPE) will be used and no the + * returnObjects will be set to false. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(String base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Only search for the + * specified attributes. The Attributes in each SearchResult is supplied to + * the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means returning all attributes. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Only search for the + * specified attributes. The Attributes in each SearchResult is supplied to + * the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means returning all attributes. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * default seach scope will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, AttributesMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * default seach scope will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, AttributesMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. Only + * look for the supplied attributes. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means all attributes. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. Only + * look for the supplied attributes. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means all attributes. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * default search scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, ContextMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * default search scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, ContextMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link NameClassPair} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void list(String base, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link NameClassPair} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void list(Name base, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects to the + * supplied NameClassPairMapper and return all the returned values as a + * List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link NameClassPair} + * to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(String base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects to the + * supplied NameClassPairMapper and return all the returned values as a + * List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link NameClassPair} + * to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(Name base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(String base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the contexts bound to the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(Name base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the specified + * NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link Binding} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void listBindings(final String base, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the specified + * NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link Binding} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void listBindings(final Name base, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the supplied + * NameClassPairMapper and return all the returned values as a List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link Binding} to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(String base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the supplied + * NameClassPairMapper and return all the returned values as a List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link Binding} to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(Name base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(final String base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(final Name base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(String base, ContextMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(Name base, ContextMapper mapper) + throws DataAccessException; + + /** + * Lookup the supplied DN and return the found object. WARNING: This + * method should only be used if a DirObjectFactory has been specified on + * the ContextFactory. If this is not the case, you will get a new instance + * of the actual DirContext, which is probably not what you want. If, + * however this is what you want, be careful to close the context + * after you finished working with it. + * + * @param dn + * The distinguished name of the object to find. + * @return the found object. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn) throws DataAccessException; + + /** + * Lookup the supplied DN and return the found object. WARNING: This + * method should only be used if a DirObjectFactory has been specified on + * the ContextFactory. If this is not the case, you will get a new instance + * of the actual DirContext, which is probably not what you want. If, + * however this is what you want, be careful to close the context + * after you finished working with it. + * + * @param dn + * The distinguished name of the object to find. + * @return the found object. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn) throws DataAccessException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, String[] attributes, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, String[] attributes, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, String[] attributes, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, String[] attributes, ContextMapper mapper) + throws DataAccessException; + + /** + * Modify an entry in the LDAP tree using the supplied ModificationItems. + * + * @param dn + * The distinguished name of the node to modify. + * @param mods + * The modifications to perform. + * @throws DataAccessException + * if any error occurs. + */ + public void modifyAttributes(Name dn, ModificationItem[] mods) + throws DataAccessException; + + /** + * Modify an entry in the LDAP tree using the supplied ModificationItems. + * + * @param dn + * The distinguished name of the node to modify. + * @param mods + * The modifications to perform. + * @throws DataAccessException + * if any error occurs. + */ + public void modifyAttributes(String dn, ModificationItem[] mods) + throws DataAccessException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters + * may be null but not both. + * + * @param dn + * The distinguished name to bind the object and attributes to. + * @param obj + * The object to bind, may be null. Typically a DirContext + * implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void bind(Name dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters + * may be null but not both. + * + * @param dn + * The distinguished name to bind the object and attributes to. + * @param obj + * The object to bind, may be null. Typically a DirContext + * implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void bind(String dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children - + * if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn + * The distinguished name of the entry to remove. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(Name dn) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children - + * if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn + * The distinguished name to unbind. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(String dn) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn + * The distinguished name to unbind. + * @param recursive + * Whether to unbind all subcontexts as well. If this parameter + * is false and the entry has children, the + * operation will fail. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(Name dn, boolean recursive) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn + * The distinguished name to unbind. + * @param recursive + * Whether to unbind all subcontexts as well. If this parameter + * is false and the entry has children, the + * operation will fail. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(String dn, boolean recursive) throws DataAccessException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj + * parameter or the attributes parameter (or both). One of + * these parameters may be null but not both. This method assumes that the + * specified context already exists - if not it will fail. + * + * @param dn + * The distinguished name to rebind. + * @param obj + * The object to bind to the DN, may be null. Typically a + * DirContext implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void rebind(Name dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj + * parameter or the attributes parameter (or both). One of + * these parameters may be null but not both. This method assumes that the + * specified context already exists - if not it will fail. + * + * @param dn + * The distinguished name to rebind. + * @param obj + * The object to bind to the DN, may be null. Typically a + * DirContext implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void rebind(String dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn + * The distinguished name of the entry to move; may not be null + * or empty. + * @param newDn + * The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws DataIntegrityViolationException + * if newDn is already bound + * @throws DataAccessException + * if any other error occurs. + */ + public void rename(final Name oldDn, final Name newDn) + throws DataAccessException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn + * The distinguished name of the entry to move; may not be null + * or empty. + * @param newDn + * The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws DataIntegrityViolationException + * if newDn is already bound + * @throws DataAccessException + * if any other error occurs. + */ + public void rename(final String oldDn, final String newDn) + throws DataAccessException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapTemplate.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapTemplate.java new file mode 100644 index 00000000..6c462737 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/LdapTemplate.java @@ -0,0 +1,1379 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.PartialResultException; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import org.apache.commons.lang.Validate; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Executes core LDAP functionality and helps to avoid common errors, relieving + * the user of the burden of looking up contexts, looping through + * NamingEnumerations and closing contexts. + *

+ * Note for Active Directory (AD) users: AD servers are apparently + * unable to handle referrals automatically, which causes a + * PartialResultException to be thrown whenever a referral is + * encountered in a search. To avoid this, set the + * ignorePartialResultException property to true. + * There is currently no way of manually handling these referrals in the form of + * ReferralException, i.e. either you get the exception (and + * your results are lost) or all referrals are ignored (if the server is unable + * to handle them properly. Neither is there any simple way to get notified that + * a PartialResultException has been ignored (other than in the + * log). + * + * @see org.springframework.ldap.ContextSource + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplate implements LdapOperations, InitializingBean { + + private static final Log log = LogFactory.getLog(LdapTemplate.class); + + private static final int DEFAULT_SEARCH_SCOPE = SearchControls.SUBTREE_SCOPE; + + private static final boolean DONT_RETURN_OBJ_FLAG = false; + + private static final boolean RETURN_OBJ_FLAG = true; + + private static final String[] ALL_ATTRIBUTES = null; + + private ContextSource contextSource; + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + private boolean ignorePartialResultException = false; + + /** + * Constructor for bean usage. + */ + public LdapTemplate() { + } + + /** + * Constructor to setup instance directly. + * + * @param contextSource + * the ContextSource to use. + */ + public LdapTemplate(ContextSource contextSource) { + this.contextSource = contextSource; + } + + /** + * Set the ContextSource. Call this method when the default constructor has + * been used. + * + * @param contextSource + * the ContextSource. + */ + public void setContextSource(ContextSource contextSource) { + this.contextSource = contextSource; + } + + /** + * Specify whether PartialResultException should be ignored + * in searches. AD servers typically have a problem with referrals. Normally + * a referral should be followed automatically, but this does not seem to + * work with AD servers. The problem manifests itself with a a + * PartialResultException being thrown when a referral is + * encountered by the server. Setting this property to true + * presents a workaround to this problem by causing + * PartialResultException to be ignored, so that the search + * method returns normally. Default value of this parameter is + * false. + * + * @param ignore + * true if PartialResultException + * should be ignored in searches, false otherwise. + * Default is false. + */ + public void setIgnorePartialResultException(boolean ignore) { + this.ignorePartialResultException = ignore; + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, boolean, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(Name base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) { + + search(base, filter, getDefaultSearchControls(searchScope, + returningObjFlag, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, boolean, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(String base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException { + + search(base, filter, getDefaultSearchControls(searchScope, + returningObjFlag, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(final Name base, final String filter, + final SearchControls controls, NameClassPairCallbackHandler handler) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(final String base, final String filter, + final SearchControls controls, NameClassPairCallbackHandler handler) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler, + * org.springframework.ldap.DirContextProcessor) + */ + public void search(final Name base, final String filter, + final SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler, processor); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler, + * org.springframework.ldap.DirContextProcessor) + */ + public void search(final String base, final String filter, + final SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler, processor); + } + + /** + * Perform a search operation, such as a search(), list() or listBindings(). + * This method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. It + * also calls the supplied DirContextProcessor before and after the search, + * respectively. This enables custom pre-processing and post-processing, + * like for example when handling paged results or other search controls. + *

+ * The actual list is delegated to the {@link SearchExecutor} and each + * {@link NameClassPair} (this might be a NameClassPair or a subclass + * thereof) is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * the SearchExecutor to use for performing the actual list. + * @param handler + * the NameClassPairCallbackHandler to which each found entry + * will be passed. + * @param processor + * DirContextProcessor for custom pre- and post-processing. May + * be null if no custom processing should take + * place. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler, + DirContextProcessor processor) { + DirContext ctx = contextSource.getReadOnlyContext(); + + NamingEnumeration results = null; + try { + processor.preProcess(ctx); + results = se.executeSearch(ctx); + + while (results.hasMore()) { + NameClassPair result = (NameClassPair) results.next(); + handler.handleNameClassPair(result); + } + processor.postProcess(ctx); + } catch (NameNotFoundException e) { + // The base context was not found, which basically means + // that the search did not return any results. Just clean up and + // exit. + } catch (PartialResultException e) { + // Workaround for AD servers not handling referrals correctly. + if (ignorePartialResultException) { + log.debug("PartialResultException encountered and ignored", e); + } else { + throw getExceptionTranslator().translate(e); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeContextAndNamingEnumeration(ctx, results); + } + } + + /** + * Perform a search operation, such as a search(), list() or listBindings(). + * This method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. + *

+ * The actual list is delegated to the {@link SearchExecutor} and each + * {@link NameClassPair} (this might be a NameClassPair or a subclass + * thereof) is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * the SearchExecutor to use for performing the actual list. + * @param handler + * the NameClassPairCallbackHandler to which each found entry + * will be passed. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler) { + search(se, handler, new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(Name base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException { + + search(base, filter, getDefaultSearchControls(DEFAULT_SEARCH_SCOPE, + DONT_RETURN_OBJ_FLAG, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(String base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException { + + search(base, filter, getDefaultSearchControls(DEFAULT_SEARCH_SCOPE, + DONT_RETURN_OBJ_FLAG, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException { + return search(base, filter, getDefaultSearchControls(searchScope, + DONT_RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException { + return search(base, filter, getDefaultSearchControls(searchScope, + DONT_RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, int searchScope, + AttributesMapper mapper) { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, AttributesMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, AttributesMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException { + + return search(base, filter, getDefaultSearchControls(searchScope, + RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException { + + return search(base, filter, getDefaultSearchControls(searchScope, + RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, int searchScope, + ContextMapper mapper) { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, ContextMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, ContextMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper) { + + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper) { + + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper) { + + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper) { + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor) { + AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor) { + AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor) { + assureReturnObjFlagSet(controls); + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor) { + assureReturnObjFlagSet(controls); + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String, + * org.springframework.ldap.ListResultCallbackHandler) + */ + public void list(final String base, NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.list(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name, + * org.springframework.ldap.ListResultCallbackHandler) + */ + public void list(final Name base, NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.list(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String, + * org.springframework.ldap.NameClassPairMapper) + */ + public List list(String base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + list(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name, + * org.springframework.ldap.NameClassPairMapper) + */ + public List list(Name base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + list(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name) + */ + public List list(final Name base) { + return list(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String) + */ + public List list(final String base) { + return list(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void listBindings(final String base, + NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.listBindings(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void listBindings(final Name base, + NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.listBindings(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.NameClassPairMapper) + */ + public List listBindings(String base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + listBindings(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.NameClassPairMapper) + */ + public List listBindings(Name base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + listBindings(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String) + */ + public List listBindings(final String base) { + return listBindings(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name) + */ + public List listBindings(final Name base) { + return listBindings(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.ContextMapper) + */ + public List listBindings(String base, ContextMapper mapper) { + + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + listBindings(base, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.ContextMapper) + */ + public List listBindings(Name base, ContextMapper mapper) { + + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + listBindings(base, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#executeReadOnly(org.springframework.ldap.ContextExecutor) + */ + public Object executeReadOnly(ContextExecutor ce) { + DirContext ctx = contextSource.getReadOnlyContext(); + return executeWithContext(ce, ctx); + } + + /* + * @see org.springframework.ldap.LdapOperations#executeReadWrite(org.springframework.ldap.ContextExecutor) + */ + public Object executeReadWrite(ContextExecutor ce) { + DirContext ctx = contextSource.getReadWriteContext(); + return executeWithContext(ce, ctx); + } + + private Object executeWithContext(ContextExecutor ce, DirContext ctx) { + try { + return ce.executeWithContext(ctx); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeContext(ctx); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name) + */ + public Object lookup(final Name dn) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return ctx.lookup(dn); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String) + */ + public Object lookup(final String dn) throws DataAccessException { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return ctx.lookup(dn); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final Name dn, final AttributesMapper mapper) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes attributes = ctx.getAttributes(dn); + return mapper.mapFromAttributes(attributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final String dn, final AttributesMapper mapper) + throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes attributes = ctx.getAttributes(dn); + return mapper.mapFromAttributes(attributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * org.springframework.ldap.ContextMapper) + */ + public Object lookup(final Name dn, final ContextMapper mapper) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Object object = ctx.lookup(dn); + return mapper.mapFromContext(object); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * org.springframework.ldap.ContextMapper) + */ + public Object lookup(final String dn, final ContextMapper mapper) + throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Object object = ctx.lookup(dn); + return mapper.mapFromContext(object); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * java.lang.String[], org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final Name dn, final String[] attributes, + final AttributesMapper mapper) throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + return mapper.mapFromAttributes(filteredAttributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * java.lang.String[], org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final String dn, final String[] attributes, + final AttributesMapper mapper) throws DataAccessException { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + return mapper.mapFromAttributes(filteredAttributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * java.lang.String[], org.springframework.ldap.ContextMapper) + */ + public Object lookup(final Name dn, final String[] attributes, + final ContextMapper mapper) throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + DirContextAdapter contextAdapter = new DirContextAdapter( + filteredAttributes, dn); + return mapper.mapFromContext(contextAdapter); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * java.lang.String[], org.springframework.ldap.ContextMapper) + */ + public Object lookup(final String dn, final String[] attributes, + final ContextMapper mapper) throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + DistinguishedName name = new DistinguishedName(dn); + DirContextAdapter contextAdapter = new DirContextAdapter( + filteredAttributes, name); + return mapper.mapFromContext(contextAdapter); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#modifyAttributes(javax.naming.Name, + * javax.naming.directory.ModificationItem[]) + */ + public void modifyAttributes(final Name dn, final ModificationItem[] mods) { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.modifyAttributes(dn, mods); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#modifyAttributes(java.lang.String, + * javax.naming.directory.ModificationItem[]) + */ + public void modifyAttributes(final String dn, final ModificationItem[] mods) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.modifyAttributes(dn, mods); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#bind(javax.naming.Name, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void bind(final Name dn, final Object obj, + final Attributes attributes) { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.bind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#bind(java.lang.String, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void bind(final String dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.bind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(javax.naming.Name) + */ + public void unbind(final Name dn) { + doUnbind(dn); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(java.lang.String) + */ + public void unbind(final String dn) throws DataAccessException { + doUnbind(dn); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(javax.naming.Name, + * boolean) + */ + public void unbind(final Name dn, boolean recursive) + throws DataAccessException { + if (!recursive) { + doUnbind(dn); + } else { + doUnbindRecursively(dn); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(java.lang.String, + * boolean) + */ + public void unbind(final String dn, boolean recursive) + throws DataAccessException { + if (!recursive) { + doUnbind(dn); + } else { + doUnbindRecursively(dn); + } + } + + private void doUnbind(final Name dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.unbind(dn); + return null; + } + }); + } + + private void doUnbind(final String dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.unbind(dn); + return null; + } + }); + } + + private void doUnbindRecursively(final Name dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + deleteRecursively(ctx, new DistinguishedName(dn)); + return null; + } + }); + } + + private void doUnbindRecursively(final String dn) + throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + deleteRecursively(ctx, new DistinguishedName(dn)); + return null; + } + }); + } + + /** + * Delete all subcontexts including the current one recursively. + * + * @param ctx + * The context to use for deleting. + * @param name + * The starting point to delete recursively. + * @throws DataAccessException + * if any error occurs + */ + protected void deleteRecursively(DirContext ctx, DistinguishedName name) + throws DataAccessException { + + NamingEnumeration enumeration = null; + try { + enumeration = ctx.listBindings(name); + while (enumeration.hasMore()) { + Binding binding = (Binding) enumeration.next(); + DistinguishedName childName = new DistinguishedName(binding + .getName()); + childName.prepend((DistinguishedName) name); + deleteRecursively(ctx, childName); + } + ctx.unbind(name); + if (log.isDebugEnabled()) { + log.debug("Entry " + name + " deleted"); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + try { + enumeration.close(); + } catch (Exception e) { + // Never mind this + } + } + } + + /* + * @see org.springframework.ldap.LdapOperations#rebind(javax.naming.Name, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void rebind(final Name dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rebind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rebind(java.lang.String, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void rebind(final String dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rebind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rename(javax.naming.Name, + * javax.naming.Name) + */ + public void rename(final Name oldDn, final Name newDn) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rename(oldDn, newDn); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rename(java.lang.String, + * java.lang.String) + */ + public void rename(final String oldDn, final String newDn) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rename(oldDn, newDn); + return null; + } + }); + } + + /* + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + if (contextSource == null) { + throw new IllegalArgumentException( + "Property 'contextSource' must be set."); + } + } + + private void closeContextAndNamingEnumeration(DirContext ctx, + NamingEnumeration results) { + + closeNamingEnumeration(results); + closeContext(ctx); + } + + /** + * Close the supplied DirContext if it is not null. Swallow any exceptions, + * as this is only for cleanup. + * + * @param ctx + * the context to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + + /** + * Close the supplied NamingEnumeration if it is not null. Swallow any + * exceptions, as this is only for cleanup. + * + * @param results + * the NamingEnumeration to close. + */ + private void closeNamingEnumeration(NamingEnumeration results) { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + + /** + * Get the NamingExceptionTranslator that will be used by this instance. If + * no exceptionTranslator has been set, a default instance will be created. + * + * @return the NamingExceptionTranslator to be used by this instance. + */ + public NamingExceptionTranslator getExceptionTranslator() { + return exceptionTranslator; + } + + /** + * Set the NamingExceptionTranslator to be used by this instance. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + + this.exceptionTranslator = exceptionTranslator; + } + + private SearchControls getDefaultSearchControls(int searchScope, + boolean returningObjFlag, String[] attrs) { + + SearchControls controls = new SearchControls(); + controls.setSearchScope(searchScope); + controls.setReturningObjFlag(returningObjFlag); + controls.setReturningAttributes(attrs); + return controls; + } + + /** + * Make sure the returnObjFlag is set in the supplied SearchControls. Set it + * and log if it's not set. + * + * @param controls + * the SearchControls to check. + */ + private void assureReturnObjFlagSet(SearchControls controls) { + Validate.notNull(controls); + if (!controls.getReturningObjFlag()) { + log.info("The returnObjFlag of supplied SearchControls is not set" + + " but a ContextMapper is used - setting flag to true"); + controls.setReturningObjFlag(true); + } + } + + private final class NullDirContextProcessor implements DirContextProcessor { + public void postProcess(DirContext ctx) throws NamingException { + // Do nothing + } + + public void preProcess(DirContext ctx) throws NamingException { + // Do nothing + } + } + + /** + * A {@link NameClassPairCallbackHandler} that passes the NameClassPairs + * found to a NameClassPairMapper and collects the results in a list. + * + * @author Mattias Arthursson + */ + public class MappingCollectingNameClassPairCallbackHandler extends + CollectingNameClassPairCallbackHandler { + + private NameClassPairMapper mapper; + + public MappingCollectingNameClassPairCallbackHandler( + NameClassPairMapper mapper) { + this.mapper = mapper; + } + + /* + * @see org.springframework.ldap.CollectingNameClassPairCallbackHandler#getObjectFromNameClassPair(javax.naming.NameClassPair) + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + try { + return mapper.mapFromNameClassPair(nameClassPair); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } + + /** + * A CollectingNameClassPairCallbackHandler to wrap an AttributesMapper. + * That is, the found object is extracted from the {@link Attributes} of + * each {@link SearchResult}, and then passed to the specified + * AttributesMapper for translation. This class needs to be nested, since we + * want to be able to get hold of the exception translator of this instance. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + public class AttributesMapperCallbackHandler extends + CollectingNameClassPairCallbackHandler { + private AttributesMapper mapper; + + public AttributesMapperCallbackHandler(AttributesMapper mapper) { + this.mapper = mapper; + } + + /** + * Cast the NameClassPair to a SearchResult and pass its attributes to + * the AttributesMapper. + * + * @param nameClassPair + * a SearchResult instance. + * @return the Object returned from the Mapper. + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + SearchResult searchResult = (SearchResult) nameClassPair; + Attributes attributes = searchResult.getAttributes(); + try { + return mapper.mapFromAttributes(attributes); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } + + /** + * A CollectingNameClassPairCallbackHandler to wrap a ContextMapper. That + * is, the found object is extracted from each {@link Binding}, and then + * passed to the specified ContextMapper for translation. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + public class ContextMapperCallbackHandler extends + CollectingNameClassPairCallbackHandler { + private ContextMapper mapper; + + public ContextMapperCallbackHandler(ContextMapper mapper) { + this.mapper = mapper; + } + + /** + * Cast the NameClassPair to a {@link Binding} and pass its attributes + * to the ContextMapper. + * + * @param nameClassPair + * a SearchResult instance. + * @return the Object returned from the Mapper. + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + Binding binding = (Binding) nameClassPair; + Object object = binding.getObject(); + if (object == null) { + throw new EntryNotFoundException( + "SearchResult did not contain any object."); + } + return mapper.mapFromContext(object); + } + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java new file mode 100644 index 00000000..0698a9c6 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; + +/** + * Callback interface used by LdapTemplate's search, list and listBindings + * methods. Implementations of this interface perform the actual work of + * extracting results from a single NameClassPair (a NameClassPair, + * Binding or SearchResult depending on the search operation) returned by an + * LDAP seach operation, such as search(), list(), and listBindings(). + * + * @author Mattias Arthursson + */ +public interface NameClassPairCallbackHandler { + /** + * Handle one entry. This method will be called once for each entry returned + * by a search or list. + * + * @param nameClassPair + * the NameClassPair returned from the NamingEnumeration. + */ + public void handleNameClassPair(NameClassPair nameClassPair); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java new file mode 100644 index 00000000..acf8cd14 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; +import javax.naming.NamingException; + +/** + * Responsible for mapping NameClassPair objects to beans. + * + * @author Mattias Arthursson + */ +public interface NameClassPairMapper { + /** + * Map NameClassPair to an Object. The supplied NameClassPair is one of the + * results from a search operation (search, list or listBindings). Depending + * on which search operation is being performed, the NameClassPair might be + * a SearchResult, Binding or NameClassPair. + * + * @param nameClassPair + * NameClassPair from a search operation. + * @return and Object built from the NameClassPair. + * @throws NamingException + * if one is encountered in the operation. + */ + public Object mapFromNameClassPair(NameClassPair nameClassPair) + throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java new file mode 100644 index 00000000..cd6e7a4c --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; + +import org.springframework.dao.DataAccessException; + +/** + * Interface to be implemented by classes that can translate between + * NamingExceptions and DataAccessExceptions. + * + * @author Mattias Arthursson + * + */ +public interface NamingExceptionTranslator { + /** + * Translate the given NamingException into a generic data access exception. + * @param namingException + * the offending NamingException. + * + * @return the DataAccessException to throw. + */ + public DataAccessException translate(NamingException namingException); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchExecutor.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchExecutor.java new file mode 100644 index 00000000..34b474b5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchExecutor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface for delegating an actual search operation. The typical + * implementation of executeSearch would be something like: + * + *

+ * SearchExecutor executor = new SearchExecutor(){
+ *   public NamingEnumeration executeSearch(DirContext ctx) throws NamingException{
+ *     return ctx.search(dn, filter, searchControls);
+ *   }
+ * }
+ * 
+ * + * @see org.springframework.ldap.LdapTemplate#search(SearchExecutor, + * NameClassPairCallbackHandler) + * + * @author Mattias Arthursson + */ +public interface SearchExecutor { + /** + * Execute the actual search. + * + * @param ctx + * the DirContext on which to work. + * @return the NamingEnumeration resulting from the search operation. + * @throws NamingException + * if the search results in one. + */ + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java new file mode 100644 index 00000000..49806334 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataRetrievalFailureException; + +/** + * Indicates that the search limit was exceeded in a search. + * + * @author Mattias Arthursson + * + */ +public class SearchLimitExceededException extends DataRetrievalFailureException { + private static final long serialVersionUID = 6899885947075235580L; + + public SearchLimitExceededException(String msg) { + super(msg); + } + + public SearchLimitExceededException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java new file mode 100644 index 00000000..2423a3b7 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.UncategorizedDataAccessException; + +/** + * Indicates that an unknown NamingException has occurred. + * + * @author Mattias Arthursson + */ +public class UncategorizedLdapException extends + UncategorizedDataAccessException { + + private static final long serialVersionUID = -3319936235493869823L; + + public UncategorizedLdapException(String msg, Throwable cause) { + super(msg, cause); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/package.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/package.html new file mode 100644 index 00000000..f160a4a2 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/package.html @@ -0,0 +1,3 @@ + +The core package of the Spring-LDAP library. + \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java new file mode 100644 index 00000000..d972ebe1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java @@ -0,0 +1,459 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.util.Hashtable; +import java.util.Map; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.JdkVersion; +import org.springframework.ldap.AuthenticationSource; +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; + +/** + * Abstract implementation of the ContextSource interface. By default, returns + * an authenticated DirContext implementation for both read-only and read-write + * operations. To have an anonymous environment created for read-only + * operations, set the anonymousReadOnly property to true. + *

+ * Implementing classes need to implement + * {@link #getDirContextInstance(Hashtable)} to create a DirContext instance of + * the desired type. + *

+ * If an AuthenticationSource is set, this will be used for getting user name + * and password for each new connection, otherwise a default one will be created + * using the specified userName and password. + *

+ * Note: When using implementations of this class outside of a Spring + * Context it is necessary to call {@link #afterPropertiesSet()} when all + * properties are set, in order to finish up initialization. + * + * @see org.springframework.ldap.LdapTemplate + * @see org.springframework.ldap.support.DefaultDirObjectFactory + * @see org.springframework.ldap.support.LdapContextSource + * @see org.springframework.ldap.support.DirContextSource + * + * @author Mattias Arthursson + * @author Adam Skogman + * @author Ulrik Sandberg + */ +public abstract class AbstractContextSource implements ContextSource, + InitializingBean { + + private static final Class DEFAULT_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory.class; + + private static final Class DEFAULT_DIR_OBJECT_FACTORY = DefaultDirObjectFactory.class; + + private Class dirObjectFactory = DEFAULT_DIR_OBJECT_FACTORY; + + private Class contextFactory = DEFAULT_CONTEXT_FACTORY; + + private DistinguishedName base; + + protected String userName = ""; + + protected String password = ""; + + private String[] urls; + + private boolean pooled = true; + + private Hashtable baseEnv = new Hashtable(); + + private Hashtable anonymousEnv; + + private AuthenticationSource authenticationSource; + + private boolean cacheEnvironmentProperties = true; + + private boolean anonymousReadOnly = false; + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + private static final Log log = LogFactory.getLog(LdapContextSource.class); + + public static final String SUN_LDAP_POOLING_FLAG = "com.sun.jndi.ldap.connect.pool"; + + private static final String JDK_142 = "1.4.2"; + + public DirContext getReadOnlyContext() { + if (!anonymousReadOnly) { + return createContext(getAuthenticatedEnv()); + } else { + return createContext(getAnonymousEnv()); + } + } + + public DirContext getReadWriteContext() { + return createContext(getAuthenticatedEnv()); + } + + /** + * Default implementation of setting the environment up to be authenticated. + * Override in subclass if necessary. This is needed for Active Directory + * connectivity, for example. + * + * @param env + * the environment to modify. + */ + protected void setupAuthenticatedEnvironment(Hashtable env) { + env + .put(Context.SECURITY_PRINCIPAL, authenticationSource + .getPrincipal()); + log.debug("Principal: '" + userName + "'"); + env.put(Context.SECURITY_CREDENTIALS, authenticationSource + .getCredentials()); + } + + /** + * Close the context and swallow any exceptions. + * + * @param ctx + * the DirContext to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + } + } + } + + /** + * Assemble a valid url String from all registered urls to add as + * PROVIDER_URL to the environment. + * + * @param ldapUrls + * all individual url Strings. + * @return the full url String + */ + protected String assembleProviderUrlString(String[] ldapUrls) { + StringBuffer providerUrlBuffer = new StringBuffer(1024); + for (int i = 0; i < ldapUrls.length; i++) { + providerUrlBuffer.append(ldapUrls[i]); + if (base != null) { + if (!ldapUrls[i].endsWith("/")) { + providerUrlBuffer.append("/"); + } + providerUrlBuffer.append(base.toUrl()); + } + providerUrlBuffer.append(' '); + } + return providerUrlBuffer.toString().trim(); + } + + /** + * Set the base suffix from which all operations should origin. If a base + * suffix is set, you will not have to (and, indeed, should not) specify the + * full distinguished names in the operations performed. + * + * @param base + * the base suffix. + */ + public void setBase(String base) { + this.base = new DistinguishedName(base); + } + + /** + * Create a DirContext using the supplied environment. + * + * @param environment + * the Ldap environment to use when creating the DirContext. + * @return a new DirContext implpementation initialized with the supplied + * environment. + */ + DirContext createContext(Hashtable environment) { + DirContext ctx = null; + + try { + ctx = getDirContextInstance(environment); + + if (log.isInfoEnabled()) { + Hashtable ctxEnv = ctx.getEnvironment(); + String ldapUrl = (String) ctxEnv.get(Context.PROVIDER_URL); + log.debug("Got Ldap context on server '" + ldapUrl + "'"); + } + + return ctx; + } catch (NamingException e) { + closeContext(ctx); + throw getExceptionTranslator().translate(e); + } + } + + /** + * Set the context factory. Default is com.sun.jndi.ldap.LdapCtxFactory. + * + * @param contextFactory + * the context factory used when creating Contexts. + */ + public void setContextFactory(Class contextFactory) { + this.contextFactory = contextFactory; + } + + /** + * Set the DirObjectFactory to use. Default is + * {@link DefaultDirObjectFactory}. The specified class needs to be an + * implementation of javax.naming.spi.DirObjectFactory. Note: Setting + * this value to null may have cause connection leaks when using + * ContextMapper methods in LdapTemplate. + * + * @param dirObjectFactory + * the DirObjectFactory to be used. Null means that no + * DirObjectFactory will be used. + */ + public void setDirObjectFactory(Class dirObjectFactory) { + this.dirObjectFactory = dirObjectFactory; + } + + /** + * Checks that all necessary data is set and that there is no compatibility + * issues, after which the instance is initialized. Note that you need to + * call this method explicitly after setting all desired properties if using + * the class outside of a Spring Context. + */ + public void afterPropertiesSet() throws Exception { + if (ArrayUtils.isEmpty(urls)) { + throw new IllegalArgumentException( + "At least one server url must be set"); + } + + if (base != null && getJdkVersion().compareTo(JDK_142) < 0) { + throw new IllegalArgumentException( + "Base path is not supported for JDK versions < 1.4.2"); + } + + if (authenticationSource == null) { + log.debug("AuthenticationSource not set - " + + "using default implementation"); + if (StringUtils.isBlank(userName)) { + log + .warn("Property 'userName' not set - " + + "anonymous context will be used for read-write operations"); + } else if (StringUtils.isBlank(password)) { + log.warn("Property 'password' not set - " + + "blank password will be used"); + } + authenticationSource = new SimpleAuthenticationSource(); + } + + if (cacheEnvironmentProperties) { + anonymousEnv = setupAnonymousEnv(); + } + } + + private Hashtable setupAnonymousEnv() { + if (pooled) { + baseEnv.put(SUN_LDAP_POOLING_FLAG, "true"); + log.debug("Using LDAP pooling."); + } else { + log.debug("Not using LDAP pooling"); + } + + Hashtable env = new Hashtable(baseEnv); + + env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory.getName()); + env.put(Context.PROVIDER_URL, assembleProviderUrlString(urls)); + + if (dirObjectFactory != null) { + env.put(Context.OBJECT_FACTORIES, dirObjectFactory.getName()); + } + + if (base != null) { + // Save the base path for use in the DefaultDirObjectFactory. + env.put(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY, base); + } + + log.debug("Trying provider Urls: " + assembleProviderUrlString(urls)); + + return env; + } + + /** + * Set the password (credentials) to use for getting authenticated contexts. + * + * @param password + * the password. + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Set the user name (principal) to use for getting authenticated contexts. + * + * @param userName + * the user name. + */ + public void setUserName(String userName) { + this.userName = userName; + } + + /** + * Set the urls of the LDAP servers. Use this method if several servers are + * required. + * + * @param urls + * the urls of all servers. + */ + public void setUrls(String[] urls) { + this.urls = urls; + } + + /** + * Set the url of the LDAP server. Utility method if only one server is + * used. + * + * @param url + * the url of the LDAP server. + */ + public void setUrl(String url) { + this.urls = new String[] { url }; + } + + /** + * Set whether the pooling flag should be set. Default is true. + * + * @param pooled + * whether Contexts should be pooled. + */ + public void setPooled(boolean pooled) { + this.pooled = pooled; + } + + /** + * If any custom environment properties are needed, these can be set using + * this method. + * + * @param baseEnvironmentProperties + */ + public void setBaseEnvironmentProperties(Map baseEnvironmentProperties) { + this.baseEnv = new Hashtable(baseEnvironmentProperties); + } + + String getJdkVersion() { + return JdkVersion.getJavaVersion(); + } + + protected Hashtable getAnonymousEnv() { + if (cacheEnvironmentProperties) { + return anonymousEnv; + } else { + return setupAnonymousEnv(); + } + } + + protected Hashtable getAuthenticatedEnv() { + // The authenticated environment should always be rebuilt. + Hashtable env = new Hashtable(getAnonymousEnv()); + setupAuthenticatedEnvironment(env); + return env; + } + + public void setAuthenticationSource( + AuthenticationSource authenticationProvider) { + this.authenticationSource = authenticationProvider; + } + + /** + * Set whether environment properties should be cached between requsts for + * anonymous environment. Default is true; setting this property to false + * causes the environment Hashmap to be rebuilt from the current property + * settings of this instance between each request for an anonymous + * environment. + * + * @param cacheEnvironmentProperties + * true causes that the anonymous environment properties should + * be cached, false causes the Hashmap to be rebuilt for each + * request. + */ + public void setCacheEnvironmentProperties(boolean cacheEnvironmentProperties) { + this.cacheEnvironmentProperties = cacheEnvironmentProperties; + } + + /** + * Set whether an anonymous environment should be used for read-only + * operations. Default is false. + * + * @param anonymousReadOnly + * true if and anonymous environment should be + * used for read-only operations, false otherwise. + */ + public void setAnonymousReadOnly(boolean anonymousReadOnly) { + this.anonymousReadOnly = anonymousReadOnly; + } + + /** + * Set the NamingExceptionTranslator to be used by this instance. By + * default, a {@link DefaultNamingExceptionTranslator} will be used. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } + + /** + * Get the NamingExceptionTranslator used by this instance. + * + * @return the NamingExceptionTranslator. + */ + public NamingExceptionTranslator getExceptionTranslator() { + return exceptionTranslator; + } + + /** + * Implement in subclass to create a DirContext of the desired type (e.g. + * InitialDirContext or InitialLdapContext). + * + * @param environment + * the environment to use when creating the instance. + * @return a new DirContext instance. + * @throws NamingException + * if one is encountered when creating the instance. + */ + protected abstract DirContext getDirContextInstance(Hashtable environment) + throws NamingException; + + class SimpleAuthenticationSource implements AuthenticationSource { + + public String getPrincipal() { + return userName; + } + + public String getCredentials() { + return password; + } + + } + + protected String[] getUrls() { + return urls; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java new file mode 100644 index 00000000..e24a88bd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java @@ -0,0 +1,72 @@ +package org.springframework.ldap.support; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.DirContextProcessor; + +/** + * Manages a sequence of DirContextProcessor instances. Applies + * {@link #preProcess(DirContext)} and {@link #postProcess(DirContext)} + * respectively in sequence on the managed objects. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class AggregateDirContextProcessor implements DirContextProcessor { + + private List dirContextProcessors = new LinkedList(); + + /** + * Add the supplied DirContextProcessor to the list of managed objects. + * + * @param processor + * the DirContextpProcessor to add. + */ + public void addDirContextProcessor(DirContextProcessor processor) { + dirContextProcessors.add(processor); + } + + /** + * Get the list of managed DirContextProcessors. + * + * @return the managed list of {@link DirContextProcessor} instances. + */ + public List getDirContextProcessors() { + return dirContextProcessors; + } + + /** + * Set the list of managed {@link DirContextProcessor} instances. + * + * @param dirContextProcessors + * the list of {@link DirContextProcessor} instances to set. + */ + public void setDirContextProcessors(List dirContextProcessors) { + this.dirContextProcessors = dirContextProcessors; + } + + /* + * @see org.springframework.ldap.DirContextProcessor#preProcess(javax.naming.directory.DirContext) + */ + public void preProcess(DirContext ctx) throws NamingException { + for (Iterator iter = dirContextProcessors.iterator(); iter.hasNext();) { + DirContextProcessor processor = (DirContextProcessor) iter.next(); + processor.preProcess(ctx); + } + } + + /* + * @see org.springframework.ldap.DirContextProcessor#postProcess(javax.naming.directory.DirContext) + */ + public void postProcess(DirContext ctx) throws NamingException { + for (Iterator iter = dirContextProcessors.iterator(); iter.hasNext();) { + DirContextProcessor processor = (DirContextProcessor) iter.next(); + processor.postProcess(ctx); + } + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java new file mode 100644 index 00000000..9d0a7fa1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import javax.naming.directory.ModificationItem; + +/** + * Indicates that the implementor is capable of keeping track of any attribute + * modifications and return them as ModificationItems. + * + * @author Mattias Arthursson + * + */ +public interface AttributeModificationsAware { + + /** + * Creates an array of which attributes have been changed or added or removed. + * + * @return an array of modification items + */ + public ModificationItem[] getModificationItems(); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java new file mode 100644 index 00000000..8f017beb --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.NameClassPair; + +import org.springframework.ldap.NameClassPairCallbackHandler; + +/** + * A NameClassPairCallbackHandler for counting all returned entries. + * + * @author Mattias Arthursson + * + */ +public class CountNameClassPairCallbackHandler implements + NameClassPairCallbackHandler { + + private int noOfRows = 0; + + /** + * Get the number of rows that was returned by the search. + * + * @return the number of entries that have been handled. + */ + public int getNoOfRows() { + return noOfRows; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.SearchResultCallbackHandler#handleSearchResult(javax.naming.directory.SearchResult) + */ + public void handleNameClassPair(NameClassPair nameClassPair) { + noOfRows++; + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java new file mode 100644 index 00000000..01776c2e --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java @@ -0,0 +1,93 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.directory.Attributes; +import javax.naming.spi.DirObjectFactory; + +/** + * Default implementation of the DirObjectFactory interface. Creates a + * DirContextAdapter from the supplied arguments. + * + * @author Mattias Arthursson + */ +public class DefaultDirObjectFactory implements DirObjectFactory { + /** + * Key to use in the ContextSource implementation to store the value of the + * base path suffix, if any, in the Ldap Environment. + */ + public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path"; + + /** + * Creates a DirContextAdapter from the supplied arguments. + * + * @param obj + * @param name + * @param nameCtx + * @param environment + * @param attrs + * @return a new DirContextAdapter from the attributes and name. + * @throws Exception + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, + Hashtable environment, Attributes attrs) throws Exception { + + try { + DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, + name, (Name) environment.get(JNDI_ENV_BASE_PATH_KEY)); + dirContextAdapter.setUpdateMode(true); + + return dirContextAdapter; + } finally { + // It seems that the object supplied to the obj parameter is a + // DirContext instance with reference to the same Ldap connection as + // the original context. Since it is not the same instance (that's + // the nameCtx parameter) this one really needs to be closed in + // order to correctly clean up and return the connection to the pool + // when we're finished with the surrounding operation. + if (obj instanceof Context) { + Context ctx = (Context) obj; + try { + ctx.close(); + } catch (Exception e) { + // Never mind this + } + + } + } + } + + /** + * Returns null. + * + * @param obj + * @param name + * @param nameCtx + * @param environment + * @return null. + * @throws Exception + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, + Hashtable environment) throws Exception { + return null; + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java new file mode 100644 index 00000000..e0ccbdc7 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.io.StringReader; + +/** + * A factory for creating DnParser instances. The actual implementation of + * DnParser is generated using javacc and should not be constructed directly. + * + * @author Mattias Arthursson + * + */ +public class DefaultDnParserFactory { + /** + * Create a new DnParser instance. + * + * @param string + * the DN String to be parsed. + * @return a new DnParser instance for parsing the supplied DN string. + */ + public static DnParser createDnParser(String string) { + return new DnParserImpl(new StringReader(string)); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java new file mode 100644 index 00000000..779af825 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java @@ -0,0 +1,1271 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.NameParser; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; + +/** + * Implements the interesting methods of the DirContext interface. In particular + * it contains utility methods for getting and setting Attributes. Using the + * {@link org.springframework.ldap.support.DefaultDirObjectFactory} in your + * ContextSource you may receive instances of this class from searches and + * lookups. This can be particularly useful when updating data, since this class + * implements + * {@link org.springframework.ldap.support.AttributeModificationsAware}, + * providing a {@link #getModificationItems()} method. + * + * @author Magnus Robertsson + * @author Andreas Ronge + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DirContextAdapter implements DirContextOperations { + + private static final boolean ORDER_DOESNT_MATTER = false; + + private static Log log = LogFactory.getLog(DirContextAdapter.class); + + private final Attributes attrs; + + private DistinguishedName dn; + + private DistinguishedName base; + + private boolean updateMode = false; + + private Attributes updatedAttrs; + + private NamingExceptionTranslator exceptionTranslator; + + /** + * Default constructor. + */ + public DirContextAdapter() { + this(null, null, null); + } + + /** + * Create a new adapter from the supplied dn. + * + * @param dn + * the dn. + */ + public DirContextAdapter(Name dn) { + this(null, dn); + } + + /** + * Create a new adapter from the supplied attributes and dn. + * + * @param attrs + * the attributes. + * @param dn + * the dn. + */ + public DirContextAdapter(Attributes attrs, Name dn) { + this(attrs, dn, null); + } + + /** + * Create a new adapter from the supplied attributes, dn, and base. + * + * @param attrs + * the attributes. + * @param dn + * the dn. + * @param base + * the base name. + */ + public DirContextAdapter(Attributes attrs, Name dn, Name base) { + if (attrs != null) { + this.attrs = attrs; + } else { + this.attrs = new BasicAttributes(true); + } + if (dn != null) { + this.dn = new DistinguishedName(dn.toString()); + } else { + this.dn = new DistinguishedName(); + } + if (base != null) { + this.base = new DistinguishedName(base.toString()); + } else { + this.base = new DistinguishedName(); + } + } + + /** + * Constructor for cloning an existing adapter. + * + * @param master + * The adapter to be copied. + */ + protected DirContextAdapter(DirContextAdapter master) { + this.attrs = (Attributes) master.attrs.clone(); + this.dn = master.dn; + this.updatedAttrs = (Attributes) master.updatedAttrs.clone(); + this.updateMode = master.updateMode; + } + + /** + * Sets the update mode. The update mode should be false for + * a new entry and true for an existing entry that is being + * updated. + * + * @param mode + * Update mode. + */ + protected void setUpdateMode(boolean mode) { + this.updateMode = mode; + if (updateMode) { + updatedAttrs = new BasicAttributes(true); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#isUpdateMode() + */ + public boolean isUpdateMode() { + return updateMode; + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getNamesOfModifiedAttributes() + */ + public String[] getNamesOfModifiedAttributes() { + + List tmpList = new ArrayList(); + + NamingEnumeration attributesEnumeration; + if (isUpdateMode()) { + attributesEnumeration = updatedAttrs.getAll(); + } else { + attributesEnumeration = attrs.getAll(); + } + + try { + while (attributesEnumeration.hasMore()) { + Attribute oneAttribute = (Attribute) attributesEnumeration + .next(); + tmpList.add(oneAttribute.getID()); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + return (String[]) tmpList.toArray(new String[0]); + } + + private void closeNamingEnumeration(NamingEnumeration enumeration) { + try { + if (enumeration != null) { + enumeration.close(); + } + } catch (NamingException e) { + // Never mind this + } + } + + /* + * @see org.springframework.ldap.support.AttributeModificationsAware#getModificationItems() + */ + public ModificationItem[] getModificationItems() { + if (!updateMode) { + return new ModificationItem[0]; + } + + List tmpList = new LinkedList(); + NamingEnumeration attributesEnumeration = null; + try { + attributesEnumeration = updatedAttrs.getAll(); + + // find attributes that have been changed, removed or added + while (attributesEnumeration.hasMore()) { + Attribute oneAttr = (Attribute) attributesEnumeration.next(); + + collectModifications(oneAttr, tmpList); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + if (log.isDebugEnabled()) { + log.debug("Number of modifications:" + tmpList.size()); + } + + return (ModificationItem[]) tmpList + .toArray(new ModificationItem[tmpList.size()]); + } + + /** + * Collect all modifications for the changed attribute. If no changes have + * been made, return immediately. If modifications have been made, and the + * original size as well as the updated size of the attribute is 1, replace + * the attribute. If the size of the updated attribute is 0, remove the + * attribute. Otherwise, the attribute is a multi-value attribute, in which + * case all modifications to the original value (removals and additions) + * will be collected individually. + * + * @param changedAttr + * the value of the changed attribute. + * @param modificationList + * the list in which to add the modifications. + * @throws NamingException + * if thrown by called Attribute methods. + */ + private void collectModifications(Attribute changedAttr, + List modificationList) throws NamingException { + Attribute currentAttribute = attrs.get(changedAttr.getID()); + + if (changedAttr.equals(currentAttribute)) { + // No changes + return; + } else if (currentAttribute != null && currentAttribute.size() == 1 + && changedAttr.size() == 1) { + // Replace single-vale attribute. + modificationList.add(new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, changedAttr)); + } else if (changedAttr.size() == 0) { + // Attribute has been removed. + modificationList.add(new ModificationItem( + DirContext.REMOVE_ATTRIBUTE, changedAttr)); + } else { + // Collect all modifications to attribute individually (this also + // covers additions to a previously non-existant attribute). + Collection oldValues = new LinkedList(); + Collection newValues = new LinkedList(); + + collectAttributeValues(oldValues, currentAttribute); + collectAttributeValues(newValues, changedAttr); + Collection myModifications = new LinkedList(); + + Collection addedValues = CollectionUtils.subtract(newValues, + oldValues); + Collection removedValues = CollectionUtils.subtract(oldValues, + newValues); + + collectModifications(DirContext.ADD_ATTRIBUTE, changedAttr, + addedValues, myModifications); + collectModifications(DirContext.REMOVE_ATTRIBUTE, changedAttr, + removedValues, myModifications); + + if (myModifications.isEmpty()) { + // This means that the attributes are not equal, but the + // actual values are the same - thus the order must have + // changed. This should result in a REPLACE_ATTRIBUTE operation. + myModifications.add(new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, changedAttr)); + } + + modificationList.addAll(myModifications); + } + } + + private void collectModifications(int modificationType, Attribute attr, + Collection values, Collection c) { + if (values.size() > 0) { + BasicAttribute modificationAttribute = new BasicAttribute(attr + .getID()); + for (Iterator iter = values.iterator(); iter.hasNext();) { + modificationAttribute.add(iter.next()); + } + c + .add(new ModificationItem(modificationType, + modificationAttribute)); + } + } + + private void collectAttributeValues(Collection valueCollection, + Attribute attribute) throws NamingException { + + if (attribute == null) { + return; + } + + NamingEnumeration attributeValues = attribute.getAll(); + while (attributeValues.hasMoreElements()) { + Object value = (Object) attributeValues.nextElement(); + valueCollection.add(value); + } + } + + /** + * Compare the existing attribute name with the value in + * value. + *

+ * Also handles the case where the value has been reset to the original + * value after a previous change. For example, changing a to + * b and then back to a again must result in + * this method returning true so the first change can be + * overwritten with the latest change. + * TODO Do the null checks on the value instead + * + * @param name + * Name of the original attribute. + * @param value + * Value to check if it has been changed. + * @return true if there has been a change compared to original attribute, + * or a previous update + */ + private boolean isChanged(String name, Object value) { + Attribute orig = attrs.get(name); + Attribute prev = updatedAttrs.get(name); + + // FALSE if both are null it is not changed + // TODO Also include prev in null check + if (orig == null && value == null) { + return false; + } + + // TRUE if existing value is null or does not contain one value + if (orig == null || orig.size() != 1) { + return true; + } + + // TRUE if existing value is not null and the new one is null + if (orig != null && value == null) { + return true; + } + + // TRUE if we can't access the value + Object obj = null; + try { + obj = orig.get(0); + } catch (NamingException e) { + return true; + } + + if (prev == null) { + // TRUE if the value is not equal + return !value.equals(obj); + } else { + // TRUE if we can't access the value + Object prevObj = null; + try { + prevObj = prev.get(0); + } catch (NamingException e) { + return true; + } + // TRUE if the value is not equal + return !value.equals(obj) || !value.equals(prevObj); + } + } + + /** + * returns true if the attribute is empty. It is empty if a == null, size == + * 0 or get() == null or an exception if thrown when accessing the get + * method + */ + private boolean isEmptyAttribute(Attribute a) { + try { + return (a == null || a.size() == 0 || a.get() == null); + } catch (NamingException e) { + return true; + } + } + + /** + * Compare the existing attribute name with the values on the + * array values. The order of the array must be the same + * order as the existing multivalued attribute. + *

+ * Also handles the case where the values have been reset to the original + * values after a previous change. For example, changing + * [a,b,c] to [a,b] and then back to + * [a,b,c] again must result in this method returning + * true so the first change can be overwritten with the + * latest change. + * + * @param name + * Name of the original multi-valued attribute. + * @param values + * Array of values to check if they have been changed. + * @return true if there has been a change compared to original attribute, + * or a previous update + */ + private boolean isChanged(String name, Object[] values, boolean orderMatters) { + + Attribute orig = attrs.get(name); + Attribute prev = updatedAttrs.get(name); + + // values == null and values.length == 0 is treated the same way + boolean emptyNewValue = (values == null || values.length == 0); + + // Setting to empty --------------------- + if (emptyNewValue) { + // FALSE: if both are null, it is not changed (both don't exist) + // TRUE: if new value is null and old value exists (should be + // removed) + // TODO Also include prev in null check + // TODO Also check if there is a single null element + if (orig != null) { + return true; + } + return false; + } + + // NOT setting to empty ------------------- + + // TRUE if existing value is null + if (orig == null) { + return true; + } + + // TRUE if different length compared to original attributes + if (orig.size() != values.length) { + return true; + } + + // TRUE if different length compared to previously updated attributes + if (prev != null && prev.size() != values.length) { + return true; + } + + // Check contents of arrays + + // Order DOES matter, e.g. first names + try { + for (int i = 0; i < orig.size(); i++) { + Object obj = orig.get(i); + // TRUE if one value is not equal + if (!(obj instanceof String)) { + return true; + } + if (orderMatters) { + // check only the string with same index + if (!values[i].equals(obj)) { + return true; + } + } else { + // check all strings + if (!ArrayUtils.contains(values, obj)) { + return true; + } + } + } + + } catch (NamingException e) { + // TRUE if we can't access the value + return true; + } + + if (prev != null) { + // Also check against updatedAttrs, since there might have been + // a previous update + try { + for (int i = 0; i < prev.size(); i++) { + Object obj = prev.get(i); + // TRUE if one value is not equal + if (!(obj instanceof String)) { + return true; + } + if (orderMatters) { + // check only the string with same index + if (!values[i].equals(obj)) { + return true; + } + } else { + // check all strings + if (!ArrayUtils.contains(values, obj)) { + return true; + } + } + } + + } catch (NamingException e) { + // TRUE if we can't access the value + return true; + } + } + // FALSE since we have compared all values + return false; + } + + /** + * Checks if an entry has a specific attribute. + * + * This method simply calls exists(String) with the attribute name. + * + * @param attr + * the attribute to check. + * @return true if attribute exists in entry. + */ + protected final boolean exists(Attribute attr) { + return exists(attr.getID()); + } + + /** + * Checks if the attribute exists in this entry, either it was read or it + * has been added and update() has been called. + * + * @param attrId + * id of the attribute to check. + * @return true if the attribute exists in the entry. + */ + protected final boolean exists(String attrId) { + return attrs.get(attrId) != null; + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getStringAttribute(java.lang.String) + */ + public String getStringAttribute(String name) { + return (String) getObjectAttribute(name); + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getObjectAttribute(java.lang.String) + */ + public Object getObjectAttribute(String name) { + Attribute oneAttr = attrs.get(name); + if (oneAttr == null) { + return null; + } + try { + return oneAttr.get(); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValue(java.lang.String, + * java.lang.Object) + */ + public void setAttributeValue(String name, Object value) { + // new entry + if (!updateMode && value != null) { + attrs.put(name, value); + } + + // updating entry + if (updateMode && isChanged(name, value)) { + BasicAttribute attribute = new BasicAttribute(name); + if (value != null) { + attribute.add(value); + } + updatedAttrs.put(attribute); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String, + * java.lang.Object[]) + */ + public void setAttributeValues(String name, Object[] values) { + setAttributeValues(name, values, ORDER_DOESNT_MATTER); + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String, + * java.lang.Object[], boolean) + */ + public void setAttributeValues(String name, Object[] values, + boolean orderMatters) { + Attribute a = new BasicAttribute(name, orderMatters); + + for (int i = 0; values != null && i < values.length; i++) { + a.add(values[i]); + } + + // only change the original attribute if not in update mode + if (!updateMode && values != null && values.length > 0) { + // don't save empty arrays + attrs.put(a); + } + + // possible to set an already existing attribute to an empty array + if (updateMode && isChanged(name, values, orderMatters)) { + updatedAttrs.put(a); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#update() + */ + public void update() { + NamingEnumeration attributesEnumeration = null; + + try { + attributesEnumeration = updatedAttrs.getAll(); + + // find what to update + while (attributesEnumeration.hasMore()) { + Attribute a = (Attribute) attributesEnumeration.next(); + + // if it does not exist it should be added + if (isEmptyAttribute(a)) { + attrs.remove(a.getID()); + } else { + // Otherwise it should be set. + attrs.put(a); + } + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + // Reset the attributes to be updated + updatedAttrs = new BasicAttributes(true); + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getStringAttributes(java.lang.String) + */ + public String[] getStringAttributes(String name) { + String[] attributes; + + Attribute attribute = attrs.get(name); + if (attribute != null && attribute.size() > 0) { + attributes = new String[attribute.size()]; + for (int i = 0; i < attribute.size(); i++) { + try { + attributes[i] = (String) attribute.get(i); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } else { + return null; + } + + return attributes; + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getAttributeSortedStringSet(java.lang.String) + */ + public SortedSet getAttributeSortedStringSet(String name) { + TreeSet attrSet = new TreeSet(); + + Attribute attribute = attrs.get(name); + if (attribute != null) { + for (int i = 0; i < attribute.size(); i++) { + try { + attrSet.add(attribute.get(i)); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } else { + return null; + } + + return attrSet; + } + + /** + * Set the supplied attribute. + * + * @param attribute + * the attribute to set. + */ + public void setAttribute(Attribute attribute) { + attrs.put(attribute); + } + + /** + * Get all attributes. + * + * @return all attributes. + */ + public Attributes getAttributes() { + return attrs; + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(Name) + */ + public Attributes getAttributes(Name name) throws NamingException { + return getAttributes(name.toString()); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(String) + */ + public Attributes getAttributes(String name) throws NamingException { + if (!StringUtils.isEmpty(name)) { + throw new NameNotFoundException(); + } + return (Attributes) attrs.clone(); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(Name, String[]) + */ + public Attributes getAttributes(Name name, String[] attrIds) + throws NamingException { + return getAttributes(name.toString(), attrIds); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(String, String[]) + */ + public Attributes getAttributes(String name, String[] attrIds) + throws NamingException { + if (!StringUtils.isEmpty(name)) { + throw new NameNotFoundException(); + } + + Attributes a = new BasicAttributes(true); + Attribute target; + for (int i = 0; i < attrIds.length; i++) { + target = attrs.get(attrIds[i]); + if (target != null) { + a.put(target); + } + } + + return a; + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, + * int, javax.naming.directory.Attributes) + */ + public void modifyAttributes(Name name, int modOp, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(String, int, + * Attributes) + */ + public void modifyAttributes(String name, int modOp, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(Name, + * ModificationItem[]) + */ + public void modifyAttributes(Name name, ModificationItem[] mods) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(String, + * ModificationItem[]) + */ + public void modifyAttributes(String name, ModificationItem[] mods) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#bind(Name, Object, Attributes) + */ + public void bind(Name name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#bind(String, Object, Attributes) + */ + public void bind(String name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#rebind(Name, Object, Attributes) + */ + public void rebind(Name name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#rebind(String, Object, Attributes) + */ + public void rebind(String name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#createSubcontext(Name, Attributes) + */ + public DirContext createSubcontext(Name name, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#createSubcontext(String, + * Attributes) + */ + public DirContext createSubcontext(String name, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchema(Name) + */ + public DirContext getSchema(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchema(String) + */ + public DirContext getSchema(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchemaClassDefinition(Name) + */ + public DirContext getSchemaClassDefinition(Name name) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchemaClassDefinition(String) + */ + public DirContext getSchemaClassDefinition(String name) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, Attributes, String[]) + */ + public NamingEnumeration search(Name name, Attributes matchingAttributes, + String[] attributesToReturn) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, Attributes, + * String[]) + */ + public NamingEnumeration search(String name, Attributes matchingAttributes, + String[] attributesToReturn) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, Attributes) + */ + public NamingEnumeration search(Name name, Attributes matchingAttributes) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, Attributes) + */ + public NamingEnumeration search(String name, Attributes matchingAttributes) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, String, + * SearchControls) + */ + public NamingEnumeration search(Name name, String filter, + SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, String, + * SearchControls) + */ + public NamingEnumeration search(String name, String filter, + SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, String, Object[], + * SearchControls) + */ + public NamingEnumeration search(Name name, String filterExpr, + Object[] filterArgs, SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, String, Object[], + * SearchControls) + */ + public NamingEnumeration search(String name, String filterExpr, + Object[] filterArgs, SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookup(Name) + */ + public Object lookup(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookup(String) + */ + public Object lookup(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#bind(Name, Object) + */ + public void bind(Name name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#bind(String, Object) + */ + public void bind(String name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rebind(Name, Object) + */ + public void rebind(Name name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rebind(String, Object) + */ + public void rebind(String name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#unbind(Name) + */ + public void unbind(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#unbind(String) + */ + public void unbind(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rename(Name, Name) + */ + public void rename(Name oldName, Name newName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rename(String, String) + */ + public void rename(String oldName, String newName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#list(Name) + */ + public NamingEnumeration list(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#list(String) + */ + public NamingEnumeration list(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#listBindings(Name) + */ + public NamingEnumeration listBindings(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#listBindings(String) + */ + public NamingEnumeration listBindings(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#destroySubcontext(Name) + */ + public void destroySubcontext(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#destroySubcontext(String) + */ + public void destroySubcontext(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#createSubcontext(Name) + */ + public Context createSubcontext(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#createSubcontext(String) + */ + public Context createSubcontext(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookupLink(Name) + */ + public Object lookupLink(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookupLink(String) + */ + public Object lookupLink(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameParser(Name) + */ + public NameParser getNameParser(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameParser(String) + */ + public NameParser getNameParser(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#composeName(Name, Name) + */ + public Name composeName(Name name, Name prefix) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#composeName(String, String) + */ + public String composeName(String name, String prefix) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#addToEnvironment(String, Object) + */ + public Object addToEnvironment(String propName, Object propVal) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#removeFromEnvironment(String) + */ + public Object removeFromEnvironment(String propName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getEnvironment() + */ + public Hashtable getEnvironment() throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#close() + */ + public void close() throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameInNamespace() + */ + public String getNameInNamespace() { + return dn.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getDn() + */ + public Name getDn() { + DistinguishedName retval = new DistinguishedName(dn); + retval.removeFirst(base); + return retval; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#setDn(javax.naming.Name) + */ + public final void setDn(Name dn) { + if (!updateMode) { + this.dn = new DistinguishedName(dn.toString()); + } + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + return EqualsBuilder.reflectionEquals(this, obj); + } + + /** + * @see Object#hashCode() + */ + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(getClass().getName()); + buf.append(":"); + if (dn != null) { + buf.append(" dn=" + dn); + } + buf.append(" {"); + + try { + for (NamingEnumeration i = attrs.getAll(); i.hasMore();) { + Attribute attribute = (Attribute) i.next(); + if (attribute.size() == 1) { + buf.append(attribute.getID()); + buf.append('='); + buf.append(attribute.get()); + } else { + for (int j = 0; j < attribute.size(); j++) { + if (j > 0) { + buf.append(", "); + } + buf.append(attribute.getID()); + buf.append('['); + buf.append(j); + buf.append("]="); + buf.append(attribute.get(j)); + } + } + + if (i.hasMore()) { + buf.append(", "); + } + } + } catch (NamingException e) { + log.warn("Error in toString()"); + } + buf.append('}'); + + return buf.toString(); + } + + /** + * Get the NamingExceptionTranslator. + * + * @return the NamingExceptionTranslator to use; if none is specified, + * {@link DefaultNamingExceptionTranslator} is used. + */ + public NamingExceptionTranslator getExceptionTranslator() { + if (exceptionTranslator == null) { + exceptionTranslator = new DefaultNamingExceptionTranslator(); + } + return exceptionTranslator; + } + + /** + * Set the NamingExceptionTranslator to use. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java new file mode 100644 index 00000000..c44f3fbd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java @@ -0,0 +1,161 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.SortedSet; + +import javax.naming.Name; +import javax.naming.directory.DirContext; + +/** + * Interface for DirContextAdapter to simplify mock testing. + * + * @author Mattias Arthursson + */ +public interface DirContextOperations extends DirContext, + AttributeModificationsAware { + + /** + * Gets the update mode. The update mode should be true for a + * new entry and true for an existing entry that is being + * updated. + * + * @return update mode + */ + public boolean isUpdateMode(); + + /** + * Creates a String array of the names of the attributes which have been + * changed. + * + * If this is a new entry, all set entries will be in the list. If this is + * an updated entry, only changed and removed entries will be in the array. + * + * @return Array of String + */ + public String[] getNamesOfModifiedAttributes(); + + /** + * Get the value of a String attribute. + * + * @param name + * name of the attribute. + * @return the value of the attribute. + */ + public String getStringAttribute(String name); + + /** + * Get the value of an Object attribute. + * + * @param name + * name of the attribute. + * @return the attribute value as an object if it exists, or + * null otherwise. + */ + public Object getObjectAttribute(String name); + + /** + * Set the with the name name to the value. + * + * @param name + * name of the attribute. + * @param value + * value to set the attribute to. + */ + public void setAttributeValue(String name, Object value); + + /** + * Sets a multivalue attribute, disregarding the order of the values. + * + * If value is null or value.length == 0 then the attribute will be removed. + * + * If update mode, changes will be made only if the array has more or less + * objects or if one or more object has changed. Reordering the objects will + * not cause an update. + * + * @param name + * The id of the attribute. + * @param values + * Attribute values. + */ + public void setAttributeValues(String name, Object[] values); + + /** + * Sets a multivalue attribute. + * + * If value is null or value.length == 0 then the attribute will be removed. + * + * If update mode, changes will be made if the array has more or less + * objects or if one or more string has changed. + * + * Reordering the objects will only cause an update if orderMatters is set + * to true. + * + * @param name + * The id of the attribute. + * @param values + * Attribute values. + * @param orderMatters + * If true, it will be changed even if data was + * just reordered. + */ + public void setAttributeValues(String name, Object[] values, + boolean orderMatters); + + /** + * Update the attributes. This will mean that the getters + * (getStringAttribute methods) will return the updated values. Remove the + * attributes to be updated. + */ + public void update(); + + /** + * Get all values of a String attribute. + * + * @param name + * name of the attribute. + * + * @return all registered values of the attribute. + */ + public String[] getStringAttributes(String name); + + /** + * Get all String values of the attribute as a SortedSet. + * + * @param name + * name of the attribute. + * @return a SortedSet containing all values of the attribute. + */ + public SortedSet getAttributeSortedStringSet(String name); + + /** + * Returns DN, without the base path. + * + * @return The distinguished name of the current context. + * + * @see DirContextAdapter#getNameInNamespace() + */ + public Name getDn(); + + /** + * Set the dn of this entry. + * + * @param dn + * the dn. + */ + public void setDn(Name dn); +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java new file mode 100644 index 00000000..e69d6a0a --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; + +/** + * ContextSource implementation which creates InitialDirContext instances, for + * LDAPv2 compatibility. For configuration information, see + * {@link org.springframework.ldap.support.AbstractContextSource AbstractContextSource}. + * + * @see org.springframework.ldap.support.AbstractContextSource + * + * @author Mattias Arthursson + */ +public class DirContextSource extends AbstractContextSource { + + /** + * Create a new InitialDirContext instance. + * + * @param environment + * the environment to use when creating the context. + * @return a new InitialDirContext implementation. + */ + protected DirContext getDirContextInstance(Hashtable environment) + throws NamingException { + return new InitialDirContext(environment); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java new file mode 100644 index 00000000..bb5392cd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java @@ -0,0 +1,629 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import javax.naming.CompositeName; +import javax.naming.InvalidNameException; +import javax.naming.Name; + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.BadLdapGrammarException; +import org.springframework.ldap.util.ListComparator; + +/** + * Default implementation of a Name corresponding to an LDAP path. A + * DistinguishedName implementation is included in JDK1.5 (LdapName), but not in + * prior releases. + * + * An DistinguishedName is particularly useful when building or modifying an + * Ldap path dynamically, as escaping will be taken care of. + * + * A path is split into several names. The Name interface specifies that the + * most significant part be in position 0, i.e. + * + * The path: uid=adam.skogman, ou=People, ou=EU Name[0]: ou=EU Name[1]: + * ou=People Name[2]: uid=adam.skogman + *

+ * Useful for parsing and building LDAP paths. + * + *

+ * DistinguishedName path = new DistinguishedName();
+ * path.addLast("cn", entry.getUid());
+ * path.addLast("ou", "users");
+ * path.append(new DistinguishedName(helpdesk.getSomeSuffix()));
+ * String dn = path.toString();
+ * 
+ * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DistinguishedName implements Name { + private static final long serialVersionUID = 3514344371999042586L; + + /** + * An empty, unmodifiable DistinguishedName. + */ + public static final DistinguishedName EMPTY_PATH = new DistinguishedName( + Collections.EMPTY_LIST); + + private List names; + + /** + * Construct a new DistinguishedName with no components. + */ + public DistinguishedName() { + names = new LinkedList(); + } + + /** + * Construct a new DistinguishedName from a String. + * + * @param path + * a String corresponding to a (syntactically) valid LDAP path. + */ + public DistinguishedName(String path) { + if (StringUtils.isBlank(path)) { + names = new LinkedList(); + } else { + parse(path); + } + } + + /** + * Construct a new DistinguishedName from the supplied List of LdapRdn + * objects. + * + * @param list + * the components that this instance will consist of. + */ + public DistinguishedName(List list) { + this.names = list; + } + + /** + * Construct a new DistinguishedName from the supplied Name. The parts of + * the supplied Name must be syntactically correct LdapRdns. + * + * @param name + * the Name to construct a new DistinguishedName from. + */ + public DistinguishedName(Name name) { + names = new LinkedList(); + for (int i = 0; i < name.size(); i++) { + names.add(new LdapRdn(name.get(i))); + } + } + + /** + * Parse the supplied String and make this instance represent the + * corresponding distinguished name. + * + * @param path + * the LDAP path to parse. + */ + protected void parse(String path) { + DnParser parser = DefaultDnParserFactory + .createDnParser(unmangleCompositeName(path)); + DistinguishedName dn; + try { + dn = parser.dn(); + } catch (ParseException e) { + throw new BadLdapGrammarException("Failed to parse DN", e); + } catch (TokenMgrError e) { + throw new BadLdapGrammarException("Failed to parse DN", e); + } + this.names = dn.names; + } + + /** + * If path is surrounded by quotes, strip them. JNDI considers forward slash + * ('/') special, but LDAP doesn't. {@link CompositeName#toString()} tends + * to mangle a Name with a slash by surrounding it with quotes ('"'). + * + * @param path + * Path to check and possibly strip. + * @return A String with the possibly stripped path. + */ + private String unmangleCompositeName(String path) { + String tempPath; + // Check if CompositeName has mangled the name with quotes + if (path.startsWith("\"") && path.endsWith("\"")) { + tempPath = path.substring(1, path.length() - 1); + } else { + tempPath = path; + } + return tempPath; + } + + /** + * Get the LdapRdn at a specified position. + * + * @param index + * the LdapRdn to retrieve. + * @return the LdapRdn at the requested position. + */ + public LdapRdn getLdapRdn(int index) { + return (LdapRdn) names.get(index); + } + + /** + * Get the name list. + * + * @return the list of LdapRdns that this DistinguishedName consists of. + */ + public List getNames() { + return names; + } + + /** + * Get the String representation of this DistinguishedName. + * + * @return a syntactically correct, escaped String representation of the + * DistinguishedName. + */ + public String toString() { + return encode(); + } + + /** + * Builds a complete LDAP path, ldap encoded, useful as a DN. + * + * Always uses lowercase, always separates with ", " i.e. comma and a space. + * + * @return the LDAP path. + */ + public String encode() { + + // empty path + if (names.size() == 0) + return ""; + + StringBuffer buffer = new StringBuffer(256); + + ListIterator i = names.listIterator(names.size()); + while (i.hasPrevious()) { + LdapRdn rdn = (LdapRdn) i.previous(); + buffer.append(rdn.getLdapEncoded()); + + // add comma, except in last iteration + if (i.hasPrevious()) + buffer.append(", "); + } + + return buffer.toString(); + + } + + /** + * Builds a complete LDAP path, ldap and url encoded. Separates only with + * ",". + * + * @return the LDAP path, for use in an url. + */ + public String toUrl() { + StringBuffer buffer = new StringBuffer(256); + + for (int i = names.size() - 1; i >= 0; i--) { + LdapRdn n = (LdapRdn) names.get(i); + buffer.append(n.encodeUrl()); + if (i > 0) { + buffer.append(","); + } + } + return buffer.toString(); + } + + /** + * Determines if a ldap path contains another path. + * + * @param path + * the path to check. + * @return true if the supplied path is conained in this instance, false + * otherwise. + */ + public boolean contains(DistinguishedName path) { + + List shortlist = path.getNames(); + + // this path must be at least as long + if (getNames().size() < shortlist.size()) + return false; + + // must have names + if (shortlist.size() == 0) + return false; + + Iterator longiter = getNames().iterator(); + Iterator shortiter = shortlist.iterator(); + + LdapRdn longname = (LdapRdn) longiter.next(); + LdapRdn shortname = (LdapRdn) shortiter.next(); + + // find first match + while (!longname.equals(shortname) && longiter.hasNext()) { + longname = (LdapRdn) longiter.next(); + } + + // Done? + if (!shortiter.hasNext() && longname.equals(shortname)) + return true; + if (!longiter.hasNext()) + return false; + + // compare + while (longname.equals(shortname) && longiter.hasNext() + && shortiter.hasNext()) { + longname = (LdapRdn) longiter.next(); + shortname = (LdapRdn) shortiter.next(); + } + + // Done + if (!shortiter.hasNext() && longname.equals(shortname)) + return true; + else + return false; + + } + + /** + * Add a LDAP path first + * + * @param path + */ + public void append(DistinguishedName path) { + getNames().addAll(path.getNames()); + } + + /** + * Add a LDAP path first + * + * @param path + */ + public void prepend(DistinguishedName path) { + ListIterator i = path.getNames().listIterator(path.getNames().size()); + while (i.hasPrevious()) { + names.add(0, i.previous()); + } + } + + /** + * Remove the first part of this DistinguishedName. + * + * @return the removed entry. + */ + public LdapRdn removeFirst() { + return (LdapRdn) names.remove(0); + } + + /** + * Remove the supplied path from the beginning of this DistinguishedName if + * this instance starts with . Useful for stripping base path suffix + * from a DistinguishedName. + * + * @param path + * the path to remove from the beginning of this instance. + */ + public void removeFirst(Name path) { + if (path != null && this.startsWith(path)) { + for (int i = 0; i < path.size(); i++) + this.removeFirst(); + } + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + + // just duplicate the list, the rdns are immutable. + LinkedList list = new LinkedList(getNames()); + + return new DistinguishedName(list); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + + DistinguishedName name = (DistinguishedName) obj; + + // compare the lists + return getNames().equals(name.getNames()); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.getClass().hashCode() ^ getNames().hashCode(); + } + + /** + * Compare this instance to another object. Note that the comparison is done + * in order of significance, so the most significant Rdn is compared first, + * then the second and so on. + * + * @see javax.naming.Name#compareTo(java.lang.Object) + */ + public int compareTo(Object obj) { + DistinguishedName that = (DistinguishedName) obj; + ListComparator comparator = new ListComparator(); + return comparator.compare(this.names, that.names); + } + + public int size() { + return names.size(); + } + + public boolean isEmpty() { + return names.size() == 0; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getAll() + */ + public Enumeration getAll() { + LinkedList strings = new LinkedList(); + for (Iterator iter = names.iterator(); iter.hasNext();) { + LdapRdn rdn = (LdapRdn) iter.next(); + strings.add(rdn.getLdapEncoded()); + } + + return Collections.enumeration(strings); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#get(int) + */ + public String get(int index) { + LdapRdn rdn = (LdapRdn) names.get(index); + return rdn.getLdapEncoded(); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getPrefix(int) + */ + public Name getPrefix(int index) { + LinkedList newNames = new LinkedList(); + for (int i = 0; i < index; i++) { + newNames.add(names.get(i)); + } + + return new DistinguishedName(newNames); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getSuffix(int) + */ + public Name getSuffix(int index) { + if (index > names.size()) { + throw new ArrayIndexOutOfBoundsException(); + } + + LinkedList newNames = new LinkedList(); + for (int i = index; i < names.size(); i++) { + newNames.add(names.get(i)); + } + + return new DistinguishedName(newNames); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#startsWith(javax.naming.Name) + */ + public boolean startsWith(Name name) { + if (name.size() == 0) { + return false; + } + + DistinguishedName start = null; + if (name instanceof DistinguishedName) { + start = (DistinguishedName) name; + } else { + return false; + } + + if (start.size() > this.size()) { + return false; + } + + Iterator longiter = names.iterator(); + Iterator shortiter = start.getNames().iterator(); + + while (shortiter.hasNext()) { + Object longname = longiter.next(); + Object shortname = shortiter.next(); + + if (!longname.equals(shortname)) { + return false; + } + } + + // All names in shortiter matched. + return true; + } + + /** + * Determines if this ldap path ends with a certian path. + * + * If the argument path is empty (no names in path) this methid will return + * false. + * + * @param name + * The suffix to check for + * + */ + public boolean endsWith(Name name) { + DistinguishedName path = null; + if (name instanceof DistinguishedName) { + path = (DistinguishedName) name; + } else { + return false; + } + + List shortlist = path.getNames(); + + // this path must be at least as long + if (getNames().size() < shortlist.size()) + return false; + + // must have names + if (shortlist.size() == 0) + return false; + + ListIterator longiter = getNames().listIterator(getNames().size()); + ListIterator shortiter = shortlist.listIterator(shortlist.size()); + + while (shortiter.hasPrevious()) { + LdapRdn longname = (LdapRdn) longiter.previous(); + LdapRdn shortname = (LdapRdn) shortiter.previous(); + + if (!longname.equals(shortname)) + return false; + } + + // if short list ended, all were equal + return true; + + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#addAll(javax.naming.Name) + */ + public Name addAll(Name name) throws InvalidNameException { + return addAll(names.size(), name); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#addAll(int, javax.naming.Name) + */ + public Name addAll(int arg0, Name name) throws InvalidNameException { + DistinguishedName distinguishedName = null; + try { + distinguishedName = (DistinguishedName) name; + } catch (ClassCastException e) { + throw new InvalidNameException("Invalid name type"); + } + + names.addAll(arg0, distinguishedName.getNames()); + return this; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#add(java.lang.String) + */ + public Name add(String string) throws InvalidNameException { + return add(names.size(), string); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#add(int, java.lang.String) + */ + public Name add(int index, String string) throws InvalidNameException { + try { + names.add(index, new LdapRdn(string)); + } catch (BadLdapGrammarException e) { + throw new InvalidNameException("Failed to parse rdn '" + string + + "'"); + } + return this; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#remove(int) + */ + public Object remove(int arg0) throws InvalidNameException { + LdapRdn rdn = (LdapRdn) names.remove(arg0); + return rdn.getLdapEncoded(); + } + + /** + * Remove the ldast part of this DistinguishedName. + * + * @return the removed LdapRdn. + */ + public LdapRdn removeLast() { + return (LdapRdn) names.remove(names.size() - 1); + } + + /** + * Add a new LdapRdn using the supplied key and value. + * + * @param key + * the key of the LdapRdn. + * @param value + * the value of the LdapRdn. + */ + public void add(String key, String value) { + names.add(new LdapRdn(key, value)); + } + + /** + * Add the supplied LdapRdn last in the list of Rdns. + * + * @param rdn + * the LdapRdn to add. + */ + public void add(LdapRdn rdn) { + names.add(rdn); + } + + /** + * Add the supplied LdapRdn att the specified index. + * + * @param idx + * the index at which to add the LdapRdn. + * @param rdn + * the LdapRdn to add. + */ + public void add(int idx, LdapRdn rdn) { + names.add(idx, rdn); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DnParser.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DnParser.java new file mode 100644 index 00000000..7bd29baa --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/DnParser.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + + +/** + * A parser for RFC2253-compliant Distinguished Names. + * + * @author Mattias Arthursson + * + */ +public interface DnParser { + /** + * Parse a full Distinguished Name. + * + * @return the DistinguishedName corresponding to the parsed stream. + */ + public DistinguishedName dn() throws ParseException; + + /** + * Parse a Relative Distinguished Name. + * + * @return the next rdn on the stream. + */ + public LdapRdn rdn() throws ParseException; +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java new file mode 100644 index 00000000..ef3e7597 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.ControlFactory; +import javax.naming.ldap.InitialLdapContext; +import javax.naming.ldap.LdapContext; + +import com.sun.jndi.ldap.ctl.ResponseControlFactory; + +/** + * ContextSource implementation which creates an InitialLdapContext + * instance. For configuration information, see + * {@link org.springframework.ldap.support.AbstractContextSource AbstractContextSource}. + * + * @see org.springframework.ldap.support.AbstractContextSource + * + * @author Mattias Arthursson + * @author Adam Skogman + * @author Ulrik Sandberg + */ +public class LdapContextSource extends AbstractContextSource { + + private static final Class DEFAULT_RESPONSE_CONTROL_FACTORY = ResponseControlFactory.class; + + private Class responseControlFactory = DEFAULT_RESPONSE_CONTROL_FACTORY; + + protected Hashtable getAnonymousEnv() { + Hashtable env = super.getAnonymousEnv(); + env + .put(LdapContext.CONTROL_FACTORIES, responseControlFactory + .getName() + ".trasig"); + return env; + } + + /* + * @see org.springframework.ldap.support.AbstractContextSource#getDirContextInstance(java.util.Hashtable) + */ + protected DirContext getDirContextInstance(Hashtable environment) + throws NamingException { + return new InitialLdapContext(environment, null); + } + + /** + * Set the ResponseControlFactory to use. Default is + * {@link com.sun.jndi.ldap.ctl.ResponseControlFactory}. The specified + * class needs to be an implementation of + * {@link javax.naming.ldap.ControlFactory}. + * + * @param responseControlFactory + * the ResponseControlFactory to be used. Null means reset to the + * default. + */ + public void setResponseControlFactory(Class responseControlFactory) { + if (responseControlFactory == null) { + this.responseControlFactory = DEFAULT_RESPONSE_CONTROL_FACTORY; + } else if (ControlFactory.class + .isAssignableFrom(responseControlFactory)) { + this.responseControlFactory = responseControlFactory; + } else { + throw new IllegalArgumentException( + "Invalid ReponseControlFactory: " + responseControlFactory + + " is not an implementation of " + + ControlFactory.class.getName()); + } + } + + /** + * @return the current ResponseControlFactory. + */ + Class getResponseControlFactory() { + return responseControlFactory; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java new file mode 100644 index 00000000..d6525bc2 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java @@ -0,0 +1,235 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Helper class to encode and decode ldap names and values. + * + * @author Adam Skogman + */ +public class LdapEncoder { + + static private String[] nameEscapeTable = new String[96]; + + static private String[] filterEscapeTable = new String['\\' + 1]; + + /** + * Pattern for matching escaped ldap name values. + * + * Double escaping: \ -> \\ (in pattern) -> \\\\ (in java string literal) + * + * Group 1: Hex escapes = \XX -> \p{XDigit}{2} Group 2: Ordinary escapes = + * \x -> \. Group 3: Anything but \ [^\\] + * + * Note that the \ is not part of the match. + */ + static private final Pattern VALUE_DECODE_PATTERN = Pattern + .compile("(?:\\\\(\\p{XDigit}{2}))|(?:\\\\(.))|([^\\\\])"); + + static { + + // Name encoding table ------------------------------------- + + // all below 0x20 (control chars) + for (char c = 0; c < ' '; c++) { + nameEscapeTable[c] = "\\" + toTwoCharHex(c); + } + + nameEscapeTable['#'] = "\\#"; + nameEscapeTable[','] = "\\,"; + nameEscapeTable[';'] = "\\;"; + nameEscapeTable['='] = "\\="; + nameEscapeTable['+'] = "\\+"; + nameEscapeTable['<'] = "\\<"; + nameEscapeTable['>'] = "\\>"; + // nameEscapeTable['\''] = "\\"; + nameEscapeTable['\"'] = "\\\""; + // nameEscapeTable['/'] = "\\" + toTwoCharHex('/'); + nameEscapeTable['\\'] = "\\\\"; + + // Filter encoding table ------------------------------------- + + // fill with char itself + for (char c = 0; c < filterEscapeTable.length; c++) { + filterEscapeTable[c] = String.valueOf(c); + } + + // escapes (RFC2254) + filterEscapeTable['*'] = "\\2a"; + filterEscapeTable['('] = "\\28"; + filterEscapeTable[')'] = "\\29"; + filterEscapeTable['\\'] = "\\5c"; + filterEscapeTable[0] = "\\00"; + + } + + static protected String toTwoCharHex(char c) { + + String raw = Integer.toHexString(c).toUpperCase(); + + if (raw.length() > 1) + return raw; + else + return "0" + raw; + } + + /** + * All static methods + */ + private LdapEncoder() { + } + + static public String filterEncode(String value) { + + if (value == null) + return null; + + // make buffer roomy + StringBuffer encodedValue = new StringBuffer(value.length() * 2); + + int length = value.length(); + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + if (c < filterEscapeTable.length) { + encodedValue.append(filterEscapeTable[c]); + } else { + // default: add the char + encodedValue.append(c); + } + } + + return encodedValue.toString(); + } + + /** + * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! + * + *
Escapes:
' ' [space] - "\ " [if first or last]
'#' + * [hash] - "\#"
',' [comma] - "\,"
';' [semicolon] - "\;"
'= + * [equals] - "\="
'+' [plus] - "\+"
'<' [less than] - + * "\<"
'>' [greater than] - "\>"
'"' [double quote] - + * "\""
'\' [backslash] - "\\"
+ * + * @param value + * @return The escaped value + */ + static public String nameEncode(String value) { + + if (value == null) + return null; + + // make buffer roomy + StringBuffer encodedValue = new StringBuffer(value.length() * 2); + + int length = value.length(); + int last = length - 1; + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + // space first or last + if (c == ' ' && (i == 0 || i == last)) { + encodedValue.append("\\ "); + continue; + } + + if (c < nameEscapeTable.length) { + // check in table for escapes + String esc = nameEscapeTable[c]; + + if (esc != null) { + encodedValue.append(esc); + continue; + } + } + + // default: add the char + encodedValue.append(c); + } + + return encodedValue.toString(); + + } + + /** + * Decodes a value. Converts escaped chars to ordinary chars. + * + * @param value + * Trimmed value, so no leading an trailing blanks, except an + * escaped space last. + * @return The decoded value as a string. + * @throws BadLdapGrammarException + */ + static public String nameDecode(String value) + throws BadLdapGrammarException { + + if (value == null) + return null; + + // make buffer same size + StringBuffer decoded = new StringBuffer(value.length()); + + Matcher matcher = VALUE_DECODE_PATTERN.matcher(value); + + int end = 0; + + while (matcher.find()) { + end = matcher.end(); + // group 1 + if (matcher.group(1) != null) { + // parse as hex = base 16 + try { + char c = (char) Integer.parseInt(matcher.group(1), 16); + decoded.append(c); + } catch (NumberFormatException e) { + throw new BadLdapGrammarException( + "Escaped hex value Could not be parsed. Found '\\" + + matcher.group(1) + "'"); + } + } else if (matcher.group(2) != null) { + // just add, we stripped away the \ + decoded.append(matcher.group(2)); + } else if (matcher.group(3) != null) { + // just add + decoded.append(matcher.group(3)); + } + + } + // end is match + +1 so it should be same as length, i.e. + // last + 1 + if (end < value.length()) { + throw new BadLdapGrammarException( + "RDN could not be parsed fully, remaining '" + + StringUtils.substring(value, end) + "'"); + } + + return decoded.toString(); + + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java new file mode 100644 index 00000000..f5ccdd6d --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java @@ -0,0 +1,198 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.ldap.BadLdapGrammarException; +import org.springframework.ldap.util.ListComparator; + +/** + * Datatype for a LDAP name, a part of a path. + * + * The name: uid=adam.skogman Key: uid Value: adam.skogman + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class LdapRdn implements Serializable, Comparable { + private static final long serialVersionUID = 5681397547245228750L; + + private List components = new LinkedList(); + + /** + * Default constructor. + */ + public LdapRdn() { + } + + /** + * Parse the supplied string and construct this instance accordingly. + * + * @param string + * the string to parse. + */ + public LdapRdn(String string) { + DnParser parser = DefaultDnParserFactory.createDnParser(string); + LdapRdn rdn; + try { + rdn = parser.rdn(); + } catch (ParseException e) { + throw new BadLdapGrammarException("Failed to parse Rdn", e); + } catch (TokenMgrError e) { + throw new BadLdapGrammarException("Failed to parse Rdn", e); + } + this.components = rdn.components; + } + + /** + * Construct an LdapRdn using the supplied key and value. + * + * @param key + * @param value + */ + public LdapRdn(String key, String value) { + components.add(new LdapRdnComponent(key, value)); + } + + /** + * Add an LdapRdnComponent to this LdapRdn. + * + * @param rdnComponent + * the LdapRdnComponent to add.s + */ + public void addComponent(LdapRdnComponent rdnComponent) { + components.add(rdnComponent); + } + + /** + * Gets all components in this LdapRdn. + * + * @return the List of all LdapRdnComponents composing this LdapRdn. + */ + public List getComponents() { + return components; + } + + /** + * Gets the first LdapRdnComponent of this LdapRdn. + * + * @return The first LdapRdnComponent of this LdapRdn. + * @throws IndexOutOfBoundsException + * if no components have been added. + */ + public LdapRdnComponent getComponent() { + return (LdapRdnComponent) components.get(0); + } + + /** + * Get the LdapRdnComponent at index idx. + * + * @param idx + * the 0-based index of the component to get. + * @return the LdapRdnComponent at indet idx. + * @throws IndexOutOfBoundsException + * if no component exists at index idx. + */ + public LdapRdnComponent getComponent(int idx) { + return (LdapRdnComponent) components.get(idx); + } + + /** + * Get a properly rfc2253-encoded String representation to this LdapRdn. + * + * @return an encoded String corresponding to this LdapRdn. + */ + public String getLdapEncoded() { + if (components.size() == 0) { + throw new IndexOutOfBoundsException("No components in Rdn."); + } + StringBuffer sb = new StringBuffer(100); + for (Iterator iter = components.iterator(); iter.hasNext();) { + LdapRdnComponent component = (LdapRdnComponent) iter.next(); + sb.append(component.encodeLdap()); + if (iter.hasNext()) { + sb.append("+"); + } + } + + return sb.toString(); + } + + /** + * Get a String representation of this LdapRdn for use in urls. + * + * @return a String representation of this LdapRdn for use in urls. + */ + public String encodeUrl() { + StringBuffer sb = new StringBuffer(100); + for (Iterator iter = components.iterator(); iter.hasNext();) { + LdapRdnComponent component = (LdapRdnComponent) iter.next(); + sb.append(component.encodeUrl()); + if (iter.hasNext()) { + sb.append("+"); + } + } + + return sb.toString(); + } + + /** + * Compare this LdapRdn to another object. + * + * @param obj + * the object to compare to. + * @throws ClassCastException + * if the supplied object is not an LdapRdn instance. + */ + public int compareTo(Object obj) { + LdapRdn that = (LdapRdn) obj; + Comparator comparator = new ListComparator(); + return comparator.compare(this.components, that.components); + } + + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + + LdapRdn that = (LdapRdn) obj; + return this.getComponents().equals(that.getComponents()); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.getClass().hashCode() ^ getComponents().hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return getLdapEncoded(); + } +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java new file mode 100644 index 00000000..52bd4e72 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java @@ -0,0 +1,163 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; + +/** + * Represents part of an LdapRdn. As specified in RFC2253 an LdapRdn may be + * composed of several attributes, separated by "+". An + * LdapRdnComponent represents one of these attributes. + * + * @author Mattias Arthursson + * + */ +public class LdapRdnComponent implements Comparable { + public static final boolean DONT_DECODE_VALUE = false; + + private String key; + + private String value; + + /** + * Constructs an LdapRdnComponent without decoding the value. + * + * @param key + * the Atttribute name. + * @param value + * the Attribute value. + */ + public LdapRdnComponent(String key, String value) { + this(key, value, DONT_DECODE_VALUE); + } + + /** + * Constructs an LdapRdnComponent, optionally decoding the value. + * + * @param key + * the Atttribute name. + * @param value + * the Attribute value. + * @param decodeValue + * if true the value is decoded (typically used + * when a DN is parsed from a String), otherwise the value is + * used as specified. + */ + public LdapRdnComponent(String key, String value, boolean decodeValue) { + Validate.notEmpty(key, "Key must not be empty"); + Validate.notEmpty(value, "Value must not be empty"); + + this.key = StringUtils.lowerCase(key); + if (decodeValue) { + this.value = LdapEncoder.nameDecode(value); + } else { + this.value = value; + } + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + /** + * Encode key and value to ldap + * + * @return The ldap encoded rdn + */ + protected String encodeLdap() { + StringBuffer buff = new StringBuffer(key.length() + value.length() * 2); + + buff.append(key); + buff.append('='); + buff.append(LdapEncoder.nameEncode(value)); + + return buff.toString(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return getLdapEncoded(); + } + + /** + * @return The LdapRdn as a string where the value is LDAP-encoded. + */ + public String getLdapEncoded() { + return encodeLdap(); + } + + public String encodeUrl() { + // Use the URI class to properly URL encode the value. + try { + URI valueUri = new URI(null, null, value, null); + return key + "=" + valueUri.toString(); + } catch (URISyntaxException e) { + // This should really never happen... + return key + "=" + "value"; + } + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return key.hashCode() ^ value.hashCode(); + } + + public boolean equals(Object obj) { + if (obj != null && obj.getClass() == LdapRdnComponent.class) { + LdapRdnComponent that = (LdapRdnComponent) obj; + return StringUtils.equalsIgnoreCase(this.key, that.key) + && StringUtils.equalsIgnoreCase(this.value, that.value); + + } else { + return false; + } + } + + /** + * Compare this instance to the supplied object. + * + * @param obj + * the object to compare to. + * @throws ClassCastException + * if the object is not possible to cast to an LdapRdnComponent. + */ + public int compareTo(Object obj) { + LdapRdnComponent that = (LdapRdnComponent) obj; + return this.toString().compareTo(that.toString()); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java new file mode 100644 index 00000000..1e28a087 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import org.acegisecurity.Authentication; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.AuthenticationSource; + + +/** + * An AuthenticationSource to retrieve authentication information stored in + * Acegi's SecurityContextHolder. Use Acegi's LdapAuthenticationProvider have a + * LdapUserDetails object placed in the authentication. + * + * @author Mattias Arthursson + * + */ +public class AcegiAuthenticationSource implements AuthenticationSource { + private static final Log log = LogFactory + .getLog(AcegiAuthenticationSource.class); + + /** + * Get the principals of the logged in user, in this case the distinguished + * name. + * + * @return the distinguished name of the logged in user. + */ + public String getPrincipal() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (!(principal instanceof LdapUserDetails)) { + throw new IllegalArgumentException( + "The principal property of the authentication object -" + + "needs to be a LdapUserDetails."); + } else { + LdapUserDetails details = (LdapUserDetails) principal; + return details.getDn(); + } + } else { + log.warn("No Authentication object set in SecurityContext - " + + "returning empty String as Principal"); + return ""; + } + } + + /* + * @see org.springframework.ldap.AuthenticationSource#getCredentials() + */ + public String getCredentials() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + + if (authentication != null) { + return (String) authentication.getCredentials(); + } else { + log.warn("No Authentication object set in SecurityContext - " + + "returning empty String as Credentials"); + return ""; + } + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java new file mode 100644 index 00000000..ed94d937 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.ldap.AuthenticationSource; + +/** + * Decorator on AuthenticationSource to have default authentication information + * be returned should the target return empty principal and credentials. Useful + * in combination with {@link AcegiAuthenticationSource} if users are to be + * allowed to read some information even though they are not logged in. + *

+ * Note: The defaultUser should be an non-privileged + * user. This is important as this is the one that will be used when no user is + * logged in (i.e. empty principal is returned from the target + * AuthenticationSource). + * + * @author Mattias Arthursson + * + */ +public class DefaultValuesAuthenticationSourceDecorator implements + AuthenticationSource, InitializingBean { + + private AuthenticationSource target; + + private String defaultUser; + + private String defaultPassword; + + /** + * Constructor for bean usage. + */ + public DefaultValuesAuthenticationSourceDecorator() { + } + + /** + * Constructor to setup instance directly. + * + * @param target + * the target AuthenticationSource. + * @param defaultUser + * dn of the user to use when the target returns an empty + * principal. + * @param defaultPassword + * password of the user to use when the target returns an empty + * principal. + */ + public DefaultValuesAuthenticationSourceDecorator( + AuthenticationSource target, String defaultUser, + String defaultPassword) { + this.target = target; + this.defaultUser = defaultUser; + this.defaultPassword = defaultPassword; + } + + /** + * Checks if the target's principal is not empty; if not, the credentials + * from the target is returned - otherwise return the + * defaultPassword. + * + * @return the target's password if the target's principal is not empty, the + * defaultPassword otherwise. + */ + public String getCredentials() { + if (StringUtils.isNotEmpty(target.getPrincipal())) { + return target.getCredentials(); + } else { + return defaultPassword; + } + } + + /** + * Checks if the target's principal is not empty; if not, this is returned - + * otherwise return the defaultUser. + * + * @return the target's principal if it is not empty, the + * defaultUser otherwise. + */ + public String getPrincipal() { + String principal = target.getPrincipal(); + if (StringUtils.isNotEmpty(principal)) { + return principal; + } else { + return defaultUser; + } + } + + /** + * Set the password of the default user. + * + * @param defaultPassword + * the password of the default user. + */ + public void setDefaultPassword(String defaultPassword) { + this.defaultPassword = defaultPassword; + } + + /** + * Set the default user DN. This should be a non-privileged user, since it + * will be used when no authentication information is returned from the + * target. + * + * @param defaultUser + * DN of the default user. + */ + public void setDefaultUser(String defaultUser) { + this.defaultUser = defaultUser; + } + + /** + * Set the target AuthenticationSource. + * + * @param target + * the target AuthenticationSource. + */ + public void setTarget(AuthenticationSource target) { + this.target = target; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + if (target == null) { + throw new IllegalArgumentException( + "Property 'target' must be set.'"); + } + + if (defaultUser == null) { + throw new IllegalArgumentException( + "Property 'defaultUser' must be set.'"); + } + + if (defaultPassword == null) { + throw new IllegalArgumentException( + "Property 'defaultPassword' must be set.'"); + } + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/package.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/package.html new file mode 100644 index 00000000..d15fe6bc --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/authentication/package.html @@ -0,0 +1,3 @@ + +Support classes for custom authentication. + diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java new file mode 100644 index 00000000..3d54d9c4 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java @@ -0,0 +1,90 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.DirContextProcessor; + +/** + * Abstract superclass with responsibility to apply a single RequestControl on + * an LdapContext, preserving any existing controls. Subclasses should implement + * {@link DirContextProcessor#postProcess(DirContext)} and template method + * {@link #createRequestControl()}. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public abstract class AbstractRequestControlDirContextProcessor implements + DirContextProcessor { + protected Log log = LogFactory + .getLog(AbstractRequestControlDirContextProcessor.class); + + /** + * Get the existing RequestControls from the LdapContext, call + * {@link #createRequestControl()} to get a new instance, build a new array + * of Controls and set it on the LdapContext. + *

+ * The {@link Control} feature is specific for LDAP v3 and thus applies only + * to {@link LdapContext}. However, the generic DirContextProcessor + * mechanism used for calling preProcess and + * postProcess uses DirContext, since it also works for LDAP + * v2. This is the reason that DirContext has to be cast into LdapContext. + * + * @param ctx + * an LdapContext instance. + * @throws NamingException + * @throws IllegalArgumentException + * if the supplied DirContext is not an LdapContext. + */ + public void preProcess(DirContext ctx) throws NamingException { + LdapContext ldapContext; + if (ctx instanceof LdapContext) { + ldapContext = (LdapContext) ctx; + } else { + throw new IllegalArgumentException( + "Request Control operations require LDAPv3 - " + + "Context must be of type LdapContext"); + } + + Control[] requestControls = ldapContext.getRequestControls(); + Control newControl = createRequestControl(); + + Control[] newControls = new Control[requestControls.length + 1]; + for (int i = 0; i < requestControls.length; i++) { + newControls[i] = requestControls[i]; + } + + // Add the new Control at the end of the array. + newControls[newControls.length - 1] = newControl; + + ldapContext.setRequestControls(newControls); + } + + /** + * Create an instance of the appropriate RequestControl. + * + * @return the new instance. + */ + public abstract Control createRequestControl(); + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java new file mode 100644 index 00000000..cbd0fe9a --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import com.sun.jndi.ldap.ctl.PagedResultsControl; + +/** + * Wrapper class for the cookie returned when using the + * {@link PagedResultsControl}. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PagedResultsCookie { + + private byte[] cookie; + + /** + * Constructor. + * + * @param cookie + * the cookie returned by a PagedResultsResponseControl. + */ + public PagedResultsCookie(byte[] cookie) { + this.cookie = cookie; + } + + /** + * Get the cookie. + * + * @return the cookie. + */ + public byte[] getCookie() { + return cookie; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java new file mode 100644 index 00000000..ab85e3c6 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java @@ -0,0 +1,200 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import org.springframework.ldap.UncategorizedLdapException; +import org.springframework.util.ReflectionUtils; + +import com.sun.jndi.ldap.ctl.PagedResultsControl; +import com.sun.jndi.ldap.ctl.PagedResultsResponseControl; + +/** + * DirContextProcessor implementation for managing the paged results. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PagedResultsRequestControl extends + AbstractRequestControlDirContextProcessor { + + private static final Class DEFAULT_RESPONSE_CONTROL = PagedResultsResponseControl.class; + + private static final boolean CRITICAL_CONTROL = true; + + private static final String JAVA5_RESPONSE_CONTROL = "javax.naming.ldap.PagedResultsResponseControl"; + + private int pageSize; + + private PagedResultsCookie cookie; + + private int resultSize; + + private Class responseControlClass = DEFAULT_RESPONSE_CONTROL; + + private Class fallbackResponseControlClass; + + private Class currentResponseControlClass; + + public PagedResultsRequestControl(int pageSize) { + this(pageSize, null); + } + + public PagedResultsRequestControl(int pageSize, PagedResultsCookie cookie) { + this.pageSize = pageSize; + this.cookie = cookie; + fallbackResponseControlClass = loadFallbackResponseControlClass(); + } + + public PagedResultsCookie getCookie() { + return cookie; + } + + public int getPageSize() { + return pageSize; + } + + public int getResultSize() { + return resultSize; + } + + /** + * Set the class of the expected ResponseControl for the paged results + * response. The default is {@link PagedResultsResponseControl}. + * + * @param responseControlClass + * Class of the expected response control. + */ + public void setResponseControlClass(Class responseControlClass) { + this.responseControlClass = responseControlClass; + } + + /* + * @see org.springframework.ldap.support.control.AbstractRequestControlDirContextProcessor#createRequestControl() + */ + public Control createRequestControl() { + try { + if (cookie != null) { + return new PagedResultsControl(pageSize, cookie.getCookie(), + CRITICAL_CONTROL); + } else { + return new PagedResultsControl(pageSize); + } + } catch (IOException e) { + throw new UncategorizedLdapException( + "Error creating PagedResultsControl", e); + } + } + + /* + * @see org.springframework.ldap.DirContextProcessor#postProcess(javax.naming.directory.DirContext) + */ + public void postProcess(DirContext ctx) throws NamingException { + // initialize from property + currentResponseControlClass = responseControlClass; + + LdapContext ldapContext = (LdapContext) ctx; + Control[] responseControls = ldapContext.getResponseControls(); + + // Go through response controls and get info, regardless of class + for (int i = 0; i < responseControls.length; i++) { + Control responseControl = responseControls[i]; + + // check for match, try fallback otherwise + if (isPagedResultsResponseControl(responseControl)) { + Object control = responseControl; + byte[] result = (byte[]) invokeMethod("getCookie", + currentResponseControlClass, control); + this.cookie = new PagedResultsCookie(result); + Integer wrapper = (Integer) invokeMethod("getResultSize", + currentResponseControlClass, control); + this.resultSize = wrapper.intValue(); + } + } + } + + /** + * Check if the given control matches a paged results response control. Try + * the fallback class from Java5 if there is no match. Set the + * {@link #currentResponseControlClass} to the fallback if it matches. + * + * @param responseControl + * the control to check for a match + * @return whether the control is a paged results response control + */ + private boolean isPagedResultsResponseControl(Control responseControl) { + if (responseControl.getClass().isAssignableFrom( + currentResponseControlClass)) { + return true; + } + if (fallbackResponseControlClass != null + && responseControl.getClass().isAssignableFrom( + fallbackResponseControlClass)) { + currentResponseControlClass = fallbackResponseControlClass; + return true; + } + return false; + } + + private Class loadFallbackResponseControlClass() { + Class fallbackResponseControlClass = null; + try { + fallbackResponseControlClass = Class + .forName(JAVA5_RESPONSE_CONTROL); + } catch (ClassNotFoundException e) { + log.debug("Could not load Java5 response control class " + + JAVA5_RESPONSE_CONTROL); + } + return fallbackResponseControlClass; + } + + private Object invokeMethod(String method, Class clazz, Object control) { + // For Spring 2.0 ReflectionUtils could be used for all of this, but + // since we still want to support the 1.2 branch we do it manually and + // only use the stuff present in 1.2.8. + Method actualMethod = null; + Object retval = null; + try { + actualMethod = clazz.getMethod(method, new Class[0]); + } catch (SecurityException e) { + ReflectionUtils.handleReflectionException(e); + } catch (NoSuchMethodException e) { + ReflectionUtils.handleReflectionException(e); + } + + try { + retval = actualMethod.invoke(control, new Object[0]); + } catch (IllegalArgumentException e) { + ReflectionUtils.handleReflectionException(e); + } catch (IllegalAccessException e) { + ReflectionUtils.handleReflectionException(e); + } catch (InvocationTargetException e) { + ReflectionUtils.handleReflectionException(e); + } + + // Retval will be set unless an exception has been thrown. + return retval; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/package.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/package.html new file mode 100644 index 00000000..e8351194 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/control/package.html @@ -0,0 +1,3 @@ + +Support classes for custom request control context processors. + diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java new file mode 100644 index 00000000..e00f8f04 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Convenience class that implements most of the methods in the Filter + * interface. + * + * @author Adam Skogman + */ +public abstract class AbstractFilter implements Filter { + + protected AbstractFilter() { + super(); + } + + /** + * Prints the query with LDAP encoding to a stringbuffer + * + * @param buff + * The stringbuffer + * @return The very same stringbuffer + */ + public abstract StringBuffer encode(StringBuffer buff); + + /** + * Encodes the filter to a string using the (@link #encode(StringBuffer) + * method. + * + * @return The encoded filter + */ + public String encode() { + StringBuffer buff = new StringBuffer(256); + buff = encode(buff); + return buff.toString(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return encode(); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java new file mode 100644 index 00000000..4622da1f --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter for a logical AND. E.g.: + * + *

+ *     AndFilter filter = new AndFilter();
+ *     filter.and(new EqualsFilter("objectclass", "person");
+ *     filter.and(new EqualsFilter("cn", "Some CN");
+ *     System.out.println(filter.ecode());    
+ * 
+ * + * would result in: (&(objectclass=person)(cn=Some CN)) + * + * @see org.springframework.ldap.support.filter.EqualsFilter + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class AndFilter extends BinaryLogicalFilter { + + private static final String AMPERSAND = "&"; + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.filter.BinaryLogicalFilter#getLogicalOperator() + */ + protected String getLogicalOperator() { + return AMPERSAND; + } + + /** + * Add a query to the and expression + * + * @param query + * The query to and with the rest of the and:ed queries. + * @return This LdapAndQuery + */ + public AndFilter and(Filter query) { + queryList.add(query); + return this; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java new file mode 100644 index 00000000..0c3ef3a2 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Abstract superclass for binary logical operations, that is "and" + * and "or" operations. + * + * @author Mattias Arthursson + */ +public abstract class BinaryLogicalFilter extends AbstractFilter { + + protected List queryList = new LinkedList(); + + /** + * @see org.springframework.ldap.support.filter.Filter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + if (queryList.size() <= 0) { + + // only output query if contains anything + return buff; + + } else if (queryList.size() == 1) { + + // don't add the & + Filter query = (Filter) queryList.get(0); + return query.encode(buff); + + } else { + buff.append("(" + getLogicalOperator()); + + for (Iterator i = queryList.iterator(); i.hasNext();) { + Filter query = (Filter) i.next(); + buff = query.encode(buff); + } + + buff.append(")"); + + return buff; + } + } + + /** + * Implement this in subclass to return the logical operator, for example + * &qout;&&qout;. + * + * @return the logical operator. + */ + protected abstract String getLogicalOperator(); + + /** + * Compares each filter in turn + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj instanceof BinaryLogicalFilter + && this.getClass() == obj.getClass()) { + return EqualsBuilder.reflectionEquals(this, obj); + } else { + return false; + } + } + + /** + * Hashes all contained data + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java new file mode 100644 index 00000000..20fc78f0 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java @@ -0,0 +1,123 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.ldap.support.LdapEncoder; + +/** + * Abstract superclass for filters to compare values. + * + * @author Mattias Arthursson + */ +public abstract class CompareFilter extends AbstractFilter { + + private final String attribute; + + private final String value; + + private final String encodedValue; + + public CompareFilter(String attribute, String value) { + this.attribute = attribute; + this.value = value; + this.encodedValue = encodeValue(value); + } + + /** + * For testing purposes. + * + * @return the encoded value. + */ + String getEncodedValue() { + return encodedValue; + } + + /** + * Override to perform special encoding in subclass. + * + * @param value + * the value to encode. + * @return properly escaped value. + */ + protected String encodeValue(String value) { + return LdapEncoder.filterEncode(value); + } + + /** + * Convenience constructor for int values. + * + * @param attribute + * @param value + */ + public CompareFilter(String attribute, int value) { + this.attribute = attribute; + this.value = String.valueOf(value); + this.encodedValue = LdapEncoder.filterEncode(this.value); + } + + /* + * @see org.springframework.ldap.support.filter.AbstractFilter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + buff.append('('); + buff.append(attribute).append(getCompareString()).append(encodedValue); + buff.append(')'); + + return buff; + } + + /** + * Compares key and value before encoding. + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object o) { + if (o instanceof CompareFilter && o.getClass() == this.getClass()) { + CompareFilter that = (CompareFilter) o; + EqualsBuilder builder = new EqualsBuilder(); + builder.append(this.attribute, that.attribute); + builder.append(this.value, that.value); + return builder.isEquals(); + } else { + return false; + } + } + + /** + * Calculate the hash code for the attribute and the value. + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + HashCodeBuilder builder = new HashCodeBuilder(); + builder.append(attribute); + builder.append(value); + return builder.toHashCode(); + } + + /** + * Implement this method in subclass to return a String representing the + * operator. The {@link EqualsFilter#getCompareString()} would for example + * return an equals sign, "=". + * + * @return the String to use as operator in the comparison for the specific + * subclass. + */ + protected abstract String getCompareString(); +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java new file mode 100644 index 00000000..069d8186 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + + +/** + * A filter for 'equals'. The following code: + * + *
+ * EqualsFilter filter = new EqualsFilter("cn", "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + *
(cn=Some CN)
+ * + * @author Adam Skogman + */ +public class EqualsFilter extends CompareFilter { + + private static final String EQUALS_SIGN = "="; + + public EqualsFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Convenience constructor for int values. + * + * @param attribute Name of attribute in filter. + * @param value The value of the attribute in the filter. + */ + public EqualsFilter(String attribute, int value) { + super(attribute, value); + } + + /* + * @see org.springframework.ldap.support.filter.CompareFilter#getCompareString() + */ + protected String getCompareString() { + return EQUALS_SIGN; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java new file mode 100644 index 00000000..a5ae4f69 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Common interface for filters. + * + * @author Adam Skogman + */ +public interface Filter { + + /** + * Encodes the filter to a string using the (@link #encode(StringBuffer) + * method. + * + * @return The encoded filter + */ + public String encode(); + + /** + * Prints the query with LDAP encoding to a stringbuffer + * + * @param buff + * The stringbuffer + * @return The very same stringbuffer + */ + public StringBuffer encode(StringBuffer buff); + + /** + * All filters must implement equals. + * + * @param o + * @return true if the objects are equal. + */ + public boolean equals(Object o); + + /** + * All filters must implement hashCode() + * + * @return hascode + */ + public int hashCode(); + +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java new file mode 100644 index 00000000..871b8dd1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter to compare >=. LDAP RFC does not allow > comparison. The following + * code: + * + *
+ * GreaterThanOrEqualsFilter filter = new GreaterThanOrEqualsFilter("cn",
+ *         "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ * (cn>=Some CN)
+ * 
+ * + * @author Mattias Arthursson + */ +public class GreaterThanOrEqualsFilter extends CompareFilter { + + private static final String GREATER_THAN_OR_EQUALS = ">="; + + public GreaterThanOrEqualsFilter(String attribute, String value) { + super(attribute, value); + } + + public GreaterThanOrEqualsFilter(String attribute, int value) { + super(attribute, value); + } + + protected String getCompareString() { + return GREATER_THAN_OR_EQUALS; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java new file mode 100644 index 00000000..36b5e723 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter to compare <=. LDAP RFC does not allow < comparison. The following + * code: + * + *
+ * LessThanOrEqualsFilter filter = new LessThanOrEqualsFilter("cn", "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ * (cn<=Some CN)
+ * 
+ * + * @author Mattias Arthursson + */ +public class LessThanOrEqualsFilter extends CompareFilter { + + private static final String LESS_THAN_OR_EQUALS = "<="; + + public LessThanOrEqualsFilter(String attribute, String value) { + super(attribute, value); + } + + public LessThanOrEqualsFilter(String attribute, int value) { + super(attribute, value); + } + + protected String getCompareString() { + return LESS_THAN_OR_EQUALS; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java new file mode 100644 index 00000000..41d46ebd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.LdapEncoder; + +/** + * This filter allows the user to specify wildcards (*) by not escaping them in + * the filter. The following code: + * + *
+ * LikeFilter filter = new LikeFilter("cn", "foo*");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ *  (cn=foo*)
+ * 
+ * + * @author Anders Henja + * @author Mattias Arthursson + */ +public class LikeFilter extends EqualsFilter { + + public LikeFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Encodes a value according to the rules for this filter. + * + * @param value + * Value to encode. + * @return Encoded value. + */ + protected String encodeValue(String value) { + // just return if blank string + if (value == null) { + return ""; + } + + String[] substrings = value.split("\\*", -2); + + if (substrings.length == 1) { + return LdapEncoder.filterEncode(substrings[0]); + } + + StringBuffer buff = new StringBuffer(); + for (int i = 0; i < substrings.length; i++) { + buff.append(LdapEncoder.filterEncode(substrings[i])); + if (i < substrings.length - 1) { + buff.append("*"); + } else { + if (substrings[i].equals("")) { + continue; + } + } + } + + return buff.toString(); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java new file mode 100644 index 00000000..972edfa5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.apache.commons.lang.Validate; + +/** + * A filter for 'not'. The following code: + * + *
+ * Filter filter = new NotFilter(new EqualsFilter("cn", "foo");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
(!(cn=foo))
+ * + * @author Adam Skogman + */ +public class NotFilter extends AbstractFilter { + + private final Filter filter; + + static private final int HASH = "!".hashCode(); + + /** + * Create a filter that negates the outcome of the given filter. + * + * @param filter + * The filter that should be negated. + */ + public NotFilter(Filter filter) { + Validate.notNull(filter); + this.filter = filter; + } + + /** + * @see org.springframework.ldap.support.filter.Filter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + + buff.append("(!"); + filter.encode(buff); + buff.append(')'); + + return buff; + + } + + /** + * Compares key and value before encoding + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object o) { + + if (o instanceof NotFilter && o.getClass() == this.getClass()) { + NotFilter f = (NotFilter) o; + return this.filter.equals(f.filter); + } + + return false; + } + + /** + * hash attribute and value + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + return HASH ^ filter.hashCode(); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java new file mode 100644 index 00000000..20ff1ddf --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Filter for logical OR. + * + *
+ *        AndFilter filter = new AndFilter();
+ *        filter.or(new EqualsFilter("objectclass", "person");
+ *        filter.or(new EqualsFilter("objectclass", "organizationalUnit");
+ *        System.out.println(filter.ecode());    
+ * 
+ * + * would result in: + * (|(objectclass=person)(objectclass=organizationalUnit)) + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class OrFilter extends BinaryLogicalFilter { + + private static final String PIPE_SIGN = "|"; + + /** + * Add a query to the OR expression + * + * @param query + * The query to or with the rest of the or:ed queries. + * @return This LdapOrQuery + */ + public OrFilter or(Filter query) { + queryList.add(query); + return this; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.filter.BinaryLogicalFilter#getLogicalOperator() + */ + protected String getLogicalOperator() { + return PIPE_SIGN; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java new file mode 100644 index 00000000..bbd6b8d0 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.support.LdapEncoder; + +/** + * This filter automatically converts all whitespace to wildcards (*). The + * following code: + * + *
+ * WhitespaceWildcardsFilter filter = new WhitespaceWildcardsFilter("cn",
+ *         "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: (cn=*Some*CN*) + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class WhitespaceWildcardsFilter extends EqualsFilter { + private static Pattern starReplacePattern = Pattern.compile("\\s+"); + + public WhitespaceWildcardsFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Encodes a value according to the rules for this filter. + * + * @param value + * Value to encode. + * @return Encoded value. + */ + protected String encodeValue(String value) { + + // blank string means just ONE star + if (StringUtils.isBlank(value)) { + return "*"; + } + + // trim value, we will add in stars first and last anywhay + value = value.trim(); + + // filter encode so that any stars etc. are preserved + String filterEncoded = LdapEncoder.filterEncode(value); + + // Now replace all whitespace with stars + Matcher m = starReplacePattern.matcher(filterEncoded); + + // possibly 2 longer (stars at ends) + StringBuffer buff = new StringBuffer(value.length() + 2); + + buff.append('*'); + + while (m.find()) { + m.appendReplacement(buff, "*"); + } + m.appendTail(buff); + + buff.append('*'); + + return buff.toString(); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/package.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/package.html new file mode 100644 index 00000000..e05a77ed --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/filter/package.html @@ -0,0 +1,16 @@ + +Utility classes for dynamically building LDAP +filters. Filters can be nested and wrapped around each other: +
+AndFilter andFilter = new AndFilter();
+andFilter.and(new EqualsFilter("objectclass", "person");
+andFilter.and(new EqualsFilter("cn", "Some CN");
+OrFilter orFilter = new OrFilter();
+orFilter.or(andFilter);
+orFilter.or(new EqualsFilter("objectclass", "organizationalUnit));
+System.out.println(orFilter.encode());
+
+would result in: + +
(|(&(objectclass=person)(cn=Some CN))(objectclass=organizationalUnit))
+ diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/package.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/package.html new file mode 100644 index 00000000..bf83afd5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/support/package.html @@ -0,0 +1,3 @@ + +Support classes for Spring-LDAP. + \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/ListComparator.java b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/ListComparator.java new file mode 100644 index 00000000..0ea9857c --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/ListComparator.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.util; + +import java.util.Comparator; +import java.util.List; + +/** + * Comparator for comparing lists of Comparable objects. + * + * @author Mattias Arthursson + * + */ +public class ListComparator implements Comparator { + + /** + * Compare two lists of Comparable objects. + * + * @param o1 + * the first object to be compared. + * @param o2 + * the second object to be compared. + * @throws ClassCastException + * if either of the lists contains an object that is not + * Comparable. + */ + public int compare(Object o1, Object o2) { + List list1 = (List) o1; + List list2 = (List) o2; + + for (int i = 0; i < list1.size(); i++) { + if (list2.size() > i) { + Comparable component1 = (Comparable) list1.get(i); + Comparable component2 = (Comparable) list2.get(i); + int componentsCompared = component1.compareTo(component2); + if (componentsCompared != 0) { + return componentsCompared; + } + } else { + // First instance has more components, so that instance is + // greater. + return 1; + } + } + + // All components so far are equal - if the other instance has + // more components it is greater otherwise they are equal. + if (list2.size() > list1.size()) { + return -1; + } else { + return 0; + } + } +} diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/package.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/package.html new file mode 100644 index 00000000..b01effef --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/org/springframework/ldap/util/package.html @@ -0,0 +1,3 @@ + +Internal utility classes. + diff --git a/build-spring-ldap/spring-ldap-1.1.1/src/main/java/overview.html b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/overview.html new file mode 100644 index 00000000..fe97647c --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1.1/src/main/java/overview.html @@ -0,0 +1,3 @@ + +This document is the API specification for the Spring LDAP Framework. + \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java new file mode 100644 index 00000000..10089337 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataIntegrityViolationException; + +/** + * Exception that indicates that an invalid or missing Attribute has been + * supplied to an LDAP operation. + * + * @author Mattias Arthursson + * + */ +public class AttributesIntegrityViolationException extends + DataIntegrityViolationException { + + private static final long serialVersionUID = -6368616096960202571L; + + public AttributesIntegrityViolationException(String msg) { + super(msg); + } + + public AttributesIntegrityViolationException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesMapper.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesMapper.java new file mode 100644 index 00000000..bc6af080 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AttributesMapper.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +/** + * An interface used by LdapTemplate for mapping LDAP Attributes to beans. + * Implementions of this interface perform the actual work of extracting + * results, but need not worry about exception handling. NamingExceptions will + * be caught and handled correctly by the LdapTemplate class. + *

+ * Typically used in LdapTemplate's search methods. AttributeMapper objects are + * typically stateless and thus reusable; they are ideal for implementing + * attribute-mapping logic in one place. + *

+ * Alternatively, consider using a {@link ContextMapper} in stead. + * + * @see org.springframework.ldap.LdapTemplate#search(Name, String, + * AttributesMapper) + * @see ContextMapper + * + * @author Mattias Arthursson + */ +public interface AttributesMapper { + /** + * Map Attributes to an object. The supplied attributes are the attributes + * from a single SearchResult. + * + * @param attributes + * attributes from a SearchResult. + * @return an object built from the attributes. + * @throws NamingException if any error occurs mapping the attributes + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java new file mode 100644 index 00000000..7a8874c1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/AuthenticationSource.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * An AuthenticationSource is responsible for providing the principal and + * credentials to be used when creating a new context. + * + * @author Mattias Arthursson + * + */ +public interface AuthenticationSource { + /** + * Get the principal to use when creating an authenticated context. + * + * @return the principal (userName). + */ + public String getPrincipal(); + + /** + * Get the credentials to use when creating an authenticated context. + * + * @return the credentials (userName). + */ + public String getCredentials(); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java new file mode 100644 index 00000000..a7d55dbd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/BadLdapGrammarException.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.InvalidDataAccessResourceUsageException; + +/** + * Thrown to indicate that an invalid value has been supplied to an LDAP + * operation. This could be an invalid filter or dn. + * + * @author Mattias Arthursson + */ +public class BadLdapGrammarException extends + InvalidDataAccessResourceUsageException { + + private static final long serialVersionUID = 961612585331409470L; + + public BadLdapGrammarException(String message) { + super(message); + } + + public BadLdapGrammarException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java new file mode 100644 index 00000000..6f42103d --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.LinkedList; +import java.util.List; + +import javax.naming.NameClassPair; + +/** + * A NameClassPairCallbackHandler to collect all results in an internal List. + * + * @see org.springframework.ldap.LdapTemplate + * + * @author Mattias Arthursson + */ +public abstract class CollectingNameClassPairCallbackHandler implements + NameClassPairCallbackHandler { + + private List list = new LinkedList(); + + /** + * Get the assembled list. + * + * @return the list of all assembled objects. + */ + public List getList() { + return list; + } + + /** + * Pass on the supplied NameClassPair to + * {@link #getObjectFromNameClassPair(NameClassPair)} and add the result to + * the internal list. + */ + public void handleNameClassPair(NameClassPair nameClassPair) { + list.add(getObjectFromNameClassPair(nameClassPair)); + } + + /** + * Handle a NameClassPair and transform it to an Object of the desired type + * and with data from the NameClassPair. + * + * @param nameClassPair + * a NameClassPair from a search operation. + * @return an object constructed from the data in the NameClassPair. + */ + public abstract Object getObjectFromNameClassPair( + NameClassPair nameClassPair); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextAssembler.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextAssembler.java new file mode 100644 index 00000000..da2ef350 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextAssembler.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * Helper interface to be used by Dao implementations for assembling to and from + * context. Useful if we have assembler classes responsible for mapping to and + * from a specific entry. + * + * @author Mattias Arthursson + */ +public interface ContextAssembler extends ContextMapper { + /** + * Map the supplied object to the specified context. + * + * @param obj + * the object to read data from. + * @param ctx + * the context to map to. + */ + public void mapToContext(Object obj, Object ctx); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextExecutor.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextExecutor.java new file mode 100644 index 00000000..70ac8790 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextExecutor.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface for delegating an actual operation to be performed on an + * DirContext. For searches, use {@link org.springframework.ldap.SearchExecutor} in + * stead. A typical usage of this interface could be e.g.: + * + *

+ * ContextExecutor executor = new ContextExecutor(){
+ *   public Object executeWithContext(DirContext ctx) throws NamingException{
+ *     return ctx.lookup(dn);
+ *   }
+ * };
+ * 
+ * + * @see org.springframework.ldap.LdapTemplate#executeReadOnly(ContextExecutor) + * @see org.springframework.ldap.LdapTemplate#executeReadWrite(ContextExecutor) + * + * @author Mattias Arthursson + */ +public interface ContextExecutor { + /** + * Perform any operation on the context. + * + * @param ctx + * the DirContext to perform the operation on. + * @return any object resulting from the operation - might be null. + * @throws NamingException + * if the operation resulted in one. + */ + public Object executeWithContext(DirContext ctx) throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextMapper.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextMapper.java new file mode 100644 index 00000000..a9effe00 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextMapper.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.directory.SearchResult; + +import org.springframework.ldap.support.DefaultDirObjectFactory; +import org.springframework.ldap.support.DirContextAdapter; + +/** + * An interface used by LdapTemplate to map LDAP Contexts to beans. Responsible + * for mapping from LDAP Contexts to beans. When a DirObjectFactory is set on + * the ContextSource, the objects returned from search and + * listBindings operations are automatically transformed to + * DirContext objects (when using the {@link DefaultDirObjectFactory}, you get + * a {@link DirContextAdapter} object). This object will then be passed to the + * ContextMapper implementation for transformation to the desired bean. + *

+ * ContextMapper implementations are typically stateless and thus reusable; they + * are ideal for implementing mapping logic in one place. + *

+ * Alternatively, consider using an {@link AttributesMapper} in stead. + * + * @see LdapTemplate#search(Name, String, + * ContextMapper) + * @see LdapTemplate#listBindings(Name, ContextMapper) + * @see LdapTemplate#lookup(Name, ContextMapper) + * @see AttributesMapper + * @see DefaultDirObjectFactory + * @see DirContextAdapter + * + * @author Mattias Arthursson + */ +public interface ContextMapper { + /** + * Map a single LDAP Context to an object. The supplied Object + * ctx is the object from a single {@link SearchResult}, + * {@link Binding}, or a lookup operation. + * + * @param ctx + * the context to map to an object. + * @return an object built from the data in the context. + */ + public Object mapFromContext(Object ctx); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextSource.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextSource.java new file mode 100644 index 00000000..fa104841 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/ContextSource.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.directory.DirContext; + +import org.springframework.dao.DataAccessException; + +/** + * Interface used to retrieve and authenticate LDAP contexts. + * + * @see org.springframework.ldap.LdapTemplate + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public interface ContextSource { + + /** + * Gets a read-only DirContext. The returned DirContext must be possible to + * perform read-only operations on. + * + * @return A DirContext instance, never null. + * @throws DataAccessException + * if some error occurs creating an DirContext. + */ + public DirContext getReadOnlyContext() throws DataAccessException; + + /** + * Gets a read-write DirContext. + * + * @return A DirContext instance, never null. + * @throws DataAccessException + * if some error occurs creating an DirContext. + */ + public DirContext getReadWriteContext() throws DataAccessException; +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java new file mode 100644 index 00000000..a7eba9e5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; +import javax.naming.NamingException; + +/** + * The default NameClassPairMapper implementation. This implementation simply + * takes the Name string from the supplied NameClassPair and returns it as + * result. + * + * @author Mattias Arthursson + * + */ +public class DefaultNameClassPairMapper implements NameClassPairMapper { + + /** + * Gets the Name from the supplied NameClassPair and returns it as the + * result. + * + * @param nameClassPair + * the NameClassPair to transform. + * @return the Name string from the NameClassPair. + */ + public Object mapFromNameClassPair(NameClassPair nameClassPair) + throws NamingException { + + return nameClassPair.getName(); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java new file mode 100644 index 00000000..6c27b5c7 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java @@ -0,0 +1,96 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.CommunicationException; +import javax.naming.ContextNotEmptyException; +import javax.naming.LimitExceededException; +import javax.naming.NameAlreadyBoundException; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import javax.naming.directory.InvalidAttributesException; +import javax.naming.directory.InvalidSearchControlsException; +import javax.naming.directory.InvalidSearchFilterException; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * The default implementation of NamingExceptionTranslator. + * + * @author Mattias Arthursson + */ +public class DefaultNamingExceptionTranslator implements + NamingExceptionTranslator { + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.NamingExceptionTranslator#translate(java.lang.String, + * java.lang.String, java.lang.String, javax.naming.NamingException) + */ + public DataAccessException translate(NamingException namingException) { + + if (namingException instanceof NameNotFoundException) { + return new EntryNotFoundException("Entry not found", + namingException); + } + + if (namingException instanceof InvalidSearchFilterException) { + return new BadLdapGrammarException("Invalid search filter", + namingException); + } + + if (namingException instanceof InvalidSearchControlsException) { + return new InvalidDataAccessApiUsageException( + "Invalid search controls supplied by internal API", + namingException); + } + + if (namingException instanceof NameAlreadyBoundException) { + return new DataIntegrityViolationException("Name already bound", + namingException); + } + + if (namingException instanceof ContextNotEmptyException) { + return new DataIntegrityViolationException( + "The context needs to be empty in order to be removed", + namingException); + } + + if (namingException instanceof InvalidAttributesException) { + return new AttributesIntegrityViolationException( + "Invalid attributes", namingException); + } + + if (namingException instanceof LimitExceededException) { + return new SearchLimitExceededException("Too many objects found", + namingException); + } + + if (namingException instanceof CommunicationException) { + throw new DataRetrievalFailureException( + "Unable to communicate with LDAP server", namingException); + } + + // Fallback - other type of NamingException encountered. + return new UncategorizedLdapException("Operation failed", + namingException); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java new file mode 100644 index 00000000..9bd81eb9 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/EntryNotFoundException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataRetrievalFailureException; + +/** + * Represents that an entry could not be found. + * + * @author Mattias Arthursson + */ +public class EntryNotFoundException extends DataRetrievalFailureException { + + private static final long serialVersionUID = -1268390922996332424L; + + public EntryNotFoundException(String msg) { + super(msg); + } + + public EntryNotFoundException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapOperations.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapOperations.java new file mode 100644 index 00000000..80653fb8 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapOperations.java @@ -0,0 +1,1104 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.directory.Attributes; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; + +/** + * Interface that specifies a basic set of LDAP operations. Implemented by + * LdapTemplate, but it might be a useful option to use this interface in order + * to enhance testability. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface LdapOperations { + /** + * Perform a search. Use this method only if especially needed - for the + * most cases there is an overloaded convenience method which calls this one + * with suitable argments. This method handles all the plumbing; getting a + * readonly context; looping through the NamingEnumeration and closing the + * context and enumeration. The actual search is delegated to the + * SearchExecutor and each found SearchResult is passed to the + * CallbackHandler. Any encountered NamingException will be translated using + * the NamingExceptionTranslator. + * + * @param se + * The SearchExecutor to use for performing the actual search. + * @param handler + * The NameClassPairCallbackHandler to which each found entry + * will be passed. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted as no entries being + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform an operation (or series of operations) on a read-only context. + * This method handles the plumbing - getting a DirContext, translating any + * Exceptions and closing the context afterwards. This method is not + * intended for searches; use + * {@link #search(SearchExecutor, NameClassPairCallbackHandler)} or any of + * the overloaded search methods for this. + * + * @param ce + * The ContextExecutor to which the actual operation on the + * DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws DataAccessException + * if the operation resulted in a NamingException. + */ + public Object executeReadOnly(ContextExecutor ce) + throws DataAccessException; + + /** + * Perform an operation (or series of operations) on a read-write context. + * This method handles the plumbing - getting a DirContext, translating any + * exceptions and closing the context afterwards. + * + * @param ce + * The ContextExecutor to which the actual operation on the + * DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws DataAccessException + * if the operation resulted in a NamingException. + */ + public Object executeReadWrite(ContextExecutor ce) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the search. Note + * that if you are using a ContextMapper, the returningObjFlag needs to be + * set to true in the SearchControls. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + */ + public void search(Name base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler); + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler)} + * for details. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + */ + public void search(String base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler); + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. Use the specified + * values for search scope and return objects flag. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param returningObjFlag + * Whether the bound object should be returned in search results. + * Must be set to true if a ContextMapper is used. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(Name base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. Use the specified + * search scope and return objects flag in search controls. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param returningObjFlag + * whether the bound object should be returned in search results. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(String base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The default + * Search scope (SearchControls.SUBTREE_SCOPE) will be used and the + * returnObjects flag will be set to false. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(Name base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The default + * Search scope (SearchControls.SUBTREE_SCOPE) will be used and no the + * returnObjects will be set to false. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(String base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Only search for the + * specified attributes. The Attributes in each SearchResult is supplied to + * the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means returning all attributes. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Only search for the + * specified attributes. The Attributes in each SearchResult is supplied to + * the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means returning all attributes. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * default seach scope will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, AttributesMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * default seach scope will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, AttributesMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. Only + * look for the supplied attributes. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means all attributes. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. Only + * look for the supplied attributes. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means all attributes. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * default search scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, ContextMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * default search scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, ContextMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link NameClassPair} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void list(String base, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link NameClassPair} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void list(Name base, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects to the + * supplied NameClassPairMapper and return all the returned values as a + * List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link NameClassPair} + * to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(String base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects to the + * supplied NameClassPairMapper and return all the returned values as a + * List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link NameClassPair} + * to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(Name base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(String base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the contexts bound to the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(Name base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the specified + * NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link Binding} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void listBindings(final String base, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the specified + * NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link Binding} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void listBindings(final Name base, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the supplied + * NameClassPairMapper and return all the returned values as a List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link Binding} to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(String base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the supplied + * NameClassPairMapper and return all the returned values as a List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link Binding} to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(Name base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(final String base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(final Name base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(String base, ContextMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(Name base, ContextMapper mapper) + throws DataAccessException; + + /** + * Lookup the supplied DN and return the found object. WARNING: This + * method should only be used if a DirObjectFactory has been specified on + * the ContextFactory. If this is not the case, you will get a new instance + * of the actual DirContext, which is probably not what you want. If, + * however this is what you want, be careful to close the context + * after you finished working with it. + * + * @param dn + * The distinguished name of the object to find. + * @return the found object. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn) throws DataAccessException; + + /** + * Lookup the supplied DN and return the found object. WARNING: This + * method should only be used if a DirObjectFactory has been specified on + * the ContextFactory. If this is not the case, you will get a new instance + * of the actual DirContext, which is probably not what you want. If, + * however this is what you want, be careful to close the context + * after you finished working with it. + * + * @param dn + * The distinguished name of the object to find. + * @return the found object. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn) throws DataAccessException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, ContextMapper mapper) + throws DataAccessException; + + /** + * Modify an entry in the LDAP tree using the supplied ModificationItems. + * + * @param dn + * The distinguished name of the node to modify. + * @param mods + * The modifications to perform. + * @throws DataAccessException + * if any error occurs. + */ + public void modifyAttributes(Name dn, ModificationItem[] mods) + throws DataAccessException; + + /** + * Modify an entry in the LDAP tree using the supplied ModificationItems. + * + * @param dn + * The distinguished name of the node to modify. + * @param mods + * The modifications to perform. + * @throws DataAccessException + * if any error occurs. + */ + public void modifyAttributes(String dn, ModificationItem[] mods) + throws DataAccessException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters + * may be null but not both. + * + * @param dn + * The distinguished name to bind the object and attributes to. + * @param obj + * The object to bind, may be null. Typically a DirContext + * implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void bind(Name dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters + * may be null but not both. + * + * @param dn + * The distinguished name to bind the object and attributes to. + * @param obj + * The object to bind, may be null. Typically a DirContext + * implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void bind(String dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children - + * if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn + * The distinguished name of the entry to remove. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(Name dn) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children - + * if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn + * The distinguished name to unbind. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(String dn) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn + * The distinguished name to unbind. + * @param recursive + * Whether to unbind all subcontexts as well. If this parameter + * is false and the entry has children, the + * operation will fail. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(Name dn, boolean recursive) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn + * The distinguished name to unbind. + * @param recursive + * Whether to unbind all subcontexts as well. If this parameter + * is false and the entry has children, the + * operation will fail. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(String dn, boolean recursive) throws DataAccessException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj + * parameter or the attributes parameter (or both). One of + * these parameters may be null but not both. This method assumes that the + * specified context already exists - if not it will fail. + * + * @param dn + * The distinguished name to rebind. + * @param obj + * The object to bind to the DN, may be null. Typically a + * DirContext implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void rebind(Name dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj + * parameter or the attributes parameter (or both). One of + * these parameters may be null but not both. This method assumes that the + * specified context already exists - if not it will fail. + * + * @param dn + * The distinguished name to rebind. + * @param obj + * The object to bind to the DN, may be null. Typically a + * DirContext implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void rebind(String dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn + * The distinguished name of the entry to move; may not be null + * or empty. + * @param newDn + * The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws DataIntegrityViolationException + * if newDn is already bound + * @throws DataAccessException + * if any other error occurs. + */ + public void rename(final Name oldDn, final Name newDn) + throws DataAccessException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn + * The distinguished name of the entry to move; may not be null + * or empty. + * @param newDn + * The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws DataIntegrityViolationException + * if newDn is already bound + * @throws DataAccessException + * if any other error occurs. + */ + public void rename(final String oldDn, final String newDn) + throws DataAccessException; +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapTemplate.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapTemplate.java new file mode 100644 index 00000000..d423f6a4 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/LdapTemplate.java @@ -0,0 +1,1176 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.PartialResultException; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import org.apache.commons.lang.Validate; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Executes core LDAP functionality and helps to avoid common errors, relieving + * the user of the burden of looking up contexts, looping through + * NamingEnumerations and closing contexts. + *

+ * Note for Active Directory (AD) users: AD servers are apparently + * unable to handle referrals automatically, which causes a + * PartialResultException to be thrown whenever a referral is + * encountered in a search. To avoid this, set the + * ignorePartialResultException property to true. + * There is currently no way of manually handling these referrals in the form of + * ReferralException, i.e. either you get the exception (and + * your results are lost) or all referrals are ignored (if the server is unable + * to handle them properly. Neither is there any simple way to get notified that + * a PartialResultException has been ignored (other than in the + * log). + * + * @see org.springframework.ldap.ContextSource + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplate implements LdapOperations, InitializingBean { + + private static final Log log = LogFactory.getLog(LdapTemplate.class); + + private static final int DEFAULT_SEARCH_SCOPE = SearchControls.SUBTREE_SCOPE; + + private static final boolean DONT_RETURN_OBJ_FLAG = false; + + private static final boolean RETURN_OBJ_FLAG = true; + + private static final String[] ALL_ATTRIBUTES = null; + + private ContextSource contextSource; + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + private boolean ignorePartialResultException = false; + + /** + * Constructor for bean usage. + */ + public LdapTemplate() { + } + + /** + * Constructor to setup instance directly. + * + * @param contextSource + * the ContextSource to use. + */ + public LdapTemplate(ContextSource contextSource) { + this.contextSource = contextSource; + } + + /** + * Set the ContextSource. Call this method when the default constructor has + * been used. + * + * @param contextSource + * the ContextSource. + */ + public void setContextSource(ContextSource contextSource) { + this.contextSource = contextSource; + } + + /** + * Specify whether PartialResultException should be ignored + * in searches. AD servers typically have a problem with referrals. Normally + * a referral should be followed automatically, but this does not seem to + * work with AD servers. The problem manifests itself with a a + * PartialResultException being thrown when a referral is + * encountered by the server. Setting this property to true + * presents a workaround to this problem by causing + * PartialResultException to be ignored, so that the search + * method returns normally. Default value of this parameter is + * false. + * + * @param ignore + * true if PartialResultException + * should be ignored in searches, false otherwise. + * Default is false. + */ + public void setIgnorePartialResultException(boolean ignore) { + this.ignorePartialResultException = ignore; + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, boolean, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(Name base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) { + + search(base, filter, getDefaultSearchControls(searchScope, + returningObjFlag, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, boolean, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(String base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException { + + search(base, filter, getDefaultSearchControls(searchScope, + returningObjFlag, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(final Name base, final String filter, + final SearchControls controls, NameClassPairCallbackHandler handler) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(final String base, final String filter, + final SearchControls controls, NameClassPairCallbackHandler handler) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler); + } + + /** + * Perform a search operation, such as a search(), list() or listBindings(). + * This method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. + * The actual list is delegated to the {@link SearchExecutor} and each + * {@link NameClassPair} (this might be a NameClassPair or a subclass + * thereof) is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * the SearchExecutor to use for performing the actual list. + * @param handler + * the NameClassPairCallbackHandler to which each found entry + * will be passed. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler) { + DirContext ctx = contextSource.getReadOnlyContext(); + + NamingEnumeration results = null; + try { + results = se.executeSearch(ctx); + + while (results.hasMore()) { + NameClassPair result = (NameClassPair) results.next(); + handler.handleNameClassPair(result); + } + } catch (NameNotFoundException e) { + // The base context was not found, which basically means + // that the search did not return any results. Just clean up and + // exit. + } catch (PartialResultException e) { + // Workaround for AD servers not handling referrals correctly. + if (ignorePartialResultException) { + log.debug("PartialResultException encountered and ignored", e); + } else { + throw getExceptionTranslator().translate(e); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeContextAndNamingEnumeration(ctx, results); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(Name base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException { + + search(base, filter, getDefaultSearchControls(DEFAULT_SEARCH_SCOPE, + DONT_RETURN_OBJ_FLAG, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(String base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException { + + search(base, filter, getDefaultSearchControls(DEFAULT_SEARCH_SCOPE, + DONT_RETURN_OBJ_FLAG, ALL_ATTRIBUTES), handler); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException { + return search(base, filter, getDefaultSearchControls(searchScope, + DONT_RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException { + return search(base, filter, getDefaultSearchControls(searchScope, + DONT_RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, int searchScope, + AttributesMapper mapper) { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, AttributesMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, AttributesMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException { + + return search(base, filter, getDefaultSearchControls(searchScope, + RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException { + + return search(base, filter, getDefaultSearchControls(searchScope, + RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, int searchScope, + ContextMapper mapper) { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, ContextMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, ContextMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper) { + + assureReturnObjFlagSet(controls); + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + search(base, filter, controls, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper) { + + assureReturnObjFlagSet(controls); + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + search(base, filter, controls, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper) { + + AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler( + mapper); + search(base, filter, controls, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper) { + + AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler( + mapper); + search(base, filter, controls, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String, + * org.springframework.ldap.ListResultCallbackHandler) + */ + public void list(final String base, NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.list(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name, + * org.springframework.ldap.ListResultCallbackHandler) + */ + public void list(final Name base, NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.list(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#list(java.lang.String, + * org.springframework.ldap.NameClassPairMapper) + */ + public List list(String base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + list(base, handler); + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name, + * org.springframework.ldap.NameClassPairMapper) + */ + public List list(Name base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + list(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name) + */ + public List list(final Name base) { + return list(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String) + */ + public List list(final String base) { + return list(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void listBindings(final String base, + NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.listBindings(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void listBindings(final Name base, + NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.listBindings(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.NameClassPairMapper) + */ + public List listBindings(String base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + listBindings(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.NameClassPairMapper) + */ + public List listBindings(Name base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + listBindings(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String) + */ + public List listBindings(final String base) { + return listBindings(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name) + */ + public List listBindings(final Name base) { + return listBindings(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.ContextMapper) + */ + public List listBindings(String base, ContextMapper mapper) { + + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + listBindings(base, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.ContextMapper) + */ + public List listBindings(Name base, ContextMapper mapper) { + + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + listBindings(base, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#executeReadOnly(org.springframework.ldap.ContextExecutor) + */ + public Object executeReadOnly(ContextExecutor ce) { + DirContext ctx = contextSource.getReadOnlyContext(); + return executeWithContext(ce, ctx); + } + + /* + * @see org.springframework.ldap.LdapOperations#executeReadWrite(org.springframework.ldap.ContextExecutor) + */ + public Object executeReadWrite(ContextExecutor ce) { + DirContext ctx = contextSource.getReadWriteContext(); + return executeWithContext(ce, ctx); + } + + private Object executeWithContext(ContextExecutor ce, DirContext ctx) { + try { + return ce.executeWithContext(ctx); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeContext(ctx); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name) + */ + public Object lookup(final Name dn) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return ctx.lookup(dn); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String) + */ + public Object lookup(final String dn) throws DataAccessException { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return ctx.lookup(dn); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final Name dn, final AttributesMapper mapper) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes attributes = ctx.getAttributes(dn); + return mapper.mapFromAttributes(attributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final String dn, final AttributesMapper mapper) + throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes attributes = ctx.getAttributes(dn); + return mapper.mapFromAttributes(attributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * org.springframework.ldap.ContextMapper) + */ + public Object lookup(final Name dn, final ContextMapper mapper) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Object object = ctx.lookup(dn); + return mapper.mapFromContext(object); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * org.springframework.ldap.ContextMapper) + */ + public Object lookup(final String dn, final ContextMapper mapper) + throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Object object = ctx.lookup(dn); + return mapper.mapFromContext(object); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#modifyAttributes(javax.naming.Name, + * javax.naming.directory.ModificationItem[]) + */ + public void modifyAttributes(final Name dn, final ModificationItem[] mods) { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.modifyAttributes(dn, mods); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#modifyAttributes(java.lang.String, + * javax.naming.directory.ModificationItem[]) + */ + public void modifyAttributes(final String dn, final ModificationItem[] mods) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.modifyAttributes(dn, mods); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#bind(javax.naming.Name, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void bind(final Name dn, final Object obj, + final Attributes attributes) { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.bind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#bind(java.lang.String, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void bind(final String dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.bind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(javax.naming.Name) + */ + public void unbind(final Name dn) { + doUnbind(dn); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(java.lang.String) + */ + public void unbind(final String dn) throws DataAccessException { + doUnbind(dn); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(javax.naming.Name, + * boolean) + */ + public void unbind(final Name dn, boolean recursive) + throws DataAccessException { + if (!recursive) { + doUnbind(dn); + } else { + doUnbindRecursively(dn); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(java.lang.String, + * boolean) + */ + public void unbind(final String dn, boolean recursive) + throws DataAccessException { + if (!recursive) { + doUnbind(dn); + } else { + doUnbindRecursively(dn); + } + } + + private void doUnbind(final Name dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.unbind(dn); + return null; + } + }); + } + + private void doUnbind(final String dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.unbind(dn); + return null; + } + }); + } + + private void doUnbindRecursively(final Name dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + deleteRecursively(ctx, new DistinguishedName(dn)); + return null; + } + }); + } + + private void doUnbindRecursively(final String dn) + throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + deleteRecursively(ctx, new DistinguishedName(dn)); + return null; + } + }); + } + + /** + * Delete all subcontexts including the current one recursively. + * + * @param ctx + * The context to use for deleting. + * @param name + * The starting point to delete recursively. + * @throws DataAccessException + * if any error occurs + */ + protected void deleteRecursively(DirContext ctx, DistinguishedName name) + throws DataAccessException { + + NamingEnumeration enumeration = null; + try { + enumeration = ctx.listBindings(name); + while (enumeration.hasMore()) { + Binding binding = (Binding) enumeration.next(); + DistinguishedName childName = new DistinguishedName(binding + .getName()); + childName.prepend((DistinguishedName) name); + deleteRecursively(ctx, childName); + } + ctx.unbind(name); + if (log.isDebugEnabled()) { + log.debug("Entry " + name + " deleted"); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + try { + enumeration.close(); + } catch (Exception e) { + // Never mind this + } + } + } + + /* + * @see org.springframework.ldap.LdapOperations#rebind(javax.naming.Name, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void rebind(final Name dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rebind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rebind(java.lang.String, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void rebind(final String dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rebind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rename(javax.naming.Name, + * javax.naming.Name) + */ + public void rename(final Name oldDn, final Name newDn) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rename(oldDn, newDn); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rename(java.lang.String, + * java.lang.String) + */ + public void rename(final String oldDn, final String newDn) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rename(oldDn, newDn); + return null; + } + }); + } + + /* + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + if (contextSource == null) { + throw new IllegalArgumentException( + "Property 'contextSource' must be set."); + } + } + + private void closeContextAndNamingEnumeration(DirContext ctx, + NamingEnumeration results) { + + closeNamingEnumeration(results); + closeContext(ctx); + } + + /** + * Close the supplied DirContext if it is not null. Swallow any exceptions, + * as this is only for cleanup. + * + * @param ctx + * the context to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + + /** + * Close the supplied NamingEnumeration if it is not null. Swallow any + * exceptions, as this is only for cleanup. + * + * @param results + * the NamingEnumeration to close. + */ + private void closeNamingEnumeration(NamingEnumeration results) { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + + /** + * Get the NamingExceptionTranslator that will be used by this instance. If + * no exceptionTranslator has been set, a default instance will be created. + * + * @return the NamingExceptionTranslator to be used by this instance. + */ + public NamingExceptionTranslator getExceptionTranslator() { + return exceptionTranslator; + } + + /** + * Set the NamingExceptionTranslator to be used by this instance. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + + this.exceptionTranslator = exceptionTranslator; + } + + private SearchControls getDefaultSearchControls(int searchScope, + boolean returningObjFlag, String[] attrs) { + + SearchControls controls = new SearchControls(); + controls.setSearchScope(searchScope); + controls.setReturningObjFlag(returningObjFlag); + controls.setReturningAttributes(attrs); + return controls; + } + + /** + * Make sure the returnObjFlag is set in the supplied SearchControls. Set it + * and log if it's not set. + * + * @param controls + * the SearchControls to check. + */ + private void assureReturnObjFlagSet(SearchControls controls) { + Validate.notNull(controls); + if (!controls.getReturningObjFlag()) { + log.info("The returnObjFlag of supplied SearchControls is not set" + + " but a ContextMapper is used - setting flag to true"); + controls.setReturningObjFlag(true); + } + } + + /** + * A {@link NameClassPairCallbackHandler} that passes the NameClassPairs + * found to a NameClassPairMapper and collects the results in a list. + * + * @author Mattias Arthursson + */ + public class MappingCollectingNameClassPairCallbackHandler extends + CollectingNameClassPairCallbackHandler { + + private NameClassPairMapper mapper; + + public MappingCollectingNameClassPairCallbackHandler( + NameClassPairMapper mapper) { + this.mapper = mapper; + } + + /* + * @see org.springframework.ldap.CollectingNameClassPairCallbackHandler#getObjectFromNameClassPair(javax.naming.NameClassPair) + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + try { + return mapper.mapFromNameClassPair(nameClassPair); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } + + /** + * A CollectingNameClassPairCallbackHandler to wrap an AttributesMapper. + * That is, the found object is extracted from the {@link Attributes} of + * each {@link SearchResult}, and then passed to the specified + * AttributesMapper for translation. This class needs to be nested, since we + * want to be able to get hold of the exception translator of this instance. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + public class AttributesMapperCallbackHandler extends + CollectingNameClassPairCallbackHandler { + private AttributesMapper mapper; + + public AttributesMapperCallbackHandler(AttributesMapper mapper) { + this.mapper = mapper; + } + + /** + * Cast the NameClassPair to a SearchResult and pass its attributes to + * the AttributesMapper. + * + * @param nameClassPair + * a SearchResult instance. + * @return the Object returned from the Mapper. + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + SearchResult searchResult = (SearchResult) nameClassPair; + Attributes attributes = searchResult.getAttributes(); + try { + return mapper.mapFromAttributes(attributes); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } + + /** + * A CollectingNameClassPairCallbackHandler to wrap a ContextMapper. That + * is, the found object is extracted from each {@link Binding}, and then + * passed to the specified ContextMapper for translation. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + public class ContextMapperCallbackHandler extends + CollectingNameClassPairCallbackHandler { + private ContextMapper mapper; + + public ContextMapperCallbackHandler(ContextMapper mapper) { + this.mapper = mapper; + } + + /** + * Cast the NameClassPair to a {@link Binding} and pass its attributes + * to the ContextMapper. + * + * @param nameClassPair + * a SearchResult instance. + * @return the Object returned from the Mapper. + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + Binding binding = (Binding) nameClassPair; + Object object = binding.getObject(); + if (object == null) { + throw new EntryNotFoundException( + "SearchResult did not contain any object."); + } + return mapper.mapFromContext(object); + } + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java new file mode 100644 index 00000000..0698a9c6 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; + +/** + * Callback interface used by LdapTemplate's search, list and listBindings + * methods. Implementations of this interface perform the actual work of + * extracting results from a single NameClassPair (a NameClassPair, + * Binding or SearchResult depending on the search operation) returned by an + * LDAP seach operation, such as search(), list(), and listBindings(). + * + * @author Mattias Arthursson + */ +public interface NameClassPairCallbackHandler { + /** + * Handle one entry. This method will be called once for each entry returned + * by a search or list. + * + * @param nameClassPair + * the NameClassPair returned from the NamingEnumeration. + */ + public void handleNameClassPair(NameClassPair nameClassPair); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java new file mode 100644 index 00000000..acf8cd14 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NameClassPairMapper.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; +import javax.naming.NamingException; + +/** + * Responsible for mapping NameClassPair objects to beans. + * + * @author Mattias Arthursson + */ +public interface NameClassPairMapper { + /** + * Map NameClassPair to an Object. The supplied NameClassPair is one of the + * results from a search operation (search, list or listBindings). Depending + * on which search operation is being performed, the NameClassPair might be + * a SearchResult, Binding or NameClassPair. + * + * @param nameClassPair + * NameClassPair from a search operation. + * @return and Object built from the NameClassPair. + * @throws NamingException + * if one is encountered in the operation. + */ + public Object mapFromNameClassPair(NameClassPair nameClassPair) + throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java new file mode 100644 index 00000000..cd6e7a4c --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; + +import org.springframework.dao.DataAccessException; + +/** + * Interface to be implemented by classes that can translate between + * NamingExceptions and DataAccessExceptions. + * + * @author Mattias Arthursson + * + */ +public interface NamingExceptionTranslator { + /** + * Translate the given NamingException into a generic data access exception. + * @param namingException + * the offending NamingException. + * + * @return the DataAccessException to throw. + */ + public DataAccessException translate(NamingException namingException); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchExecutor.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchExecutor.java new file mode 100644 index 00000000..34b474b5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchExecutor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface for delegating an actual search operation. The typical + * implementation of executeSearch would be something like: + * + *

+ * SearchExecutor executor = new SearchExecutor(){
+ *   public NamingEnumeration executeSearch(DirContext ctx) throws NamingException{
+ *     return ctx.search(dn, filter, searchControls);
+ *   }
+ * }
+ * 
+ * + * @see org.springframework.ldap.LdapTemplate#search(SearchExecutor, + * NameClassPairCallbackHandler) + * + * @author Mattias Arthursson + */ +public interface SearchExecutor { + /** + * Execute the actual search. + * + * @param ctx + * the DirContext on which to work. + * @return the NamingEnumeration resulting from the search operation. + * @throws NamingException + * if the search results in one. + */ + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException; +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java new file mode 100644 index 00000000..49806334 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/SearchLimitExceededException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataRetrievalFailureException; + +/** + * Indicates that the search limit was exceeded in a search. + * + * @author Mattias Arthursson + * + */ +public class SearchLimitExceededException extends DataRetrievalFailureException { + private static final long serialVersionUID = 6899885947075235580L; + + public SearchLimitExceededException(String msg) { + super(msg); + } + + public SearchLimitExceededException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java new file mode 100644 index 00000000..2423a3b7 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/UncategorizedLdapException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.UncategorizedDataAccessException; + +/** + * Indicates that an unknown NamingException has occurred. + * + * @author Mattias Arthursson + */ +public class UncategorizedLdapException extends + UncategorizedDataAccessException { + + private static final long serialVersionUID = -3319936235493869823L; + + public UncategorizedLdapException(String msg, Throwable cause) { + super(msg, cause); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/package.html b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/package.html new file mode 100644 index 00000000..f160a4a2 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/package.html @@ -0,0 +1,3 @@ + +The core package of the Spring-LDAP library. + \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java new file mode 100644 index 00000000..756fc593 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AbstractContextSource.java @@ -0,0 +1,455 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.util.Hashtable; +import java.util.Map; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.JdkVersion; +import org.springframework.ldap.AuthenticationSource; +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; + +/** + * Abstract implementation of the ContextSource interface. By default, returns + * an authenticated DirContext implementation for both read-only and read-write + * operations. To have an anonymous environment created for read-only + * operations, set the anonymousReadOnly property to true. + *

+ * Implementing classes need to implement + * {@link #getDirContextInstance(Hashtable)} to create a DirContext instance of + * the desired type. + *

+ * If an AuthenticationSource is set, this will be used for getting user name + * and password for each new connection, otherwise a default one will be created + * using the specified userName and password. + *

+ * Note: When using implementations of this class outside of a Spring + * Context it is necessary to call {@link #afterPropertiesSet()} when all + * properties are set, in order to finish up initialization. + * + * @see org.springframework.ldap.LdapTemplate + * @see org.springframework.ldap.support.DefaultDirObjectFactory + * @see org.springframework.ldap.support.LdapContextSource + * @see org.springframework.ldap.support.DirContextSource + * + * @author Mattias Arthursson + * @author Adam Skogman + * @author Ulrik Sandberg + */ +public abstract class AbstractContextSource implements ContextSource, + InitializingBean { + + private static final Class DEFAULT_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory.class; + + private static final Class DEFAULT_DIR_OBJECT_FACTORY = DefaultDirObjectFactory.class; + + private Class dirObjectFactory = DEFAULT_DIR_OBJECT_FACTORY; + + private Class contextFactory = DEFAULT_CONTEXT_FACTORY; + + private DistinguishedName base; + + protected String userName = ""; + + protected String password = ""; + + private String[] urls; + + private boolean pooled = true; + + private Hashtable baseEnv = new Hashtable(); + + private Hashtable anonymousEnv; + + private AuthenticationSource authenticationSource; + + private boolean cacheEnvironmentProperties = true; + + private boolean anonymousReadOnly = false; + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + private static final Log log = LogFactory.getLog(LdapContextSource.class); + + public static final String SUN_LDAP_POOLING_FLAG = "com.sun.jndi.ldap.connect.pool"; + + private static final String JDK_142 = "1.4.2"; + + public DirContext getReadOnlyContext() { + if (!anonymousReadOnly) { + return createContext(getAuthenticatedEnv()); + } else { + return createContext(getAnonymousEnv()); + } + } + + public DirContext getReadWriteContext() { + return createContext(getAuthenticatedEnv()); + } + + /** + * Default implementation of setting the environment up to be authenticated. + * Override in subclass if necessary. This is needed for Active Directory + * connectivity, for example. + * + * @param env + * the environment to modify. + */ + protected void setupAuthenticatedEnvironment(Hashtable env) { + env + .put(Context.SECURITY_PRINCIPAL, authenticationSource + .getPrincipal()); + log.debug("Principal: '" + userName + "'"); + env.put(Context.SECURITY_CREDENTIALS, authenticationSource + .getCredentials()); + } + + /** + * Close the context and swallow any exceptions. + * + * @param ctx + * the DirContext to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + } + } + } + + /** + * Assemble a valid url String from all registered urls to add as + * PROVIDER_URL to the environment. + * + * @param ldapUrls + * all individual url Strings. + * @return the full url String + */ + protected String assembleProviderUrlString(String[] ldapUrls) { + StringBuffer providerUrlBuffer = new StringBuffer(1024); + for (int i = 0; i < ldapUrls.length; i++) { + providerUrlBuffer.append(ldapUrls[i]); + if (base != null) { + if (!ldapUrls[i].endsWith("/")) { + providerUrlBuffer.append("/"); + } + providerUrlBuffer.append(base.toUrl()); + } + providerUrlBuffer.append(' '); + } + return providerUrlBuffer.toString().trim(); + } + + /** + * Set the base suffix from which all operations should origin. If a base + * suffix is set, you will not have to (and, indeed, should not) specify the + * full distinguished names in the operations performed. + * + * @param base + * the base suffix. + */ + public void setBase(String base) { + this.base = new DistinguishedName(base); + } + + /** + * Create a DirContext using the supplied environment. + * + * @param environment + * the Ldap environment to use when creating the DirContext. + * @return a new DirContext implpementation initialized with the supplied + * environment. + */ + DirContext createContext(Hashtable environment) { + DirContext ctx = null; + + try { + ctx = getDirContextInstance(environment); + + if (log.isInfoEnabled()) { + Hashtable ctxEnv = ctx.getEnvironment(); + String ldapUrl = (String) ctxEnv.get(Context.PROVIDER_URL); + log.debug("Got Ldap context on server '" + ldapUrl + "'"); + } + + return ctx; + } catch (NamingException e) { + closeContext(ctx); + throw getExceptionTranslator().translate(e); + } + } + + /** + * Set the context factory. Default is com.sun.jndi.ldap.LdapCtxFactory. + * + * @param contextFactory + * the context factory used when creating Contexts. + */ + public void setContextFactory(Class contextFactory) { + this.contextFactory = contextFactory; + } + + /** + * Set the DirObjectFactory to use. Default is + * {@link DefaultDirObjectFactory}. The specified class needs to be an + * implementation of javax.naming.spi.DirObjectFactory. Note: Setting + * this value to null may have cause connection leaks when using + * ContextMapper methods in LdapTemplate. + * + * @param dirObjectFactory + * the DirObjectFactory to be used. Null means that no + * DirObjectFactory will be used. + */ + public void setDirObjectFactory(Class dirObjectFactory) { + this.dirObjectFactory = dirObjectFactory; + } + + /** + * Checks that all necessary data is set and that there is no compatibility + * issues, after which the instance is initialized. Note that you need to + * call this method explicitly after setting all desired properties if using + * the class outside of a Spring Context. + */ + public void afterPropertiesSet() throws Exception { + if (ArrayUtils.isEmpty(urls)) { + throw new IllegalArgumentException( + "At least one server url must be set"); + } + + if (base != null && getJdkVersion().compareTo(JDK_142) < 0) { + throw new IllegalArgumentException( + "Base path is not supported for JDK versions < 1.4.2"); + } + + if (authenticationSource == null) { + log.debug("AuthenticationSource not set - " + + "using default implementation"); + if (StringUtils.isBlank(userName)) { + log + .warn("Property 'userName' not set - " + + "anonymous context will be used for read-write operations"); + } else if (StringUtils.isBlank(password)) { + log.warn("Property 'password' not set - " + + "blank password will be used"); + } + authenticationSource = new SimpleAuthenticationSource(); + } + + if (cacheEnvironmentProperties) { + anonymousEnv = setupAnonymousEnv(); + } + } + + private Hashtable setupAnonymousEnv() { + if (pooled) { + baseEnv.put(SUN_LDAP_POOLING_FLAG, "true"); + log.debug("Using LDAP pooling."); + } else { + log.debug("Not using LDAP pooling"); + } + + Hashtable env = new Hashtable(baseEnv); + + env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory.getName()); + env.put(Context.PROVIDER_URL, assembleProviderUrlString(urls)); + + if (dirObjectFactory != null) { + env.put(Context.OBJECT_FACTORIES, dirObjectFactory.getName()); + } + + if (base != null) { + // Save the base path for use in the DefaultDirObjectFactory. + env.put(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY, base); + } + + log.debug("Trying provider Urls: " + assembleProviderUrlString(urls)); + + return env; + } + + /** + * Set the password (credentials) to use for getting authenticated contexts. + * + * @param password + * the password. + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Set the user name (principal) to use for getting authenticated contexts. + * + * @param userName + * the user name. + */ + public void setUserName(String userName) { + this.userName = userName; + } + + /** + * Set the urls of the LDAP servers. Use this method if several servers are + * required. + * + * @param urls + * the urls of all servers. + */ + public void setUrls(String[] urls) { + this.urls = urls; + } + + /** + * Set the url of the LDAP server. Utility method if only one server is + * used. + * + * @param url + * the url of the LDAP server. + */ + public void setUrl(String url) { + this.urls = new String[] { url }; + } + + /** + * Set whether the pooling flag should be set. Default is true. + * + * @param pooled + * whether Contexts should be pooled. + */ + public void setPooled(boolean pooled) { + this.pooled = pooled; + } + + /** + * If any custom environment properties are needed, these can be set using + * this method. + * + * @param baseEnvironmentProperties + */ + public void setBaseEnvironmentProperties(Map baseEnvironmentProperties) { + this.baseEnv = new Hashtable(baseEnvironmentProperties); + } + + String getJdkVersion() { + return JdkVersion.getJavaVersion(); + } + + protected Hashtable getAnonymousEnv() { + if (cacheEnvironmentProperties) { + return anonymousEnv; + } else { + return setupAnonymousEnv(); + } + } + + protected Hashtable getAuthenticatedEnv() { + // The authenticated environment should always be rebuilt. + Hashtable env = new Hashtable(getAnonymousEnv()); + setupAuthenticatedEnvironment(env); + return env; + } + + public void setAuthenticationSource( + AuthenticationSource authenticationProvider) { + this.authenticationSource = authenticationProvider; + } + + /** + * Set whether environment properties should be cached between requsts for + * anonymous environment. Default is true; setting this property to false + * causes the environment Hashmap to be rebuilt from the current property + * settings of this instance between each request for an anonymous + * environment. + * + * @param cacheEnvironmentProperties + * true causes that the anonymous environment properties should + * be cached, false causes the Hashmap to be rebuilt for each + * request. + */ + public void setCacheEnvironmentProperties(boolean cacheEnvironmentProperties) { + this.cacheEnvironmentProperties = cacheEnvironmentProperties; + } + + /** + * Set whether an anonymous environment should be used for read-only + * operations. Default is false. + * + * @param anonymousReadOnly + * true if and anonymous environment should be + * used for read-only operations, false otherwise. + */ + public void setAnonymousReadOnly(boolean anonymousReadOnly) { + this.anonymousReadOnly = anonymousReadOnly; + } + + /** + * Set the NamingExceptionTranslator to be used by this instance. By + * default, a {@link DefaultNamingExceptionTranslator} will be used. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } + + /** + * Get the NamingExceptionTranslator used by this instance. + * + * @return the NamingExceptionTranslator. + */ + public NamingExceptionTranslator getExceptionTranslator() { + return exceptionTranslator; + } + + /** + * Implement in subclass to create a DirContext of the desired type (e.g. + * InitialDirContext or InitialLdapContext). + * + * @param environment + * the environment to use when creating the instance. + * @return a new DirContext instance. + * @throws NamingException + * if one is encountered when creating the instance. + */ + protected abstract DirContext getDirContextInstance(Hashtable environment) + throws NamingException; + + class SimpleAuthenticationSource implements AuthenticationSource { + + public String getPrincipal() { + return userName; + } + + public String getCredentials() { + return password; + } + + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java new file mode 100644 index 00000000..9d0a7fa1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import javax.naming.directory.ModificationItem; + +/** + * Indicates that the implementor is capable of keeping track of any attribute + * modifications and return them as ModificationItems. + * + * @author Mattias Arthursson + * + */ +public interface AttributeModificationsAware { + + /** + * Creates an array of which attributes have been changed or added or removed. + * + * @return an array of modification items + */ + public ModificationItem[] getModificationItems(); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java new file mode 100644 index 00000000..8f017beb --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.NameClassPair; + +import org.springframework.ldap.NameClassPairCallbackHandler; + +/** + * A NameClassPairCallbackHandler for counting all returned entries. + * + * @author Mattias Arthursson + * + */ +public class CountNameClassPairCallbackHandler implements + NameClassPairCallbackHandler { + + private int noOfRows = 0; + + /** + * Get the number of rows that was returned by the search. + * + * @return the number of entries that have been handled. + */ + public int getNoOfRows() { + return noOfRows; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.SearchResultCallbackHandler#handleSearchResult(javax.naming.directory.SearchResult) + */ + public void handleNameClassPair(NameClassPair nameClassPair) { + noOfRows++; + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java new file mode 100644 index 00000000..b46e1d55 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java @@ -0,0 +1,115 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.directory.Attributes; +import javax.naming.spi.DirObjectFactory; + +/** + * Default implementation of the DirObjectFactory interface. Creates a + * DirContextAdapter from the supplied arguments. + * + * @author Mattias Arthursson + */ +public class DefaultDirObjectFactory implements DirObjectFactory { + /** + * Key to use in the ContextSource implementation to store the value of the + * base path suffix, if any, in the Ldap Environment. + */ + public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path"; + + /** + * Creates a DirContextAdapter from the supplied arguments. + * + * @param obj + * @param name + * @param nameCtx + * @param environment + * @param attrs + * @return a new DirContextAdapter from the attributes and name. + * @throws Exception + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, + Hashtable environment, Attributes attrs) throws Exception { + + try { + DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, + stripBasePath(name, environment)); + dirContextAdapter.setUpdateMode(true); + + return dirContextAdapter; + } finally { + // It seems that the object supplied to the obj parameter is a + // DirContext instance with reference to the same Ldap connection as + // the original context. Since it is not the same instance (that's + // the nameCtx parameter) this one really needs to be closed in + // order to correctly clean up and return the connection to the pool + // when we're finished with the surrounding operation. + if (obj instanceof Context) { + Context ctx = (Context) obj; + try { + ctx.close(); + } catch (Exception e) { + // Never mind this + } + + } + } + } + + /** + * Rather crude method to remove the base suffix if specified in the LDAP + * environment. This could probably be improved to increase performance. + * + * @param name + * the full distinguished name of the found object. + * @param environment + * the context environment. + * @return the DN, without the base suffix. + */ + private Name stripBasePath(Name name, Hashtable environment) { + if (environment.containsKey(JNDI_ENV_BASE_PATH_KEY)) { + DistinguishedName distinguishedName = new DistinguishedName(name + .toString()); + distinguishedName.removeFirst((Name) environment + .get(JNDI_ENV_BASE_PATH_KEY)); + return distinguishedName; + } else { + return name; + } + } + + /** + * Returns null. + * + * @param obj + * @param name + * @param nameCtx + * @param environment + * @return null. + * @throws Exception + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, + Hashtable environment) throws Exception { + return null; + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java new file mode 100644 index 00000000..e75ecef0 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextAdapter.java @@ -0,0 +1,1186 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.NameParser; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; + +/** + * Implements the interesting methods of the DirContext interface. In particular + * it contains utility methods for getting and setting Attributes. Using the + * {@link org.springframework.ldap.support.DefaultDirObjectFactory} in your + * ContextSource you may receive instances of this class from searches and + * lookups. This can be particularly useful when updating data, since this class + * implements {@link org.springframework.ldap.support.AttributeModificationsAware}, + * providing a {@link #getModificationItems()} method. + * + * @author Magnus Robertsson + * @author Andreas Ronge + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DirContextAdapter implements DirContextOperations { + + private static final boolean ORDER_DOESNT_MATTER = false; + + private static Log log = LogFactory.getLog(DirContextAdapter.class); + + private final Attributes attrs; + + private Name dn; + + private boolean updateMode = false; + + private Attributes updatedAttrs; + + private NamingExceptionTranslator exceptionTranslator; + + /** + * Default constructor. + */ + public DirContextAdapter() { + attrs = new BasicAttributes(true); + dn = null; + } + + public DirContextAdapter(Name dn) { + attrs = new BasicAttributes(true); + this.dn = dn; + } + + /** + * Create a new entry from the supplied attributes and dn. + * + * @param pAttrs + * the attributes. + * @param dn + * the dn. + */ + public DirContextAdapter(Attributes pAttrs, Name dn) { + attrs = (Attributes) pAttrs.clone(); + this.dn = dn; + } + + /** + * Constructor for cloning an existing entry. + * + * @param master + * The object to be copied. + */ + protected DirContextAdapter(DirContextAdapter master) { + this.attrs = (Attributes) master.attrs.clone(); + this.dn = master.dn; + this.updatedAttrs = (Attributes) master.updatedAttrs.clone(); + this.updateMode = master.updateMode; + } + + /** + * Sets the update mode. The update mode should be false for + * a new entry and true for an existing entry that is being + * updated. + * + * @param mode + * Update mode. + */ + protected void setUpdateMode(boolean mode) { + this.updateMode = mode; + if (updateMode) { + updatedAttrs = new BasicAttributes(true); + } + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#isUpdateMode() + */ + public boolean isUpdateMode() { + return updateMode; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getNamesOfModifiedAttributes() + */ + public String[] getNamesOfModifiedAttributes() { + + List tmpList = new ArrayList(); + + NamingEnumeration attributesEnumeration; + if (isUpdateMode()) { + attributesEnumeration = updatedAttrs.getAll(); + } else { + attributesEnumeration = attrs.getAll(); + } + + try { + while (attributesEnumeration.hasMore()) { + Attribute oneAttribute = (Attribute) attributesEnumeration + .next(); + tmpList.add(oneAttribute.getID()); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + return (String[]) tmpList.toArray(new String[0]); + } + + private void closeNamingEnumeration(NamingEnumeration enumeration) { + try { + if (enumeration != null) { + enumeration.close(); + } + } catch (NamingException e) { + // Never mind this + } + } + + /* + * @see org.springframework.ldap.support.AttributeModificationsAware#getModificationItems() + */ + public ModificationItem[] getModificationItems() { + if (!updateMode) { + return new ModificationItem[0]; + } + + List tmpList = new LinkedList(); + NamingEnumeration attributesEnumeration = null; + try { + attributesEnumeration = updatedAttrs.getAll(); + + // find attributes that have been changed, removed or added + while (attributesEnumeration.hasMore()) { + Attribute oneAttr = (Attribute) attributesEnumeration.next(); + + collectModifications(oneAttr, tmpList); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + if (log.isDebugEnabled()) { + log.debug("Number of modifications:" + tmpList.size()); + } + + return (ModificationItem[]) tmpList + .toArray(new ModificationItem[tmpList.size()]); + } + + /** + * Collect all modifications for the changed attribute. If no changes have + * been made, return immediately. If modifications have been made, and the + * original size as well as the updated size of the attribute is 1, replace + * the attribute. If the size of the updated attribute is 0, remove the + * attribute. Otherwise, the attribute is a multi-value attribute, in which + * case all modifications to the original value (removals and additions) + * will be collected individually. + * + * @param changedAttr + * the value of the changed attribute. + * @param modificationList + * the list in which to add the modifications. + * @throws NamingException + * if thrown by called Attribute methods. + */ + private void collectModifications(Attribute changedAttr, + List modificationList) throws NamingException { + Attribute currentAttribute = attrs.get(changedAttr.getID()); + + if (changedAttr.equals(currentAttribute)) { + // No changes + return; + } else if (currentAttribute != null && currentAttribute.size() == 1 + && changedAttr.size() == 1) { + // Replace single-vale attribute. + modificationList.add(new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, changedAttr)); + } else if (changedAttr.size() == 0) { + // Attribute has been removed. + modificationList.add(new ModificationItem( + DirContext.REMOVE_ATTRIBUTE, changedAttr)); + } else { + // Collect all modifications to attribute individually (this also + // covers additions to a previously non-existant attribute). + Collection oldValues = new LinkedList(); + Collection newValues = new LinkedList(); + + collectAttributeValues(oldValues, currentAttribute); + collectAttributeValues(newValues, changedAttr); + Collection myModifications = new LinkedList(); + + Collection addedValues = CollectionUtils.subtract(newValues, + oldValues); + Collection removedValues = CollectionUtils.subtract(oldValues, + newValues); + + collectModifications(DirContext.ADD_ATTRIBUTE, changedAttr, + addedValues, myModifications); + collectModifications(DirContext.REMOVE_ATTRIBUTE, changedAttr, + removedValues, myModifications); + + if (myModifications.isEmpty()) { + // This means that the attributes are not equal, but the + // actual values are the same - thus the order must have + // changed. This should result in a REPLACE_ATTRIBUTE operation. + myModifications.add(new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, changedAttr)); + } + + modificationList.addAll(myModifications); + } + } + + private void collectModifications(int modificationType, Attribute attr, + Collection values, Collection c) { + if (values.size() > 0) { + BasicAttribute modificationAttribute = new BasicAttribute(attr + .getID()); + for (Iterator iter = values.iterator(); iter.hasNext();) { + modificationAttribute.add(iter.next()); + } + c + .add(new ModificationItem(modificationType, + modificationAttribute)); + } + } + + private void collectAttributeValues(Collection valueCollection, + Attribute attribute) throws NamingException { + + if (attribute == null) { + return; + } + + NamingEnumeration attributeValues = attribute.getAll(); + while (attributeValues.hasMoreElements()) { + Object value = (Object) attributeValues.nextElement(); + valueCollection.add(value); + } + } + + /** + * Decide whether an attribute has changed or not. + * + * @param name + * Attribute name. + * @param value + * Attribute value. + * @return true if attribute has changed. + */ + private boolean isChanged(String name, Object value) { + Attribute a = attrs.get(name); + + // FALSE if both are null it is not changed + if (a == null && value == null) { + return false; + } + + // TRUE if existing value is null or does not contain one value + if (a == null || a.size() != 1) { + return true; + } + + // TRUE if existing value is not null and the new one is null + if (a != null && value == null) { + return true; + } + + // TRUE if we can't access the value + Object obj = null; + try { + obj = a.get(0); + } catch (NamingException e) { + return true; + } + + // TRUE if the value is not equal and all other tests has been performed + return !value.equals(obj); + } + + /** + * returns true if the attribute is empty. It is empty if a == null, size == + * 0 or get() == null or an exception if thrown when accessing the get + * method + */ + private boolean isEmptyAttribute(Attribute a) { + try { + return (a == null || a.size() == 0 || a.get() == null); + } catch (NamingException e) { + return true; + } + } + + /** + * Compare an existing attribute with name pName with value pValue. The + * order of the array must be the same order as the existing multivalued + * attribute. + * + * @param name + * @param values + * @return true if it has changed + */ + private boolean isChanged(String name, Object[] values, boolean orderMatters) { + + Attribute a = attrs.get(name); + + // values == null and values.length == 0 is treated the same way + boolean emptyNewValue = (values == null || values.length == 0); + + // Setting to empty --------------------- + if (emptyNewValue) { + // FALSE if both are null it is not changed (they both does not + // exist) + // TRUE if new value is null and old value exists (should be + // removed) + return (a != null); + } + + // NOT setting to empty ------------------- + + // TRUE if existing value is null + if (a == null) { + return true; + } + + // TRUE is different length + if (a.size() != values.length) { + return true; + } + + // Check contents of arrays + + // Order DOES matter, e.g. first names + try { + for (int i = 0; i < a.size(); i++) { + Object obj = a.get(i); + // TRUE if one value is not equal + if (!(obj instanceof String)) { + return true; + } + if (orderMatters) { + // check only the string with same index + if (!values[i].equals(obj)) { + return true; + } + } else { + // check all strings + if (!ArrayUtils.contains(values, obj)) { + return true; + } + } + } + + } catch (NamingException e) { + // TRUE if we can't access the value + return true; + } + + // FALSE since we have compared all values + return false; + } + + /** + * Checks if an entry has a specific attribute. + * + * This method simply calls exists(String) with the attribute name. + * + * @param attr + * the attribute to check. + * @return true if attribute exists in entry. + */ + protected final boolean exists(Attribute attr) { + return exists(attr.getID()); + } + + /** + * Checks if the attribute exists in this entry, either it was read or it + * has been added and update() has been called. + * + * @param attrId + * id of the attribute to check. + * @return true if the attribute exists in the entry. + */ + protected final boolean exists(String attrId) { + return attrs.get(attrId) != null; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getStringAttribute(java.lang.String) + */ + public String getStringAttribute(String name) { + return (String) getObjectAttribute(name); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getObjectAttribute(java.lang.String) + */ + public Object getObjectAttribute(String name) { + Attribute oneAttr = attrs.get(name); + if (oneAttr == null) { + return null; + } + try { + return oneAttr.get(); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValue(java.lang.String, + * java.lang.Object) + */ + public void setAttributeValue(String name, Object value) { + // new entry + if (!updateMode && value != null) { + attrs.put(name, value); + } + + // updating entry + if (updateMode && isChanged(name, value)) { + BasicAttribute attribute = new BasicAttribute(name); + if (value != null) { + attribute.add(value); + } + updatedAttrs.put(attribute); + } + + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String, + * java.lang.Object[]) + */ + public void setAttributeValues(String name, Object[] values) { + setAttributeValues(name, values, ORDER_DOESNT_MATTER); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String, + * java.lang.Object[], boolean) + */ + public void setAttributeValues(String name, Object[] values, + boolean orderMatters) { + Attribute a = new BasicAttribute(name, orderMatters); + + for (int i = 0; values != null && i < values.length; i++) { + a.add(values[i]); + } + + // only change the original attribute if not in update mode + if (!updateMode && values != null && values.length > 0) { + // don't save empty arrays + attrs.put(a); + } + + // possible to set an already existing attribute to an empty array + if (updateMode && isChanged(name, values, orderMatters)) { + updatedAttrs.put(a); + } + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#update() + */ + public void update() { + NamingEnumeration attributesEnumeration = null; + + try { + attributesEnumeration = updatedAttrs.getAll(); + + // find what to update + while (attributesEnumeration.hasMore()) { + Attribute a = (Attribute) attributesEnumeration.next(); + + // if it does not exist it should be added + if (isEmptyAttribute(a)) { + attrs.remove(a.getID()); + } else { + // Otherwise it should be set. + attrs.put(a); + } + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + // Reset the attributes to be updated + updatedAttrs = new BasicAttributes(true); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getStringAttributes(java.lang.String) + */ + public String[] getStringAttributes(String name) { + String[] attributes; + + Attribute attribute = attrs.get(name); + if (attribute != null && attribute.size() > 0) { + attributes = new String[attribute.size()]; + for (int i = 0; i < attribute.size(); i++) { + try { + attributes[i] = (String) attribute.get(i); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } else { + return null; + } + + return attributes; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getAttributeSortedStringSet(java.lang.String) + */ + public SortedSet getAttributeSortedStringSet(String name) { + TreeSet attrSet = new TreeSet(); + + Attribute attribute = attrs.get(name); + if (attribute != null) { + for (int i = 0; i < attribute.size(); i++) { + try { + attrSet.add(attribute.get(i)); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } else { + return null; + } + + return attrSet; + } + + /** + * Set the supplied attribute. + * + * @param attribute + * the attribute to set. + */ + public void setAttribute(Attribute attribute) { + attrs.put(attribute); + } + + /** + * Get all attributes. + * + * @return all attributes. + */ + public Attributes getAttributes() { + return attrs; + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(Name) + */ + public Attributes getAttributes(Name name) throws NamingException { + return getAttributes(name.toString()); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(String) + */ + public Attributes getAttributes(String name) throws NamingException { + if (!StringUtils.isEmpty(name)) { + throw new NameNotFoundException(); + } + return (Attributes) attrs.clone(); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(Name, String[]) + */ + public Attributes getAttributes(Name name, String[] attrIds) + throws NamingException { + return getAttributes(name.toString(), attrIds); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(String, String[]) + */ + public Attributes getAttributes(String name, String[] attrIds) + throws NamingException { + if (!StringUtils.isEmpty(name)) { + throw new NameNotFoundException(); + } + + Attributes a = new BasicAttributes(true); + Attribute target; + for (int i = 0; i < attrIds.length; i++) { + target = attrs.get(attrIds[i]); + if (target != null) { + a.put(target); + } + } + + return a; + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, + * int, javax.naming.directory.Attributes) + */ + public void modifyAttributes(Name name, int modOp, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(String, int, + * Attributes) + */ + public void modifyAttributes(String name, int modOp, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(Name, + * ModificationItem[]) + */ + public void modifyAttributes(Name name, ModificationItem[] mods) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(String, + * ModificationItem[]) + */ + public void modifyAttributes(String name, ModificationItem[] mods) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#bind(Name, Object, Attributes) + */ + public void bind(Name name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#bind(String, Object, Attributes) + */ + public void bind(String name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#rebind(Name, Object, Attributes) + */ + public void rebind(Name name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#rebind(String, Object, Attributes) + */ + public void rebind(String name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#createSubcontext(Name, Attributes) + */ + public DirContext createSubcontext(Name name, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#createSubcontext(String, + * Attributes) + */ + public DirContext createSubcontext(String name, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchema(Name) + */ + public DirContext getSchema(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchema(String) + */ + public DirContext getSchema(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchemaClassDefinition(Name) + */ + public DirContext getSchemaClassDefinition(Name name) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchemaClassDefinition(String) + */ + public DirContext getSchemaClassDefinition(String name) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, Attributes, String[]) + */ + public NamingEnumeration search(Name name, Attributes matchingAttributes, + String[] attributesToReturn) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, Attributes, + * String[]) + */ + public NamingEnumeration search(String name, Attributes matchingAttributes, + String[] attributesToReturn) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, Attributes) + */ + public NamingEnumeration search(Name name, Attributes matchingAttributes) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, Attributes) + */ + public NamingEnumeration search(String name, Attributes matchingAttributes) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, String, + * SearchControls) + */ + public NamingEnumeration search(Name name, String filter, + SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, String, + * SearchControls) + */ + public NamingEnumeration search(String name, String filter, + SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, String, Object[], + * SearchControls) + */ + public NamingEnumeration search(Name name, String filterExpr, + Object[] filterArgs, SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, String, Object[], + * SearchControls) + */ + public NamingEnumeration search(String name, String filterExpr, + Object[] filterArgs, SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookup(Name) + */ + public Object lookup(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookup(String) + */ + public Object lookup(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#bind(Name, Object) + */ + public void bind(Name name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#bind(String, Object) + */ + public void bind(String name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rebind(Name, Object) + */ + public void rebind(Name name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rebind(String, Object) + */ + public void rebind(String name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#unbind(Name) + */ + public void unbind(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#unbind(String) + */ + public void unbind(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rename(Name, Name) + */ + public void rename(Name oldName, Name newName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rename(String, String) + */ + public void rename(String oldName, String newName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#list(Name) + */ + public NamingEnumeration list(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#list(String) + */ + public NamingEnumeration list(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#listBindings(Name) + */ + public NamingEnumeration listBindings(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#listBindings(String) + */ + public NamingEnumeration listBindings(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#destroySubcontext(Name) + */ + public void destroySubcontext(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#destroySubcontext(String) + */ + public void destroySubcontext(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#createSubcontext(Name) + */ + public Context createSubcontext(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#createSubcontext(String) + */ + public Context createSubcontext(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookupLink(Name) + */ + public Object lookupLink(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookupLink(String) + */ + public Object lookupLink(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameParser(Name) + */ + public NameParser getNameParser(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameParser(String) + */ + public NameParser getNameParser(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#composeName(Name, Name) + */ + public Name composeName(Name name, Name prefix) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#composeName(String, String) + */ + public String composeName(String name, String prefix) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#addToEnvironment(String, Object) + */ + public Object addToEnvironment(String propName, Object propVal) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#removeFromEnvironment(String) + */ + public Object removeFromEnvironment(String propName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getEnvironment() + */ + public Hashtable getEnvironment() throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#close() + */ + public void close() throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameInNamespace() + */ + public String getNameInNamespace() { + return dn.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getDn() + */ + public Name getDn() { + return dn; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#setDn(javax.naming.Name) + */ + public final void setDn(Name dn) { + if (!updateMode) { + this.dn = dn; + } + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + return EqualsBuilder.reflectionEquals(this, obj); + } + + /** + * @see Object#hashCode() + */ + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(getClass().getName()); + buf.append(":"); + if (dn != null) { + buf.append(" dn=" + dn); + } + buf.append(" {"); + + try { + for (NamingEnumeration i = attrs.getAll(); i.hasMore();) { + Attribute attribute = (Attribute) i.next(); + if (attribute.size() == 1) { + buf.append(attribute.getID()); + buf.append('='); + buf.append(attribute.get()); + } else { + for (int j = 0; j < attribute.size(); j++) { + if (j > 0) { + buf.append(", "); + } + buf.append(attribute.getID()); + buf.append('['); + buf.append(j); + buf.append("]="); + buf.append(attribute.get(j)); + } + } + + if (i.hasMore()) { + buf.append(", "); + } + } + } catch (NamingException e) { + log.warn("Error in toString()"); + } + buf.append('}'); + + return buf.toString(); + } + + /** + * Get the NamingExceptionTranslator. + * + * @return the NamingExceptionTranslator to use; if none is specified, + * {@link DefaultNamingExceptionTranslator} is used. + */ + public NamingExceptionTranslator getExceptionTranslator() { + if (exceptionTranslator == null) { + exceptionTranslator = new DefaultNamingExceptionTranslator(); + } + return exceptionTranslator; + } + + /** + * Set the NamingExceptionTranslator to use. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java new file mode 100644 index 00000000..645b18d6 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextOperations.java @@ -0,0 +1,161 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.SortedSet; + +import javax.naming.Name; +import javax.naming.directory.DirContext; + +/** + * Interface for DirContextAdapter to simplify mock testing. + * + * @author Mattias Arthursson + */ +public interface DirContextOperations extends DirContext, + AttributeModificationsAware { + + /** + * Gets the update mode. The update mode should be true for a + * new entry and true for an existing entry that is being + * updated. + * + * @return update mode + */ + public boolean isUpdateMode(); + + /** + * Creates a String array of the names of the attributes which have been + * changed. + * + * If this is a new entry, all set entries will be in the list. If this is + * an updated entry, only changed and removed entries will be in the array. + * + * @return Array of String + */ + public String[] getNamesOfModifiedAttributes(); + + /** + * Get the value of a String attribute. + * + * @param name + * name of the attribute. + * @return the value of the attribute. + */ + public String getStringAttribute(String name); + + /** + * Get the value of an Object attribute. + * + * @param name + * name of the attribute. + * @return the attribute value as an object if it exists, or + * null otherwise. + */ + public Object getObjectAttribute(String name); + + /** + * Set the with the name name to the value. + * + * @param name + * name of the attribute. + * @param value + * value to set the attribute to. + */ + public void setAttributeValue(String name, Object value); + + /** + * Sets a multivalue attribute, disregarding the order of the values. + * + * If value is null or value.length == 0 then the attribute will be removed. + * + * If update mode, changes will be made only if the array has more or less + * objects or if one or more object has changed. Reordering the objects will + * not cause an update. + * + * @param name + * The id of the attribute. + * @param values + * Attribute values. + */ + public void setAttributeValues(String name, Object[] values); + + /** + * Sets a multivalue attribute. + * + * If value is null or value.length == 0 then the attribute will be removed. + * + * If update mode, changes will be made if the array has more or less + * objects or if one or more string has changed. + * + * Reordering the objects will only cause an update if orderMatters is set + * to true. + * + * @param name + * The id of the attribute. + * @param values + * Attribute values. + * @param orderMatters + * If true, it will be changed even if data was + * just reordered. + */ + public void setAttributeValues(String name, Object[] values, + boolean orderMatters); + + /** + * Update the attributes. This will mean that the getters + * (getStringAttribute methods) will return the updated values. Remove the + * attributes to be updated. + */ + public void update(); + + /** + * Get all values of a String attribute. + * + * @param name + * name of the attribute. + * + * @return all registered values of the attribute. + */ + public String[] getStringAttributes(String name); + + /** + * Get all String values of the attribute as a SortedSet. + * + * @param name + * name of the attribute. + * @return a SortedSet containing all values of the attribute. + */ + public SortedSet getAttributeSortedStringSet(String name); + + /** + * Returns DN, for example uid=some.user,ou=People,ou=EU. + * + * @return The distinguished name of the current context. + * + * @see DirContextAdapter#getNameInNamespace() + */ + public Name getDn(); + + /** + * Set the dn of this entry. + * + * @param dn + * the dn. + */ + public void setDn(Name dn); +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java new file mode 100644 index 00000000..e69d6a0a --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DirContextSource.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; + +/** + * ContextSource implementation which creates InitialDirContext instances, for + * LDAPv2 compatibility. For configuration information, see + * {@link org.springframework.ldap.support.AbstractContextSource AbstractContextSource}. + * + * @see org.springframework.ldap.support.AbstractContextSource + * + * @author Mattias Arthursson + */ +public class DirContextSource extends AbstractContextSource { + + /** + * Create a new InitialDirContext instance. + * + * @param environment + * the environment to use when creating the context. + * @return a new InitialDirContext implementation. + */ + protected DirContext getDirContextInstance(Hashtable environment) + throws NamingException { + return new InitialDirContext(environment); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java new file mode 100644 index 00000000..88b26f95 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/DistinguishedName.java @@ -0,0 +1,570 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.naming.InvalidNameException; +import javax.naming.Name; + + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Default implementation of a Name corresponding to an LDAP path. A + * DistinguishedName implementation is included in JDK1.5 (LdapName), but not in + * prior releases. + * + * An DistinguishedName is particularly useful when building or modifying an + * Ldap path dynamically, as escaping will be taken care of. + * + * A path is split into several names. The Name interface specifies that the + * most significant part be in position 0, i.e. + * + * The path: uid=adam.skogman, ou=People, ou=EU Name[0]: ou=EU Name[1]: + * ou=People Name[2]: uid=adam.skogman + *

+ * Useful for parsing and building LDAP paths. + * + *

+ * DistinguishedName path = new DistinguishedName();
+ * path.addLast("cn", entry.getUid());
+ * path.addLast("ou", "users");
+ * path.append(new DistinguishedName(helpdesk.getSomeSuffix()));
+ * String dn = path.toString();
+ * 
+ * + * TODO: Implement compareTo(). + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DistinguishedName implements Name { + private static final long serialVersionUID = 3514344371999042586L; + + public static final DistinguishedName EMPTY_PATH = new DistinguishedName(); + + private LinkedList names; + + protected static final Pattern NAME_PATTERN = Pattern + .compile("(.*?[^\\\\])(,|;|$)"); + + /** + * Construct a new DistinguishedName with no components. + */ + public DistinguishedName() { + names = new LinkedList(); + } + + /** + * Construct a new DistinguishedName from a String. + * + * @param path + * a String corresponding to a (syntactically) valid LDAP path. + */ + public DistinguishedName(String path) { + parse(path); + } + + /** + * Construct a new DistinguishedName from the supplied List of LdapRdn + * objects. + * + * @param list + * the components that this instance will consist of. + */ + public DistinguishedName(LinkedList list) { + this.names = list; + } + + /** + * Construct a new DistinguishedName from the supplied Name. The parts of + * the supplied Name must be syntactically correct LdapRdns. + * + * @param name + * the Name to construct a new DistinguishedName from. + */ + public DistinguishedName(Name name) { + names = new LinkedList(); + for (int i = 0; i < name.size(); i++) { + names.add(new LdapRdn(name.get(i))); + } + } + + /** + * Parse the supplied String and make this instance represent the + * corresponding distinguished name. + * + * @param path + * the LDAP path to parse. + */ + protected void parse(String path) { + names = new LinkedList(); + + if (!StringUtils.isBlank(path)) { + + Matcher matcher = NAME_PATTERN.matcher(path); + + while (matcher.find()) { + String rdnString = matcher.group(1); + LdapRdn name = new LdapRdn(rdnString); + names.add(0, name); + } + } + } + + /** + * Get the LdapRdn at a specified position. + * + * @param index + * the LdapRdn to retrieve. + * @return the LdapRdn at the requested position. + */ + public LdapRdn getLdapRdn(int index) { + return (LdapRdn) names.get(index); + } + + /** + * Get the name list. + * + * @return the list of LdapRdns that this DistinguishedName consists of. + */ + public LinkedList getNames() { + return names; + } + + /** + * Get the String representation of this DistinguishedName. + * + * @return a syntactically correct, escaped String representation of the + * DistinguishedName. + */ + public String toString() { + return encode(); + } + + /** + * Builds a complete LDAP path, ldap encoded, useful as a DN. + * + * Always uses lowercase, always separates with ", " i.e. comma and a space. + * + * @return the LDAP path. + */ + public String encode() { + + // empty path + if (names.size() == 0) + return ""; + + StringBuffer buffer = new StringBuffer(256); + + ListIterator i = names.listIterator(names.size()); + while (i.hasPrevious()) { + LdapRdn rdn = (LdapRdn) i.previous(); + buffer.append(rdn.getLdapEncoded()); + + // add comma, except in last iteration + if (i.hasPrevious()) + buffer.append(", "); + } + + return buffer.toString(); + + } + + /** + * Builds a complete LDAP path, ldap and url encoded. Separates only with + * ",". + * + * @return the LDAP path, for use in an url. + */ + public String toUrl() { + StringBuffer buffer = new StringBuffer(256); + + for (int i = names.size() - 1; i >= 0; i--) { + LdapRdn n = (LdapRdn) names.get(i); + buffer.append(n.encodeUrl()); + if (i > 0) { + buffer.append(","); + } + } + return buffer.toString(); + } + + /** + * Determines if a ldap path contains another path. + * + * @param path + * the path to check. + * @return true if the supplied path is conained in this instance, false + * otherwise. + */ + public boolean contains(DistinguishedName path) { + + List shortlist = path.getNames(); + + // this path must be at least as long + if (getNames().size() < shortlist.size()) + return false; + + // must have names + if (shortlist.size() == 0) + return false; + + Iterator longiter = getNames().iterator(); + Iterator shortiter = shortlist.iterator(); + + LdapRdn longname = (LdapRdn) longiter.next(); + LdapRdn shortname = (LdapRdn) shortiter.next(); + + // find first match + while (!longname.equals(shortname) && longiter.hasNext()) { + longname = (LdapRdn) longiter.next(); + } + + // Done? + if (!shortiter.hasNext() && longname.equals(shortname)) + return true; + if (!longiter.hasNext()) + return false; + + // compare + while (longname.equals(shortname) && longiter.hasNext() + && shortiter.hasNext()) { + longname = (LdapRdn) longiter.next(); + shortname = (LdapRdn) shortiter.next(); + } + + // Done + if (!shortiter.hasNext() && longname.equals(shortname)) + return true; + else + return false; + + } + + /** + * Add a LDAP path first + * + * @param path + */ + public void append(DistinguishedName path) { + getNames().addAll(path.getNames()); + } + + /** + * Add a LDAP path first + * + * @param path + */ + public void prepend(DistinguishedName path) { + ListIterator i = path.getNames().listIterator(path.getNames().size()); + while (i.hasPrevious()) { + getNames().addFirst(i.previous()); + } + } + + /** + * Remove the first part of this DistinguishedName. + * + * @return the removed entry. + */ + public LdapRdn removeFirst() { + return (LdapRdn) getNames().removeFirst(); + } + + /** + * Remove the supplied path from the beginning of this DistinguishedName if + * this instance starts with . Useful for stripping base path suffix + * from a DistinguishedName. + * + * @param path + * the path to remove from the beginning of this instance. + */ + public void removeFirst(Name path) { + if (path != null && this.startsWith(path)) { + for (int i = 0; i < path.size(); i++) + this.removeFirst(); + } + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + + // just duplicate the list, the rdns are immutable. + LinkedList list = new LinkedList(getNames()); + + return new DistinguishedName(list); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + + DistinguishedName name = (DistinguishedName) obj; + + // compare the lists + return getNames().equals(name.getNames()); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.getClass().hashCode() ^ getNames().hashCode(); + } + + public int compareTo(Object o) { + // TODO: Implement this. + return 0; + } + + public int size() { + return names.size(); + } + + public boolean isEmpty() { + return names.size() == 0; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getAll() + */ + public Enumeration getAll() { + LinkedList strings = new LinkedList(); + for (Iterator iter = names.iterator(); iter.hasNext();) { + LdapRdn rdn = (LdapRdn) iter.next(); + strings.add(rdn.getLdapEncoded()); + } + + return Collections.enumeration(strings); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#get(int) + */ + public String get(int index) { + LdapRdn rdn = (LdapRdn) names.get(index); + return rdn.getLdapEncoded(); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getPrefix(int) + */ + public Name getPrefix(int index) { + LinkedList newNames = new LinkedList(); + for (int i = 0; i < index; i++) { + newNames.add(names.get(i)); + } + + return new DistinguishedName(newNames); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getSuffix(int) + */ + public Name getSuffix(int index) { + if (index > names.size()) { + throw new ArrayIndexOutOfBoundsException(); + } + + LinkedList newNames = new LinkedList(); + for (int i = index; i < names.size(); i++) { + newNames.add(names.get(i)); + } + + return new DistinguishedName(newNames); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#startsWith(javax.naming.Name) + */ + public boolean startsWith(Name name) { + if (name.size() == 0) { + return false; + } + + DistinguishedName start = null; + if (name instanceof DistinguishedName) { + start = (DistinguishedName) name; + } else { + return false; + } + + if (start.size() > this.size()) { + return false; + } + + Iterator longiter = names.iterator(); + Iterator shortiter = start.getNames().iterator(); + + while (shortiter.hasNext()) { + Object longname = longiter.next(); + Object shortname = shortiter.next(); + + if (!longname.equals(shortname)) { + return false; + } + } + + // All names in shortiter matched. + return true; + } + + /** + * Determines if this ldap path ends with a certian path. + * + * If the argument path is empty (no names in path) this methid will return + * false. + * + * @param name + * The suffix to check for + * + */ + public boolean endsWith(Name name) { + DistinguishedName path = null; + if (name instanceof DistinguishedName) { + path = (DistinguishedName) name; + } else { + return false; + } + + List shortlist = path.getNames(); + + // this path must be at least as long + if (getNames().size() < shortlist.size()) + return false; + + // must have names + if (shortlist.size() == 0) + return false; + + ListIterator longiter = getNames().listIterator(getNames().size()); + ListIterator shortiter = shortlist.listIterator(shortlist.size()); + + while (shortiter.hasPrevious()) { + LdapRdn longname = (LdapRdn) longiter.previous(); + LdapRdn shortname = (LdapRdn) shortiter.previous(); + + if (!longname.equals(shortname)) + return false; + } + + // if short list ended, all were equal + return true; + + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#addAll(javax.naming.Name) + */ + public Name addAll(Name name) throws InvalidNameException { + return addAll(names.size(), name); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#addAll(int, javax.naming.Name) + */ + public Name addAll(int arg0, Name name) throws InvalidNameException { + DistinguishedName distinguishedName = null; + try { + distinguishedName = (DistinguishedName) name; + } catch (ClassCastException e) { + throw new InvalidNameException("Invalid name type"); + } + + names.addAll(arg0, distinguishedName.getNames()); + return this; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#add(java.lang.String) + */ + public Name add(String string) throws InvalidNameException { + return add(names.size(), string); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#add(int, java.lang.String) + */ + public Name add(int index, String string) throws InvalidNameException { + try { + names.add(index, new LdapRdn(string)); + } catch (BadLdapGrammarException e) { + throw new InvalidNameException("Failed to parse rdn '" + string + + "'"); + } + return this; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#remove(int) + */ + public Object remove(int arg0) throws InvalidNameException { + LdapRdn rdn = (LdapRdn) names.remove(arg0); + return rdn.getLdapEncoded(); + } + + /** + * Remove the ldast part of this DistinguishedName. + * + * @return the removed LdapRdn. + */ + public LdapRdn removeLast() { + return (LdapRdn) getNames().removeLast(); + } + + public void add(String key, String value) { + names.add(new LdapRdn(key, value)); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java new file mode 100644 index 00000000..cc73c4ba --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapContextSource.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.InitialLdapContext; + +/** + * ContextSource implementation which creates an InitialLdapContext + * instance. For configuration information, see + * {@link org.springframework.ldap.support.AbstractContextSource AbstractContextSource}. + * + * @see org.springframework.ldap.support.AbstractContextSource + * + * @author Mattias Arthursson + * @author Adam Skogman + * @author Ulrik Sandberg + */ +public class LdapContextSource extends AbstractContextSource { + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.AbstractContextSource#getDirContextInstance(java.util.Hashtable) + */ + protected DirContext getDirContextInstance(Hashtable environment) + throws NamingException { + return new InitialLdapContext(environment, null); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java new file mode 100644 index 00000000..d6525bc2 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapEncoder.java @@ -0,0 +1,235 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Helper class to encode and decode ldap names and values. + * + * @author Adam Skogman + */ +public class LdapEncoder { + + static private String[] nameEscapeTable = new String[96]; + + static private String[] filterEscapeTable = new String['\\' + 1]; + + /** + * Pattern for matching escaped ldap name values. + * + * Double escaping: \ -> \\ (in pattern) -> \\\\ (in java string literal) + * + * Group 1: Hex escapes = \XX -> \p{XDigit}{2} Group 2: Ordinary escapes = + * \x -> \. Group 3: Anything but \ [^\\] + * + * Note that the \ is not part of the match. + */ + static private final Pattern VALUE_DECODE_PATTERN = Pattern + .compile("(?:\\\\(\\p{XDigit}{2}))|(?:\\\\(.))|([^\\\\])"); + + static { + + // Name encoding table ------------------------------------- + + // all below 0x20 (control chars) + for (char c = 0; c < ' '; c++) { + nameEscapeTable[c] = "\\" + toTwoCharHex(c); + } + + nameEscapeTable['#'] = "\\#"; + nameEscapeTable[','] = "\\,"; + nameEscapeTable[';'] = "\\;"; + nameEscapeTable['='] = "\\="; + nameEscapeTable['+'] = "\\+"; + nameEscapeTable['<'] = "\\<"; + nameEscapeTable['>'] = "\\>"; + // nameEscapeTable['\''] = "\\"; + nameEscapeTable['\"'] = "\\\""; + // nameEscapeTable['/'] = "\\" + toTwoCharHex('/'); + nameEscapeTable['\\'] = "\\\\"; + + // Filter encoding table ------------------------------------- + + // fill with char itself + for (char c = 0; c < filterEscapeTable.length; c++) { + filterEscapeTable[c] = String.valueOf(c); + } + + // escapes (RFC2254) + filterEscapeTable['*'] = "\\2a"; + filterEscapeTable['('] = "\\28"; + filterEscapeTable[')'] = "\\29"; + filterEscapeTable['\\'] = "\\5c"; + filterEscapeTable[0] = "\\00"; + + } + + static protected String toTwoCharHex(char c) { + + String raw = Integer.toHexString(c).toUpperCase(); + + if (raw.length() > 1) + return raw; + else + return "0" + raw; + } + + /** + * All static methods + */ + private LdapEncoder() { + } + + static public String filterEncode(String value) { + + if (value == null) + return null; + + // make buffer roomy + StringBuffer encodedValue = new StringBuffer(value.length() * 2); + + int length = value.length(); + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + if (c < filterEscapeTable.length) { + encodedValue.append(filterEscapeTable[c]); + } else { + // default: add the char + encodedValue.append(c); + } + } + + return encodedValue.toString(); + } + + /** + * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! + * + *
Escapes:
' ' [space] - "\ " [if first or last]
'#' + * [hash] - "\#"
',' [comma] - "\,"
';' [semicolon] - "\;"
'= + * [equals] - "\="
'+' [plus] - "\+"
'<' [less than] - + * "\<"
'>' [greater than] - "\>"
'"' [double quote] - + * "\""
'\' [backslash] - "\\"
+ * + * @param value + * @return The escaped value + */ + static public String nameEncode(String value) { + + if (value == null) + return null; + + // make buffer roomy + StringBuffer encodedValue = new StringBuffer(value.length() * 2); + + int length = value.length(); + int last = length - 1; + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + // space first or last + if (c == ' ' && (i == 0 || i == last)) { + encodedValue.append("\\ "); + continue; + } + + if (c < nameEscapeTable.length) { + // check in table for escapes + String esc = nameEscapeTable[c]; + + if (esc != null) { + encodedValue.append(esc); + continue; + } + } + + // default: add the char + encodedValue.append(c); + } + + return encodedValue.toString(); + + } + + /** + * Decodes a value. Converts escaped chars to ordinary chars. + * + * @param value + * Trimmed value, so no leading an trailing blanks, except an + * escaped space last. + * @return The decoded value as a string. + * @throws BadLdapGrammarException + */ + static public String nameDecode(String value) + throws BadLdapGrammarException { + + if (value == null) + return null; + + // make buffer same size + StringBuffer decoded = new StringBuffer(value.length()); + + Matcher matcher = VALUE_DECODE_PATTERN.matcher(value); + + int end = 0; + + while (matcher.find()) { + end = matcher.end(); + // group 1 + if (matcher.group(1) != null) { + // parse as hex = base 16 + try { + char c = (char) Integer.parseInt(matcher.group(1), 16); + decoded.append(c); + } catch (NumberFormatException e) { + throw new BadLdapGrammarException( + "Escaped hex value Could not be parsed. Found '\\" + + matcher.group(1) + "'"); + } + } else if (matcher.group(2) != null) { + // just add, we stripped away the \ + decoded.append(matcher.group(2)); + } else if (matcher.group(3) != null) { + // just add + decoded.append(matcher.group(3)); + } + + } + // end is match + +1 so it should be same as length, i.e. + // last + 1 + if (end < value.length()) { + throw new BadLdapGrammarException( + "RDN could not be parsed fully, remaining '" + + StringUtils.substring(value, end) + "'"); + } + + return decoded.toString(); + + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java new file mode 100644 index 00000000..3cd37a8d --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/LdapRdn.java @@ -0,0 +1,217 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Datatype for a LDAP name, a part of a path. + * + * The name: uid=adam.skogman Key: uid Value: adam.skogman + * + * @author Adam Skogman + */ +public class LdapRdn { + + private String key; + + private String value; + + private String ldapEncoded; + + protected static final Pattern RDN_PATTERN = Pattern + .compile("\\s*(\\p{Alnum}+)\\s*=\\s*((\\\\\\p{XDigit}{2}|\\\\.|[^\\\\])+?)\\s*"); + + private static final Log log = LogFactory.getLog(LdapRdn.class); + + /** + * Constructs a RDN from an ldap encoded rdn "foo=bar". + * + * The key will be forced to lowercase. The value is kept as is. + * + * The ldapEncoded value will not be the same, but rather a reencoded value, + * so that all looks the same. + * + * @param ldapRdn + * @throws BadLdapGrammarException + * If the rdn could not be parsed. + */ + public LdapRdn(String ldapRdn) throws BadLdapGrammarException { + + parseLdap(ldapRdn); + + } + + /** + * Constructs a RDN from a key and a value. + * + * The key will be forced to lowercase. The value is kept as is. + * + * @param key + * Not blank + * @param value + * Not blank + */ + public LdapRdn(String key, String value) { + + if (StringUtils.isBlank(key)) + throw new IllegalArgumentException("Key may not be blank"); + + if (StringUtils.isBlank(value)) + throw new IllegalArgumentException("Value may not be blank"); + + this.key = key.toLowerCase(); + this.value = value; + + this.ldapEncoded = encodeLdap(); + + } + + /** + * Encode key and value to ldap + * + * @return The ldap encoded rdn + */ + protected String encodeLdap() { + + StringBuffer buff = new StringBuffer(key.length() + value.length() * 2); + + buff.append(key); + buff.append('='); + buff.append(LdapEncoder.nameEncode(value)); + + return buff.toString(); + } + + /** + * @param rdn + * The ldap rdn to parse + * @throws BadLdapGrammarException if any error occurs parsing the rdn. + */ + protected void parseLdap(String rdn) throws BadLdapGrammarException { + + Matcher matcher = RDN_PATTERN.matcher(rdn); + + if (!matcher.matches()) { + throw new BadLdapGrammarException( + "Not a proper name (such as key=value): " + rdn); + } + + String rawKey = matcher.group(1); + String rawValue = matcher.group(2); + + this.key = StringUtils.lowerCase(rawKey); + this.value = LdapEncoder.nameDecode(rawValue); + + if (key == null) { + throw new BadLdapGrammarException("Key empty in rdn '" + rdn + "'"); + } + if (value == null) { + throw new BadLdapGrammarException("Value empty in rdn '" + rdn + + "'"); + } + + this.ldapEncoded = encodeLdap(); + + } + + /** + * Parse the supplied String for a valid LdapRdn. Swallow any exceptions. + * + * @param rdn + * the String to parse. + * @return an LdapRdn corresponding to the supplied String if the format was + * valid, null otherwise. + */ + public static LdapRdn parse(String rdn) { + + try { + return new LdapRdn(rdn); + } catch (BadLdapGrammarException e) { + return null; + } + + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + /** + * + * + * @see java.lang.Object#toString() + */ + public String toString() { + return ldapEncoded; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + + LdapRdn rdn = (LdapRdn) obj; + + return StringUtils.equalsIgnoreCase(rdn.key, this.key) + && StringUtils.equalsIgnoreCase(rdn.value, this.value); + } + + public Object encodeUrl() { + // Use the URI class to properly URL encode the value. + try { + URI valueUri = new URI(null, null, value, null); + return key + "=" + valueUri.toString(); + } catch (URISyntaxException e) { + // This should really never happen... + log.error("Failed to URL encode value " + value, e); + return key + "=" + "value"; + } + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return key.hashCode() ^ value.hashCode(); + } + + /** + * @return The LdapRdn as a string where the value is LDAP-encoded. + */ + public String getLdapEncoded() { + return ldapEncoded; + } +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java new file mode 100644 index 00000000..1e28a087 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import org.acegisecurity.Authentication; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.AuthenticationSource; + + +/** + * An AuthenticationSource to retrieve authentication information stored in + * Acegi's SecurityContextHolder. Use Acegi's LdapAuthenticationProvider have a + * LdapUserDetails object placed in the authentication. + * + * @author Mattias Arthursson + * + */ +public class AcegiAuthenticationSource implements AuthenticationSource { + private static final Log log = LogFactory + .getLog(AcegiAuthenticationSource.class); + + /** + * Get the principals of the logged in user, in this case the distinguished + * name. + * + * @return the distinguished name of the logged in user. + */ + public String getPrincipal() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (!(principal instanceof LdapUserDetails)) { + throw new IllegalArgumentException( + "The principal property of the authentication object -" + + "needs to be a LdapUserDetails."); + } else { + LdapUserDetails details = (LdapUserDetails) principal; + return details.getDn(); + } + } else { + log.warn("No Authentication object set in SecurityContext - " + + "returning empty String as Principal"); + return ""; + } + } + + /* + * @see org.springframework.ldap.AuthenticationSource#getCredentials() + */ + public String getCredentials() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + + if (authentication != null) { + return (String) authentication.getCredentials(); + } else { + log.warn("No Authentication object set in SecurityContext - " + + "returning empty String as Credentials"); + return ""; + } + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java new file mode 100644 index 00000000..ed94d937 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.ldap.AuthenticationSource; + +/** + * Decorator on AuthenticationSource to have default authentication information + * be returned should the target return empty principal and credentials. Useful + * in combination with {@link AcegiAuthenticationSource} if users are to be + * allowed to read some information even though they are not logged in. + *

+ * Note: The defaultUser should be an non-privileged + * user. This is important as this is the one that will be used when no user is + * logged in (i.e. empty principal is returned from the target + * AuthenticationSource). + * + * @author Mattias Arthursson + * + */ +public class DefaultValuesAuthenticationSourceDecorator implements + AuthenticationSource, InitializingBean { + + private AuthenticationSource target; + + private String defaultUser; + + private String defaultPassword; + + /** + * Constructor for bean usage. + */ + public DefaultValuesAuthenticationSourceDecorator() { + } + + /** + * Constructor to setup instance directly. + * + * @param target + * the target AuthenticationSource. + * @param defaultUser + * dn of the user to use when the target returns an empty + * principal. + * @param defaultPassword + * password of the user to use when the target returns an empty + * principal. + */ + public DefaultValuesAuthenticationSourceDecorator( + AuthenticationSource target, String defaultUser, + String defaultPassword) { + this.target = target; + this.defaultUser = defaultUser; + this.defaultPassword = defaultPassword; + } + + /** + * Checks if the target's principal is not empty; if not, the credentials + * from the target is returned - otherwise return the + * defaultPassword. + * + * @return the target's password if the target's principal is not empty, the + * defaultPassword otherwise. + */ + public String getCredentials() { + if (StringUtils.isNotEmpty(target.getPrincipal())) { + return target.getCredentials(); + } else { + return defaultPassword; + } + } + + /** + * Checks if the target's principal is not empty; if not, this is returned - + * otherwise return the defaultUser. + * + * @return the target's principal if it is not empty, the + * defaultUser otherwise. + */ + public String getPrincipal() { + String principal = target.getPrincipal(); + if (StringUtils.isNotEmpty(principal)) { + return principal; + } else { + return defaultUser; + } + } + + /** + * Set the password of the default user. + * + * @param defaultPassword + * the password of the default user. + */ + public void setDefaultPassword(String defaultPassword) { + this.defaultPassword = defaultPassword; + } + + /** + * Set the default user DN. This should be a non-privileged user, since it + * will be used when no authentication information is returned from the + * target. + * + * @param defaultUser + * DN of the default user. + */ + public void setDefaultUser(String defaultUser) { + this.defaultUser = defaultUser; + } + + /** + * Set the target AuthenticationSource. + * + * @param target + * the target AuthenticationSource. + */ + public void setTarget(AuthenticationSource target) { + this.target = target; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + if (target == null) { + throw new IllegalArgumentException( + "Property 'target' must be set.'"); + } + + if (defaultUser == null) { + throw new IllegalArgumentException( + "Property 'defaultUser' must be set.'"); + } + + if (defaultPassword == null) { + throw new IllegalArgumentException( + "Property 'defaultPassword' must be set.'"); + } + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/package.html b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/package.html new file mode 100644 index 00000000..d15fe6bc --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/authentication/package.html @@ -0,0 +1,3 @@ + +Support classes for custom authentication. + diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java new file mode 100644 index 00000000..e00f8f04 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Convenience class that implements most of the methods in the Filter + * interface. + * + * @author Adam Skogman + */ +public abstract class AbstractFilter implements Filter { + + protected AbstractFilter() { + super(); + } + + /** + * Prints the query with LDAP encoding to a stringbuffer + * + * @param buff + * The stringbuffer + * @return The very same stringbuffer + */ + public abstract StringBuffer encode(StringBuffer buff); + + /** + * Encodes the filter to a string using the (@link #encode(StringBuffer) + * method. + * + * @return The encoded filter + */ + public String encode() { + StringBuffer buff = new StringBuffer(256); + buff = encode(buff); + return buff.toString(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return encode(); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java new file mode 100644 index 00000000..4622da1f --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/AndFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter for a logical AND. E.g.: + * + *

+ *     AndFilter filter = new AndFilter();
+ *     filter.and(new EqualsFilter("objectclass", "person");
+ *     filter.and(new EqualsFilter("cn", "Some CN");
+ *     System.out.println(filter.ecode());    
+ * 
+ * + * would result in: (&(objectclass=person)(cn=Some CN)) + * + * @see org.springframework.ldap.support.filter.EqualsFilter + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class AndFilter extends BinaryLogicalFilter { + + private static final String AMPERSAND = "&"; + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.filter.BinaryLogicalFilter#getLogicalOperator() + */ + protected String getLogicalOperator() { + return AMPERSAND; + } + + /** + * Add a query to the and expression + * + * @param query + * The query to and with the rest of the and:ed queries. + * @return This LdapAndQuery + */ + public AndFilter and(Filter query) { + queryList.add(query); + return this; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java new file mode 100644 index 00000000..0c3ef3a2 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Abstract superclass for binary logical operations, that is "and" + * and "or" operations. + * + * @author Mattias Arthursson + */ +public abstract class BinaryLogicalFilter extends AbstractFilter { + + protected List queryList = new LinkedList(); + + /** + * @see org.springframework.ldap.support.filter.Filter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + if (queryList.size() <= 0) { + + // only output query if contains anything + return buff; + + } else if (queryList.size() == 1) { + + // don't add the & + Filter query = (Filter) queryList.get(0); + return query.encode(buff); + + } else { + buff.append("(" + getLogicalOperator()); + + for (Iterator i = queryList.iterator(); i.hasNext();) { + Filter query = (Filter) i.next(); + buff = query.encode(buff); + } + + buff.append(")"); + + return buff; + } + } + + /** + * Implement this in subclass to return the logical operator, for example + * &qout;&&qout;. + * + * @return the logical operator. + */ + protected abstract String getLogicalOperator(); + + /** + * Compares each filter in turn + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj instanceof BinaryLogicalFilter + && this.getClass() == obj.getClass()) { + return EqualsBuilder.reflectionEquals(this, obj); + } else { + return false; + } + } + + /** + * Hashes all contained data + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java new file mode 100644 index 00000000..20fc78f0 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java @@ -0,0 +1,123 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.ldap.support.LdapEncoder; + +/** + * Abstract superclass for filters to compare values. + * + * @author Mattias Arthursson + */ +public abstract class CompareFilter extends AbstractFilter { + + private final String attribute; + + private final String value; + + private final String encodedValue; + + public CompareFilter(String attribute, String value) { + this.attribute = attribute; + this.value = value; + this.encodedValue = encodeValue(value); + } + + /** + * For testing purposes. + * + * @return the encoded value. + */ + String getEncodedValue() { + return encodedValue; + } + + /** + * Override to perform special encoding in subclass. + * + * @param value + * the value to encode. + * @return properly escaped value. + */ + protected String encodeValue(String value) { + return LdapEncoder.filterEncode(value); + } + + /** + * Convenience constructor for int values. + * + * @param attribute + * @param value + */ + public CompareFilter(String attribute, int value) { + this.attribute = attribute; + this.value = String.valueOf(value); + this.encodedValue = LdapEncoder.filterEncode(this.value); + } + + /* + * @see org.springframework.ldap.support.filter.AbstractFilter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + buff.append('('); + buff.append(attribute).append(getCompareString()).append(encodedValue); + buff.append(')'); + + return buff; + } + + /** + * Compares key and value before encoding. + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object o) { + if (o instanceof CompareFilter && o.getClass() == this.getClass()) { + CompareFilter that = (CompareFilter) o; + EqualsBuilder builder = new EqualsBuilder(); + builder.append(this.attribute, that.attribute); + builder.append(this.value, that.value); + return builder.isEquals(); + } else { + return false; + } + } + + /** + * Calculate the hash code for the attribute and the value. + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + HashCodeBuilder builder = new HashCodeBuilder(); + builder.append(attribute); + builder.append(value); + return builder.toHashCode(); + } + + /** + * Implement this method in subclass to return a String representing the + * operator. The {@link EqualsFilter#getCompareString()} would for example + * return an equals sign, "=". + * + * @return the String to use as operator in the comparison for the specific + * subclass. + */ + protected abstract String getCompareString(); +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java new file mode 100644 index 00000000..069d8186 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + + +/** + * A filter for 'equals'. The following code: + * + *
+ * EqualsFilter filter = new EqualsFilter("cn", "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + *
(cn=Some CN)
+ * + * @author Adam Skogman + */ +public class EqualsFilter extends CompareFilter { + + private static final String EQUALS_SIGN = "="; + + public EqualsFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Convenience constructor for int values. + * + * @param attribute Name of attribute in filter. + * @param value The value of the attribute in the filter. + */ + public EqualsFilter(String attribute, int value) { + super(attribute, value); + } + + /* + * @see org.springframework.ldap.support.filter.CompareFilter#getCompareString() + */ + protected String getCompareString() { + return EQUALS_SIGN; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java new file mode 100644 index 00000000..a5ae4f69 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/Filter.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Common interface for filters. + * + * @author Adam Skogman + */ +public interface Filter { + + /** + * Encodes the filter to a string using the (@link #encode(StringBuffer) + * method. + * + * @return The encoded filter + */ + public String encode(); + + /** + * Prints the query with LDAP encoding to a stringbuffer + * + * @param buff + * The stringbuffer + * @return The very same stringbuffer + */ + public StringBuffer encode(StringBuffer buff); + + /** + * All filters must implement equals. + * + * @param o + * @return true if the objects are equal. + */ + public boolean equals(Object o); + + /** + * All filters must implement hashCode() + * + * @return hascode + */ + public int hashCode(); + +} \ No newline at end of file diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java new file mode 100644 index 00000000..871b8dd1 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter to compare >=. LDAP RFC does not allow > comparison. The following + * code: + * + *
+ * GreaterThanOrEqualsFilter filter = new GreaterThanOrEqualsFilter("cn",
+ *         "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ * (cn>=Some CN)
+ * 
+ * + * @author Mattias Arthursson + */ +public class GreaterThanOrEqualsFilter extends CompareFilter { + + private static final String GREATER_THAN_OR_EQUALS = ">="; + + public GreaterThanOrEqualsFilter(String attribute, String value) { + super(attribute, value); + } + + public GreaterThanOrEqualsFilter(String attribute, int value) { + super(attribute, value); + } + + protected String getCompareString() { + return GREATER_THAN_OR_EQUALS; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java new file mode 100644 index 00000000..36b5e723 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter to compare <=. LDAP RFC does not allow < comparison. The following + * code: + * + *
+ * LessThanOrEqualsFilter filter = new LessThanOrEqualsFilter("cn", "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ * (cn<=Some CN)
+ * 
+ * + * @author Mattias Arthursson + */ +public class LessThanOrEqualsFilter extends CompareFilter { + + private static final String LESS_THAN_OR_EQUALS = "<="; + + public LessThanOrEqualsFilter(String attribute, String value) { + super(attribute, value); + } + + public LessThanOrEqualsFilter(String attribute, int value) { + super(attribute, value); + } + + protected String getCompareString() { + return LESS_THAN_OR_EQUALS; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java new file mode 100644 index 00000000..41d46ebd --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.LdapEncoder; + +/** + * This filter allows the user to specify wildcards (*) by not escaping them in + * the filter. The following code: + * + *
+ * LikeFilter filter = new LikeFilter("cn", "foo*");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ *  (cn=foo*)
+ * 
+ * + * @author Anders Henja + * @author Mattias Arthursson + */ +public class LikeFilter extends EqualsFilter { + + public LikeFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Encodes a value according to the rules for this filter. + * + * @param value + * Value to encode. + * @return Encoded value. + */ + protected String encodeValue(String value) { + // just return if blank string + if (value == null) { + return ""; + } + + String[] substrings = value.split("\\*", -2); + + if (substrings.length == 1) { + return LdapEncoder.filterEncode(substrings[0]); + } + + StringBuffer buff = new StringBuffer(); + for (int i = 0; i < substrings.length; i++) { + buff.append(LdapEncoder.filterEncode(substrings[i])); + if (i < substrings.length - 1) { + buff.append("*"); + } else { + if (substrings[i].equals("")) { + continue; + } + } + } + + return buff.toString(); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java new file mode 100644 index 00000000..972edfa5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/NotFilter.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.apache.commons.lang.Validate; + +/** + * A filter for 'not'. The following code: + * + *
+ * Filter filter = new NotFilter(new EqualsFilter("cn", "foo");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
(!(cn=foo))
+ * + * @author Adam Skogman + */ +public class NotFilter extends AbstractFilter { + + private final Filter filter; + + static private final int HASH = "!".hashCode(); + + /** + * Create a filter that negates the outcome of the given filter. + * + * @param filter + * The filter that should be negated. + */ + public NotFilter(Filter filter) { + Validate.notNull(filter); + this.filter = filter; + } + + /** + * @see org.springframework.ldap.support.filter.Filter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + + buff.append("(!"); + filter.encode(buff); + buff.append(')'); + + return buff; + + } + + /** + * Compares key and value before encoding + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object o) { + + if (o instanceof NotFilter && o.getClass() == this.getClass()) { + NotFilter f = (NotFilter) o; + return this.filter.equals(f.filter); + } + + return false; + } + + /** + * hash attribute and value + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + return HASH ^ filter.hashCode(); + } + +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java new file mode 100644 index 00000000..20ff1ddf --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/OrFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Filter for logical OR. + * + *
+ *        AndFilter filter = new AndFilter();
+ *        filter.or(new EqualsFilter("objectclass", "person");
+ *        filter.or(new EqualsFilter("objectclass", "organizationalUnit");
+ *        System.out.println(filter.ecode());    
+ * 
+ * + * would result in: + * (|(objectclass=person)(objectclass=organizationalUnit)) + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class OrFilter extends BinaryLogicalFilter { + + private static final String PIPE_SIGN = "|"; + + /** + * Add a query to the OR expression + * + * @param query + * The query to or with the rest of the or:ed queries. + * @return This LdapOrQuery + */ + public OrFilter or(Filter query) { + queryList.add(query); + return this; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.filter.BinaryLogicalFilter#getLogicalOperator() + */ + protected String getLogicalOperator() { + return PIPE_SIGN; + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java new file mode 100644 index 00000000..bbd6b8d0 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.support.LdapEncoder; + +/** + * This filter automatically converts all whitespace to wildcards (*). The + * following code: + * + *
+ * WhitespaceWildcardsFilter filter = new WhitespaceWildcardsFilter("cn",
+ *         "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: (cn=*Some*CN*) + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class WhitespaceWildcardsFilter extends EqualsFilter { + private static Pattern starReplacePattern = Pattern.compile("\\s+"); + + public WhitespaceWildcardsFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Encodes a value according to the rules for this filter. + * + * @param value + * Value to encode. + * @return Encoded value. + */ + protected String encodeValue(String value) { + + // blank string means just ONE star + if (StringUtils.isBlank(value)) { + return "*"; + } + + // trim value, we will add in stars first and last anywhay + value = value.trim(); + + // filter encode so that any stars etc. are preserved + String filterEncoded = LdapEncoder.filterEncode(value); + + // Now replace all whitespace with stars + Matcher m = starReplacePattern.matcher(filterEncoded); + + // possibly 2 longer (stars at ends) + StringBuffer buff = new StringBuffer(value.length() + 2); + + buff.append('*'); + + while (m.find()) { + m.appendReplacement(buff, "*"); + } + m.appendTail(buff); + + buff.append('*'); + + return buff.toString(); + } +} diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/package.html b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/package.html new file mode 100644 index 00000000..e05a77ed --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/filter/package.html @@ -0,0 +1,16 @@ + +Utility classes for dynamically building LDAP +filters. Filters can be nested and wrapped around each other: +
+AndFilter andFilter = new AndFilter();
+andFilter.and(new EqualsFilter("objectclass", "person");
+andFilter.and(new EqualsFilter("cn", "Some CN");
+OrFilter orFilter = new OrFilter();
+orFilter.or(andFilter);
+orFilter.or(new EqualsFilter("objectclass", "organizationalUnit));
+System.out.println(orFilter.encode());
+
+would result in: + +
(|(&(objectclass=person)(cn=Some CN))(objectclass=organizationalUnit))
+ diff --git a/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/package.html b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/package.html new file mode 100644 index 00000000..bf83afd5 --- /dev/null +++ b/build-spring-ldap/spring-ldap-1.1/src/main/java/org/springframework/ldap/support/package.html @@ -0,0 +1,3 @@ + +Support classes for Spring-LDAP. + \ No newline at end of file diff --git a/common-build/.cvsignore b/common-build/.cvsignore new file mode 100644 index 00000000..8bbd83c4 --- /dev/null +++ b/common-build/.cvsignore @@ -0,0 +1,11 @@ +build.properties +*.jpx.local* +*.log +*.iws +*.tws +target +dist +gen-src +bak +mimedata +ivy-cache diff --git a/common-build/.project b/common-build/.project new file mode 100644 index 00000000..41d6903f --- /dev/null +++ b/common-build/.project @@ -0,0 +1,11 @@ + + + common-build + + + + + + + + diff --git a/common-build/clover-targets.xml b/common-build/clover-targets.xml new file mode 100644 index 00000000..50af58bb --- /dev/null +++ b/common-build/clover-targets.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/common-targets.xml b/common-build/common-targets.xml new file mode 100644 index 00000000..c384b209 --- /dev/null +++ b/common-build/common-targets.xml @@ -0,0 +1,928 @@ + + + + + + + + + + + + + + + + ANT build for ${project.name} ${project.version}. + + Please execute: + ant -projecthelp + or + ant -p + to see a list of publically executable targets. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + reading ivy config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + copying generated resources + + + + + + + + copying generated test resources + + + + + + + + + + + + + + + + + + + + + + + + compiling main sources + + + + + + + + + compiling test sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/db-targets.xml b/common-build/db-targets.xml new file mode 100644 index 00000000..06aaa0ac --- /dev/null +++ b/common-build/db-targets.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + User sql.src = '${sql.src}' + + + + + + + + + + + + Admin sql.src = '${sql.src}' + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/doc-targets.xml b/common-build/doc-targets.xml new file mode 100644 index 00000000..895439fe --- /dev/null +++ b/common-build/doc-targets.xml @@ -0,0 +1,157 @@ + + + + + + + + + + +Targets for generating reference documentation. + +Please execute + ant -p + +to see a list of all relevant targets. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/ejb21-targets.xml b/common-build/ejb21-targets.xml new file mode 100644 index 00000000..6732d54b --- /dev/null +++ b/common-build/ejb21-targets.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/hibernate-targets.xml b/common-build/hibernate-targets.xml new file mode 100644 index 00000000..f82fce41 --- /dev/null +++ b/common-build/hibernate-targets.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + generating database.properties from build.properties + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/ivyconf.properties b/common-build/ivyconf.properties new file mode 100644 index 00000000..f2d940b6 --- /dev/null +++ b/common-build/ivyconf.properties @@ -0,0 +1,2 @@ +repository.dir=${ivy.conf.dir}/../repository +integration.repo.dir=${ivy.conf.dir}/../integration-repo diff --git a/common-build/ivyconf.xml b/common-build/ivyconf.xml new file mode 100644 index 00000000..dcb9e570 --- /dev/null +++ b/common-build/ivyconf.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common-build/lib/ivy-1.4.1.jar b/common-build/lib/ivy-1.4.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..09b0403e34797dbfbe89c24706461297fdfe0248 GIT binary patch literal 571869 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
$Hz(QDInIXnN98F@=A6CkKVehs;L%_oFn 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%0A0ZYuBs2*$Bbj$I?Bjgjtp%w)ud>|G<4afKp4 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
%^`^4kpUxUXugI=<4 z;b8v5DE`Hz+se1&sV1a)H9lX*VK~$3vm0JHc81EDM}5px&aCxSOrA2oJ{SofYVPrq z35~*NvxrWHsnA0rt&v0;gg1mKIEIwMEJMlOB3JxqSG=XT&H6Tcw0V*Abvf6v{Kp>- zykNR|kcqXY2|PdE7)n*Ox0Wcu?)07B?*%l4xu3HX>G7BdHsnOt{R+>QB^|CVEFuL0 z6Yw>=A51fAn*rc|w@tWM1yF*(nKHkCGh+X{`LN1HCN@SEW(r1*j#l;-|7oKVoIr58TWcM-Lzjug=RV2?>Nb1!^P(@_%6}g-8i@s}-1d1>`fxgiU z60Uo-qc>;q=T^E{^tcEFe7=8x|A^IsQ(ciEk7%I5RH-QVP3IZdO<^r#iBNv@y;bc70(7ILlWs~R|DUG(Aa{44l!=*vO*W9{D7cg zcq;udLcND(7)Cq5=!_Vk#klz~s^fPBS2^{1yumdnWI4PcH(<14t-GQfXW%l@;mB#? zTJ5y3sOZ~4E`;+Wa$0jq1PMcb7#YobAy4@@!Ho&V%G#1pco%!jaFp#Rl`}&kPF{+B zg=^uSmI)|`|7}W8vo~q0Dth#a5E_wlgBwOT9uytA08=?y=4_65(ekl{@&)crWiiAK z^D$m6UrZ$dm6Bc-PZrG$^VM@qxkJzm@WwH)uc_qFiICNLqrz75aX9O$Yu^%am2{xA zQS1^%p5)!=t~V7ETexAWi@o zA+DHYj%5^pVXA*Y z4w80Ubk8VWFteNygcg!yX0$3`$ws2v=XP&7+=DFfIaDIOTxcLUkHyZX;`kp6KS}{s zobk%>k>7!%jk+n4kD)F`rmL@tYGLTxL+?Zoo$*Bz-H#Vi^7=1rvPdSF6pQXS z%K_JRUm!Q|IDbfVh8%GsQH*$_Wuddyn2w?i-(}BcmpoP{y2s6Nz)o2`&4K146?$a= zTV-4hc>dThk4c^tyowMHZHaY6-)*EL#cUw@iv%6>Nc+Vr; z&Jpg6fGw#9$Ga&7O3_u>cY>p_A%&L>>yuD z;Tp&lMidaqFI;4KIhdDv)jG^DgCNzLki{Cq@h!>oEg{u~q5O1ymS#D?0~b1c zi0}04EcQKps6>b`IhA!ASEliENLxqno;pwDS%|N(RQy7?Yj8Ww(sV~4Wb0x8#Y5)i z#yEmN9h2*T{1hG6o!fBeYR*6JK_z~cnIpvW{89UMSa&_KsUTe;g6h zqdZkNo;DsePo2VDi#wUheM6{{CK}!S(}5S}H$zdKU7yH&Kb$kdV!(mYbFFuWZumrTLH?=Px z%2M%=!@sDiroXc~=+N;$v^B&w?n&HB?u7Re^>nsK8Z1O4*QUFfw21}mz9jCtb+f8i z94g|_>vW~bL{9}|-yTIGw*_WKa8_ld_rs%8;vo1ajZG@cy)nc=*DS_@Gy2^uk8FNk zzmatHC?hm>D?jVzMbhjsak{X~)mpzt%+1L{F>T5e3r%x%c*=mQ7nK{2Qs$_o6neug zG^N7&k!2S?>bku0uW%n^u0M`$mvm%=NaZfUU6dJP(X+s6Nb$qWfLd`XO-JWKGMM*h zMg|(+Aw6epyB8-{6>}X)$FI)D7gt#P)8kr{pT$loK#h$A8h!5n9n{ihwvJ~18K1buD#N=HKp3MMHDZAKam&Ms;(80e&1d}`w-FT-awj^Km+fy8a^ z1YSli+-tDczx`ut8GxMcyCQ$(*WS+inC+qO|MuYxVh9(9eli#y)CnuWLN*|XS;%&5 ziX$fy%oLn&*aeQBu5L(|ZX7O*S_5;0ThLz530MizIzZS=b$pI`F%NvLy$}nflbLY& zJ)U_1??sGd(#Nl2l3p*{({ALj&RL6*Zfvve8gliEzQutlBuY~M&_1Da`T?z0yoRK$QSYs(9 zt5?74->cZCDTXo!h$J(Sd?F@r`-E!)h^DT{T8Mlymym_X%qZ5~Q4P57T?^lY`i0(~ zt$vHG@@Bf?!woT&NtB1xU}&&&cqA{ObEvT46wu0S^doxXCET%m&q~%fQCC36AG2mL zO+ltCe-ZlS*L0Pwn!=YaTl|~>pyLbKeI>F>P)}Jz?jbjl%+h{|<|uy(LINxTVhx5_ z9fj?X!=-;W2ss{-Q#45;3(e7!#?z{kFNX=V?ES7#alF;(66dDGkw<rnooQ1)3EGH3O6R)|3e1tEr<;|;qD28-fA9DFi3!%v(h_4gxx zt;I!Z1-LWwz$0Ji-|dd1v$KQq|9kHLeT#Au6@VcD3Se77cijmrG&xyyTuLTXHJ$~U z4uw`)14gwd9=x1RBb)1iYja#r%Z8flGqRr)EoEmqPHd7-6Ip$?Q0Vt`Y@Xk7&fLe- z^B?^0r7JXj!*AI#=kfV z+<=z{s|+@8j|X$_Nt7v<8O|$lDh)Z#o6;aluBph3YmngNa&s}4n>6pmLtu5PMr@sU zlH4;9OC;B~7AKzC0E|ss;_}yGz=*vKYSh}(eI;-8PJ}nIo<11OvuyFxl zG051-+e5oFXjemDsn|4g>Z~Ri32bl^6JCU`Io>Zw#(nNyZlt02syQ}o--doCkqaGR zChw?78m+)#saSYE5EnWGAPmaLYEEwA4Ma`EPH+4KKKkbqU=fdkS9C{-V;xgtH6GW7 z_mZ4yEe$@z*R7sL#6D1Al|~lzz($wcE>_C9Hf7-l^_uLYW!2nhiwn8WK;3#`+Av*c zZ4|jj8ybr6UN>wKi>G6AX=@y=>f@hE5A{CLX)KT*F;OecHlhYx?~d=*$=GeI^WTt$TAdki5LZ0W*SmfeFcwFv(W}QbC0Zh zg9s`SiW{JUMO(C_MBS1$V6$6H3moULTg<$@yzf(gm+U%|#Ck>;R=D4-4}?Xhl{aT8 zKDI(vQl4Fkj`%i-o6ZfJ$8nuZs>YzzvOIxLjFT$IX?Ar(g&eGHI`L(}y~x=(j^3xx zt_vHw-y`&jgFay|p^RG#x4{h+^POd{ha5)}j-C6Lj2#3M?0s4h^Z1RwMwy-dpV1`! zq@L(4HdkzOcO2*9-rX%EEmeos4D}{@alqol4AauPNCZ7Q&embixn3`eJa$iZ(iXzT z3c5}KsW|SFq=$yZa${|gT!y@EaOrI=ul}pEIc0bXxsa@1PI-V?XWaSv{;N`MiP_aP(_Oi9u>82=P?&qJ;PK(TEZIsu`tS(6WD5z8hfdLnI<~rM* z;!w=$mzQC;;yh=o-`<=Q;}JEHL=4G%4#^mNQ^*{XEWr8R(~A{gDZZz|9d}9BNFl~2 zm5|nXQdwjOUV>J)=dJ_KO($Veq7&vgG`iB!Zg3+B_rDtpV*tvFBp5iQ+`zs(c}5bg zpxtFEY$NvOs}_0t&3)zY|z3BWL^n zg}BLd*Kxip(}VJqye^*3wlxTHAxf9{rvt(I=$F@T+^Yc^d;EJ$<>(aEDhP$1_3_u@*s|W^o*mdc4ln=s=c{ zWE_q;iik<0^EE;$`#=GbeKHsNzHN>DhY_>xzNSB#qS_Neu-nY`@oonU*j706qsFDE z!#CGo`O7W1&c!YfH}<gw(;_oY~6V%LMq&XliC|ucO zDiZqq{DbXt(|!Avi+qM()Zf^nzaXC<7Z;xB=jGAyv&D=yl)-@Oy8_Nc2tzugpw;3t zBP1&CvPk7KUT*6X;O(MHLv$Z=wHoCtCE3|tg^~zELe}1@4^nYOA$ZR^6A^FlCGtcB zhL$+M|ETp6uuKc-ximztP%VH&dCbb_a6d6!446kwPtAR17|CO>CAJutQ-{G|CQ++m-qKwBD`2H zF$C^T7VrYr>Vud&Gg}*Z8M!!^yZ!|y^Iv%WUtH~gaQ*|RiaK!LNl@OHPLLX~ufc3Q zSl5-WQElKhdlCzTUb2jGPtNRBb%*n>;%TW3BJPIxI5azH3XqCOvQY+go3!ejNG(&j z$cH| zg=ga!L#6!mj9laX;a(H1EaUVHtsEmA)D4f_cU8%9NI0*E_VN~4$YL4Zj4|04!_b#e zI=g!#prrqOoA4#z81{j`S^yNL|MAydERCGaO#hWMZG1?NidG#i?W~BZ_5%_FY8&xA z78=4Dl=DodSnvdG)6>)xKQ5lj>&XvMWw25Vd$sg_qzZqZZAKE5SJ58-*2LF?yQkj9 zoQK~z-{NUpv;?U=r6FD^K(68#dO^x&eK%5|V-0~?R1|=5!PYGfhk)jMroe5=Ey)17 zOYoGLWHy+q08P<1AoJ2P(0Cu$SuVyc_jwG6cVU2W_&NN7l7Njx;O_Hk%4}&8^{qLp z0=~VmXK^DGNnF2~t<&_+bKB*WlV6mMi_P(T6|cLEg5cyogfoAkM5gB);tAX*FQC&- z@;{*T|G)#vilM5yfF|c68>AX_=Q6GuWt;K?42TM6hSwNxF>N_qu_SMcEZw5Wg|{-K zH_3%JZH8p?i?X;Iylj#)ThbpoXP41Az3haq$(dp`m)UOzg9Of;$5iG=r&Jaoz-Rft zkN?0m22W}Q{|9tSfUABOW*BJ#uJ{@lW^nyCs|L!G>whH)fm-p`4Fw~6An)*hvJHvr zvID^I;!^>6P8)f#Wyz#^M7uA%HIgKVM7>+NE5%O!Je4cZwEDgp1EUX~xHk;Vq7^k? zLDa#$q4D$WZYqAJ_7NGxXGNAYFhylhMRlYif)o9mic8*>jly1U%N?hrQekUXGpZBu zT=u2kj(}y*L9%orzH-U0a;#I}`fR=+*=^}`-sM)gO^k?jaD1J+Na*Hr)T)6__joT~ z&*jZV-^R*e=BOI~65b6t$;pcu4Db%>umDplOvD0;ZVhqGl3{X@cGn(8TiG#XjXl?l9<18#ipzt{&nJp{4vKf!aoTDfx>9s ziiY7O31LW@6}BY)H2X)EWP*yk`c`jlvn?A&psCu+FECRUg#;t0)xbS$93{V@jL|)U zTceuhe}$URARz4jP7c0Ud77Du|4SiIxAQ=k z#PFwDHC>njqhw_4YgP4<5uYHVu@17dVw6|_p$&q>q#mQl$u(=W@JJGWr~Ux@dB&Tm z$~&^J_5S-x<;oVzI%(?W+U#L^)8f)Em;Z4(FW~b9|GQi~l)2MtFJ>2iAZ}Obeg!CE z8oQ@~pRn>om^Cf#eP`9aHWsj1cOZk1<`VTchJApxrfU@*PplGR)o#g)ha4j&VczLe zHtC-gbiq8Ml8z~#jWekE7ERrCtSONW#SBtE1wOVm#qj<@(BUJ+ku?~BQ`d3$N8BdN zR!W>$jbd`^O=`s5&3(iyf%b~^g9pD$ndZ1`?K(=@JPkXaC9dtmo^>RK)%E7gnuQiK z_PV75wK?qw_w$Wi!d+BUI}ukp0OUXsweRv}1ojAwXCq5u!TfqP>aug!Qm7N6gsdX6c_DRcnq(en@e|lSRr*(POO0OWg z!S@=!v+pAf$2Xf5_uz!c^1cxYDF^uxQctoY%TzsmCg|Hi?31yy`4Lc=d^9P_uxlsj zD`H_rrzvY8yYpY)oClBvwh+F=QovV4QHLEU*Dq{n72r%0S--Ex*wMY@yQ{Fc#raxD z@wggAg{G_EIw4l*5(N<>5kt>FT=t41YTyi^iakmy?<ok$nx_kso+;Pm>QfI((ytUU4c4RN}(OL69pXj9@0A*vS^e=4@nufm!&-N&h|FsBqL-gYg0lq8Y?e5 z;t`yl5lk}$wzt^*Vs)WKshYTQRc+Ss(nr=DlIZqirHg$DFl7Iy<2WE0cAF(dW$KcA zFq3dEi58F&Qk!`1CbmJ^5_!dF+#pRblNf|SY98SPYQ^`hA1pF|{6&t_O_ziKo)ME( z^hT>*B9-o3@@s+^y*fe>#xl6-=`1fX6&Lh(8jdO7aPMP-ziWGI-Y@17pq76CuYY^$ z%LC~j7uSDMcM8`3;Db`472x_=P(rt#uyr~eFUCX9OLFr`U?Sm_SO85W$rzbmPZo7O zL69kj^NR7euMLF&&zEuMh#~+95tzY{rxji8Vs7Aov7y**cOeH`75u|T+xA~}+D;=O zCo4JuOItL7xTN&j-<)P@XuCM{m=_=AK9Z}JAW#ykn>(g#+!guz--=T?*HwuWQ#5nq zKaPjkzCu5l;y?v{!THGx7c-E<0=s?>`}cpY?mfci0Q6-1ff1+lzdPst^*@(!_fm8) zH4}AqwK4}XW-|8X4*$uGCE5H(u4GjotA(EAF-se>iE$hYgLy8UCZwoDog7eW-jS0^ z>bCq_5&yMNoYXRkkX+4eGGofI; zTLDyCZZ8}-*|q260KM%>?&8X9HZ3ys_4>{c!7Y@&ab9IQ3KewXlV?1!6tA*}x6CRz zl|oOZ&qPx38}0%|@lzj!g?8WP@YeQ)1O0(jt-yP{5Ek02aY<$0z|bISJh)t}yRs3sav?^$CmX#E`#KaH%>YCvpwP!Ru- z)xrcGSze%tH4YLz4o6?t_X`4gfcHm*H-)aG&hpH=jtW5wviH`niFVLJBb-9gpY|Fu zLn-V;eupJ@YiLK|x2a#eR6|PrvPLo z2N#JJvsRdjMi@&yWKQzAfldu3((yS`Xz&tW2O+!~H*Ix?Ies{>OPJkf4Czj86cK2f zMq~7lI0YS)60uhAYjKQS9t~1pF-lZz&kK+&ES4(9e{6)c`9md~l48|kkZ0p0M54U! zEwb;a*P`KT(bA(`&Ejh0GF9aS5k8h%H1VxZos=)MmAs;CHr#tc*`KrpX06p2Mo!Cg zWVBUU)XP&Ze*P2FYg6-}zXSyWvWg4>!tuWr>i<+`t!EGP5yH>t_~w=-9G23+@1SX; zUks;9`d|&^L7Q9T?Z9}DC~d6Fuu}CbJj_sdeGX3iT4&>lnrLORz@1lkx^8dL{c1nO zKGG=izExAMY8!bzWM$+$=jL6p7Jddiuj+xUJMqU-D01zpWJkK-DDGHAkM3qbDDJ;H z^Azr^^5ErDvP4$t9v;ZXk;m2ZO!voUA0Idhfudt$e06H-)np+WVG{t>HAConI^(D) z$KQnnMX6p7BoqU^O|uCmLbD)n1a*@zVKm8hy^2SsI54x%P6axXfE!*6zM_&PElf z=O^IQo&UW+$IvK4piplXQu}4v3SB#`{F{j$1$z}M+E6YF!@xRq9m%Sb7|EJkHCWUO zg4_%SQ}o%ilijcTjEgGs+*tx~f9Ncgt13~O*5#GN=ISmh)9&7~t(``L#wK8I{xyZM z=ig~d9GY*NNmb1sq7o8}+mA!Bmup8MLME`)LaH`m-@QF#H2T;lYxLJS{#044XnIIJ zwfx!*Ueeae6`@E&U(pqJlqO!T&bBv;3UlQ?$Jx(ioQuHAy@X+?R82pM)#Qtbv5B?! znhdiY%EJ5;9hD(O19ooRq-B9kn{}y zhMz=uN9~eS>EjnjJt6KaI;@?Oa|PR~EmvrfCLLkZKwgEhC+^-ib{2-1u~sS0?vZ7x zRu9gvVLQZy>9CU?lvnmd>tC{W{1h5wQ1OK6U%kiuRNXtyhnv6W@zfn8T=rC0^p0Lr z))q+*_ffT{psRMB8u@dlmhL4%C1KbD<4s{`+evR{XJAp=N19sY2Kg;Xp#&|BXk;#u zjc2~K_3)Y*l3Tqi*apnz3fmU*YHu6t{8$DSQ*WhaPuNqb@0CudH%xxDot5Y7=&{*W zD^}HAs^6S7eX;$z{MW~p^0o*aI)I~YpA?PxZ%7f!coyVft32usa zBk}+mQ6M20oLYTy@hLkE)K$@8xotPpnqc z-{MxEg;=~}wP}qhD_N>QVefxA#55OcmxeV9!w@QPZ47W##x7${;WD_L>Sk^>2o^Ek zueS%4BcGuIGyk3+#9qZ~JH2TRhYIPw< zaANwEDB)bD%0x2->2ag)WtX<8**1M}cz$z7({hV5(?W08|7W@<~Ggx}aP$GE?e*jUU`;T12m*0=9@Om06`yjdeqNTxSC z3j{LykA1jfgz!wY4Y}Py%1LSIQ3zw0_EoGTyKD|wSdx!QBss1J$xGzuI zQ-dC17&VpjXxxonXZTix{xA895FlFblTPCPY%hmOG zv^Ma01#ODBtruT-O4eh@J;@9M1tV$4r~3(3%6)mHv6VrcjEwzH?o6Q=B{YZsf=vpkgg#l!Cvrg)t z0djY7bXlDaC~?#|@XQyIdCo-p{v3=m2OI0J1t>Pt{IPB=yZNB-5LwAd9CVW!A97=mxk@ zMu-_qq6)YpFD?z;K`ql?>c1s&X0-k4=1vAEc?8J9H=D8)cWK?u*aNl6rN0T@aLp(N(q6>AT|t*E6HC#2>Q9E zzaDfr>NOni=pewfqvxibXD2vzuqwl}0DFu}{_Yp0@X9s0U~9F%a1F6p#u|k39>14x zmaBLU9U^n$+Cuf7uUV8BW4E&rSoF&{sp%xxyggOCzn7&d87aTGbWASA9BAaN{5s$m za)_E=%r)MpFPf6M>n$m4Dl9eKNljq%^g-OAVBXE8`b*eP=y`;RGX_smv!eeFHkoC9 z-Kau`xA4zS_Fg#T0%h01Ys2o>((F~Qksb!oocb(983OM1y9YPBDwT)IT~dOh{@4;V zHvg(!YEQ`lzqY&;wj)_Hl{uEcyz!?DfYyymfem}+NM;J0i?e}ezN*~^fx7UWrE30}ZpFEzq4Nd9pu zBNyI4bM6w=0l<9A^%f{@&6N0Q>wU*ZC~frwzQDP32ggoL=@5L1RA$g?g?nZFM6PM} zCNq$CgN?X+oeTK6=fJkL>_}K^^VQ_~yiL^3f5TOm*-);P-n&e95MS>`+%EN9ag>!W z$Un7QtyHH3&;EA&2j`8{E7Lm7XqFTc_;!jkmj)-Nukf%V!*D5$1h#$K}2Rk~)5XX9|sIIAM03-;^-_`R3knhvr>~ z?B)c|ICK*4U{q&xBgomFkbmzC@5R#tQM)TIcbP?*pgoY^-sreJ!R_};UCb`iD2F-h zGtOS}l+gGw%VA=n02M8hiLBbjK*%)>(G99FQNezxlvNB~x}w4ktMImrHX;h~A6ziw z)AwamhY|JnMS_BZ(061gO~zVQ0&<9=ES^~OK;}~#N%NvgRaO`Dy!iMi3Nr3`oqjg` z!%{)CkH9`%*8_5%Q;FpHjaR%Q@h@M}BS_6dfn{eSk8>iGuU`9#-ii`BR1ub8h_$a@ z@(?^HhtOD!Z=o(bLcx#G>fKI=RYyNa4mKykDGP>DKGnl7eQKK7dh*Wju5V!6(JlC# zIA!Jair@5mWx7HH^!tu)xJt^VC0}M0UMI7QvTM;gsZVvI6&VvY(Fe04xktUnufi6w z94cvMYYv1loyILb^=|JWoLXakx)|x1pXQwNq!X3MFW?Gq`fL{wX^Wb^TEn|dK60Lu z&jq7be+?Ew8w=QjA+RaIG@^@UnZ@1RF`u#E7eH+v4#c^$w8;tJ7RlgRH7e0oj4Fl)M&F^qV zOw(Rv4(+1z#4;$@v^$vjbA`2hZ7YY!^mNsW5*W=aPN{&S7dWiIJ1Mx@V;3xB;C4m< z|E9GCg0})+x_^Y&T!8%Sk?pVrv|7*q+{P>lujSDV=qthfPs9+g&^kyK4t;HHl+ZWeHENK zS9TL-QA1=eu4z6BO>=m9g+)qw^twyb5`1O4#VAO!^E!dgA)(){RyuvjhAh)K z_yq#z9>+cZP`>aNv(vcwc_;@2F$0(&`nSH*-+}x)zo#yv2CM}8z)O_Jf$GEg1!Ao$ zlZ>*FvJ;7q2NqfIgNQF59gsOWn1K|jq516tto8-E>kLx4@>ddcK=O+>+Fa1!Ja3o3 zPk=+l$HV&oHHf%pnF&4AT0*}e|2&TBK^=gcFNmjNHysHPJdyx;KZH+-Zlat;F^sk9 zAUYN`Tjih%;KE17Q@anwWR0`v7(vQmyjCJGF`Fr^$PV!(hqrGwgVQddGWD*%d+H9$ zitJlyZ?)BBrfdy8xbxOM4xmAjySq27?HI#sO;=YIo1oJ&12Q8wk%_R-%_)1mi(&&o zJdIvpL>uELL-L`uv3O?vP%**om?`!XnUYqqRk0M|1RA6jpF7p+SB2u_?nJTQS&a5+ zzBuj?@}TRr%uDxl&aB0bxCH^G#N>!+v0y|Mj#@y*ulgGQWyxH+AM4R{`lo81bA`RA zF001AH{OGpvKea~;yR};mm{PWr!G4S;2g@HWTLJb)*5_&6gBz}q(K!{R6i$6pbQjw zZe3_Py35U*s_v;hURx+FU~241oAG9(Bs-41t|)N5t_$XD>_ldyjA(StlPCSTnW9| z#w*xkpd?Z|C7n>fq9Ab%iC{3X{=M>@!U$lFF8HjUynOEV%&FKrKH@xz7K~~98 zB#8tG{ex!lD|u2dYH0z(q$=K^> z;aYrSAzd8&yX33MUfdDiN!B7B;(y6;-jgbNs)c+-X%(raF+nCWAB2C; zFmE?+vL^6pdfH-_tN=LKEkDAD<@GaNWkIwEB~8y2Fody77Cu9W$Tm9Tw4%1x`#y0KLj=nE%IzONa7ols#mQG;LcPDuC6A zx`hrK(M*da78;IiBicBc-JG&Z^BPJAZfh?mBs<8;mi}b#Uhu>m=ch&-?TvT4`yI7+ zpfv{#(jRemNKUNmjfTE1{`aY`biH3zUGH5=*PsK~Dblm~(gXBDO27d`tcfH!K_&pR zxq}U^h*_9-l*AubNTd*+!KX^-I~R_AamPM-%;>Rzpx=6HjPtzY+o|nP6Rr?UsBe2g z(7Kl2Z6l>$S)}QU;f7EEW9%CP;ZjL|ELAgVVcyBO3g8XM23zy|dU%3Np-E76f_Tod zY2(;?p%?abMccd|!4r@(=%w!^BDmcV+oy4zSPR9N@U-G=`WCQ10WI`26!e~<{8J3* zhzw4`a(Dr8l9V%7{TRd!NV(Q9NUwe9(yylw8_r+Y)Y8JavA-3ke@n~njJ(BpvQC_S zieeWdjW8#55hGPI{_DdXMx$eJd{}P0Rero-V?1SkJZ^n_YQ0WzdNY1VS#JC{?xVSX zA~0Q$Hich--iafyDK+!I$mINo-h8pLbu|OlBLP`Ec`FxJGyDHjuM(ryXAgWrHrp+m zM=`sosR=Q3K18`LC#W6UNwhk|v@fs%O_y$D6GCdZhJagDDDen1L8i(jI)a&l zpcOo_U3?CGAE3rAwAss?sAL%uy$F$GLf^!SiE`tGGKDT>ixOu{e}cp;XbI4%RUnAu zxI>@4(8EmVSDF3{w0EY~9t9Ve9{$#X*8zVyfrnZ+LdiICugU(xC-RL6q~#5})Q`3} z)M7ffcze)Hi$lH0HjT+zbfY1{U zoqg+g^zJgfIH;iIskaa-cdDp-Y~U>|+e$_6g(GQzP5qKK|LQsX<(2;Xed_Axx8=xR z0wMeg^yq%D>WHoM#JFZJ(|sv}l4$5?_%tSh%^~FphknB&!rC;41&(6kfp}r~DP$mW zNmpb1n&A5Q0jSrx0q$bv2+P@{JonDpG#2D2TY>Gs|lqD^1hI&KQ)l9+ z-s<#BE}OfwW8dq{qoSqOCQ*y=f-}0?b|Z&im)UTp$t2gl@^`Q)(H%~B_VnIN6d*fp zX{hw5kI2!@euf)q(qak|{=yVn+sVk&^TJ7HDdW3UT_dDyZk*qr0)awsqSy?;LXVGn~$c2AHp z6NcVK_`4pl47qv9 z(&A_JZOn+fU1upUtmHBuNfHU3m4aOjUyEj%YiyB%^Z?Vc$UEQJ`+9A-X5TBf1sY$( zxJyuPI5y%Pj?cC=kU?9?ZKlcMXSr>zETw6AOkK)ss<`2>b32#L{<;pFlUvbjmDSeE zg&7DARiQn1`d`#%C#yV))f;&n+^r2T(U|0tSu^G~)|KHFJAu?imIlg1DuOEGeup%V zkq_hS-%EH8OMziO%hA@rd4ywKeOKD~C%h<)yH8DNr9i5@Ee%^iYtv?iB=qJ3dt3EvR%{~Ff&jw4}-8yJ!&&ymd1dEWGEVA^FTRN9EOC&D89{>`o zg3beRIC-7X%I8YKPUCu!{Wkb9qMN>_L#ajtFGYZgD6Z=uI3<2Rnt#=I6COKtzg2Gm z;O?uh2JeM(f>9J_m!PypU%jI^rdOy3!sOw~z>(pZL<6~QhLKFe%P7K?!m&}12~(IR zaavHAs*!}uA~C_ta)kl4e`JRj=ZVkv)bWRhI85MkT*5UB=2?JaB?8YlB`hka7n(Nq z+J(5VjblNzZEKWWS8(xK_P`qS`{M47nh0~RriC=V2SHQnUQBaAvx_I=Z^-=&D?*6N zb5<%hBDm7cgKh9J@Wd@cJj*L5nN(!Q$L>yO0JXS6!SF5-U{+5jrAE`EWTOkqIKdf= zY#5w!#c)XC9P~g_aw9QB96nngEL4wxq=AwfU{i9^O1TKduRQ!&K*&b2)RyFAA7Qhg&ERJ`N1`058Ip1OXKtRf`2)jvvb)L zIQQ0eUH_#(_Yc>$%t^Al{^AUWUzcI3|Hv8s8|(kc9sax2DN_C){c~Ptp3Qd9X7RUD zYY9OJoH;N*LM+av6bWkf7sk&$ zY>Z6~m#(gOzcI~Fbqfh&bD}6;5BFCFQk9muMsOp_NX|>LL1BW!mJz_ma_tb>jTi93 z(f3KWp?V1N9K_qnxbrhSh}2Qi27aY_GR=s-3xM(nYQy-6HH=idL>3Qp@tZS5smJ zLOahRL%7i!CPn0rJrFPDQMlUfq~#F}(r9>$Azg=bn}3pS6Wkd~a+vHMq%VtL`nd2 zdG_3DebLk0Ut|~dU-O2EPA6<}U$-=nFQ)MSZ8;48#TFDdz6!(OKCP}sR~}=gcE8`^ zFRr4D;uD171u&(>AbA$=02u5(E;j}bC2BTFyl0vj;pVvn*DVFf z;t9lWWTs|rjoTPMzMf4*6Mkb<4aEyfSe-Q=6N2x{_bnmo9Ui2E9_yBbf~B|Ej`d{+ zibmImz9eZ*z}Z5EdVj&*+)f(ns8x#T+)G47CkQMgr4-;`@h@3-X{o2|t)iD~A4&GK z2xfJwP>)NRGgZHku;_3?=#)^-P}dK_cbimW3Lvd$5V;FP(B`PL#81MSiXDTpQBd*E zDDq;jxhL_@DzjEt;dUEB#C+Juz1F$Q#bnAgcW{Y+i<(^%(L(P1X5N=}1kQVOt1cCD zU`~ZtSIT6)rZ2OOa>AMX%dT6Y(nOzCRn5>u7o28*eCe*t3- zK2M3fZ&=Ne{JK#cuavGpWLXQvUP*pcU#nE@zF@YZa-m>vw)!bV*Cp6DCIH_WRcbpo zDq8C{0WBh_z}dL`qA6vwmu-GY6!tp?b4II_J?wmyPQ!bG$R68_Ks_itsaHt8(X5lv zh$N1WQ6UW6s3B~&QK#T1g6mdxM|iuhOS4!T`mldO`O*Xe zoJHNj;`)0mjpTOVW(hSu5GZ2W18+X7SZ5M~ra2{_?;wg53S3=(|C99fTsM`Met#)Zvtuk9RX>Wk7GYKgX2`6Y9mSIAY| znWtGV5>#I(!1D2yi@K+#u8t|5qv%iX7D!#rO2}&hqHNfq@NNE|@Y35vXV6G{NT6;R zDBT94-D;xej8xO=Dc})o_;slvh;pPNYAQSQgR3UM&2SF-8Ns83G}#FFqzL7iwge;U zQhXqeBpLSlaSc^YKY9m&=O7 zKG1@74e(XtQCAbGaRm5{YH;AE3;#(>8XL{;kGsjn6K+%eu&I9dEE{AOm%cf$CMv0N_?Jt zIU~AMBx3(1xkxVjRaij}drX*+s<|SJ1mR@_cvFT4l4=9Xu$~}SXiZg5oN*lv70$=;=qRi;b00q#l?3KJ7@(K4-80| z<62=y_FcdmEW9FKxYIKzN2m1ueog938o&hH`pVKEB%E8qKo?&#I}JHx!g@<`U}b^$ zQMTX*p=2>J`+h^_(r63-y@K&#ww~cQ`S>r5Dd1h+5(`qK#u3GkQ@PkAjK$i=G0gYE zq%(+jZB5-&UKsM&m<4#4iNfvj4M?-njBm$NReOG zzt$HO;q-j z{<~CF85e1b5ezbrLors$0H}%*2Bz4B$dcf_Se`oybC-L?f|(_O27pb&1=UG*rG*2= z*BHvgi%abJ#4wtc;&iSf`*|)Jl(PmM!eT z?tVtaB$7Bb%zZQ&6a1bjz!*tj2~cU4K)aJO;pe`y z%`8Wg9<$>Ti<2JH|HSdXk7A1)WAnc%?g+$R=Lh^L$k^+cLe?o%b!m;23zf+Sd$B3v z%O+D6yi+u-mEVok6E6}qapcct6A+b!^_={OMG%11)>_L>K9>^MF!F|pQPpeR!LPVN z{**@Lm{V2cn}T_rV9s(D*&c5(%tj|%T}Zw*iH=9fFnT+fKKx=}I4Uq%=hfkwrjGjH zYWQ)=F!A}XZe$n3;UnkEeJp%Ef7d1WKY^5g4a7M`)j;&}!3mi#AL?74mk)?wPHn35 zgQN$MFiIOA?RAR7UQ*W9bUB@{b0O_-DqJA{6&?mI!7C17&|=&{o2U@*uoVG+Z^2DL zsdRMvO2*z0urO_IB{#CO2o?<7+rKp5B@KYzUG4(bA&uw#ud9Uf2;0s3TH)H)L-_Ul zd&}rQSNShtdaG#qKPwdeG#xibx&cISUTuC{gb?T!psfxXsl_L%RztOChJ@YD>5o(o z9q=?xdHSS_KDvO>^{?rc)g_97D@@y%bU1h{bhHEyKcJYXpi(SL<8YaMRzAGS{Eep} zU|(9rvPZ|LXWuAd(Re1{CYmPPNZLCH})&E%J3i8XlUbNZE2%tNGtSTAN~>`OH{D3 znUzKIrV&JwWzkbSS}&ZF%AqUu9!P;J8bP3&LGMh1q&}z7vKR&F>zWlZx%cPo#x>%4 zl1JA_ondP6x^#1!WS=to`SJPz)J@1WLg0S^m1IXMF|>i@Y%7!V25~`ApFHT#gu`IC zc_SOfb0roOsmxn1^Be%{-&sH4s?SQOmi|efDLIe4 z1oW1)Fr;3&-_CScD@nAw%=v5^5l<62*0k+L=puR?jNSh!FXsB|Do9OF3ej|`7d4MdBn;nWE%@nnu5 zHlj|l@?Azs7d!pb-gIKB%cn#$^iB|05LFB6iVYyX>PGbGAaZz@(xlk{Xss_W+` zP`AW2wC02!giXXYx@LUz8K`((N}p#`04p@r{x!DpP+4H)N1)da-IIvf`j=5JC9Bk>{Xw+3!?yXEp zD@2Fz9KrmEDtF(u%~lnMJZkMbtq~*DqYsv7E^?Q|wB-l=APcXdRx4Jx#yRc@ZJ3Na zcq)m2eL@%wxlGSY$pZhL=O!-DD-Jz2?i8Tg70T$tX8MjO?8*3Vdi%^BK0E7tte6n| z%dv%&ENvf^ND?wy*K$T%5S*_^ckzL26C4(T9-41yI7?p zS$*h;CO7R-)QGscYyDp#Q3l#((*cgll;xfw4j%d&azohuO_j>fDO;7HBN8_Ad<$7T zj#Cn>lWt+bA9MYc{jhJf%#yCl@yE1i-L?-u8-e@A4XC2KlR?MjwvJ&h(N><1aCML| zJWCHax_%(D^E*klXi8qPA@j>u5Q8ymNrLCe5JuDTDrwMT6^XjHmX;C{C3>N70u?M&Ro6>lO9SIyy_McDon}H+nFW8nBAVqE`8m&z-EbIgRx>Mi*A6$qMHzon6USN@was66#;SQX@ghl!Hc^4)LTW|+Y-Tf@y? zsKP%M#$Fsp%J2?gFu}8&ZoP+%8Ztk#Ig8rxQ)pxqS4I~Rdmq{IHpg=pKsxU9ha>{U zPl^?#t6xg}w6hKXdtZY}`Q0MrjN=nl+(u7~Mo&Qx>P6J7VbzQ2O?N;;_6^564X)bEw(< zz$o+-O{)Ke1Dc^EE`e=H;&a&pRkgi)@E>+SM`gW{yAW)2Zr zCW);uR9kJ+3+60&JN3(+WZi(f0Mh)J3=Q*SH>an<3Sv;!q)7g5&?D=P9m)npLZH8V z2}5`kA>)Pxlei~SDE*@yc^1*0j$2wTA@_Maxzl}edyx@@_q2M@j>WzTo;GK_%Fc1i*nd=sjn;B&ulh@caZG@aefMN)8YYcBcYYwru zjm#mTIZkcY77Ln8%<7N~>QKjBG7FTkTxWx~@3(02-dJ&_`<`)ql8hrI?Qg@vM9Dgt zIHTDQBKAjGj+*KaY)BLosB`t=JiVSloW7n<`=04`lKglG@^*)TTSk-1t+LJbEKE>; zw2K>u-2!pTNwx))r}jpI3SQ-a)ru)oLIbmAM+c}@aXuIevK%P&tVOgAA#(~^{m{;_ z{0>219NoUnvg-G$;gyN0;k87+ckmaR6oY5K-5=P_;ho6Pol?Z53FSc^s`!|u!W`gk zr9MgK`+Dl?#D>xmF2yBWYD;#k)K}BI{1e0nJeo=5=6h+YNS#hZ8lS6N_U=ZN!Oiqm`^VeK+Uzp0vMuGj%O-*2OnTm>yZCaVL1mt%zBOAG!U8bDJX zQklv89nkyyld%=zg@eV^thfFLfFV3T5)@+A&@pjjXQmIoNnAUI-~G3dUgMw+JlSP; zk?R==iJ8>fZYX#ug%POP{R&t}x=`}&I)(s-sk9uF)*hFPK&*N8SU^#kYjfP#=h{2$Rd6fzWtpV+P`hIf}@_jI_ zEnBJ4pvZxud-wM?TGP)jOtl^N1iEw!O~W3G67opzyqR^iV*_H*b7OX7a0%-$sZt?@cf znAp{Z6}^>FBj*6rc;aoF1E)$(um#s~nPTR&v^yj>U3;ubzVT)`4ZXfgYRNSrKrh!N zC!ucc-Zu!@GAn565E4~^T38QLE=*HWHrf7!TCLwgqu!|0r6YVdNv9XKB7!@_6CUO~BCfBu*VLckcW?4&Lmns8|SkTE(LVb#^?PDr7iw8eE5nN@RZC7aK7d>!{{C z-;3CyRjHS6XmKySFnz--`M}@BOhbN){z%5k`P8n^qVW zH#;iF6ZmMON5WAjR@Xf?=fy#Ml^h-)C&UXNLNcw;0?3dM z0y5kS0X0Q9I3bMgfc)!kg;mBUFwObraT{jwA0VG0(dM~mp4T&9C7?Hx&N*p~%V=|k zkCPWIN9$k09>4#gBI&lTBuNrGs0fHrsAMQV+$*XFS|_$omrT@DqOUzbh#ZZ~C0E@I zw>EZV&3GJ$SZ1DTG{(&W8*tS;R0ee-H3c1T5SFV{X$yMrP-3DoYG?%Uqti`)p}dTy8~qCz$0-^@Up8G#>mLMhf?hz_khzLm)&4D5|OT)iTs+v zCGcd)Y20cliU{+?N+N(OsJrZ$co)Oc4Fbx%f0t3x(VhfKt8s#EVP!=YFu6kl%b^By zMTBI{jWqtd9yl#FI{RwlGCR8%l%R<=p1qtL`x``F4sJNcYj!a6(h4%yLUn)<2qi|A zo>EU*(2?rWH6UhWU5yc?CwtfpVHwu6%Ly)LZ?&zLVH@3yaaelg)MvT{dzC__Q|Kj? zQxm*I-F$A}Lke%9!MP1u5WK#1MXP~M(HvjH(n}^e@~P$`BVRjp7Rf~IMSJ#!p71o9 zq=`CH_DDRneg;kt6L+!}+9343-;Qx}-Wt&lhT1oJzB9awO+sm2Je%=jOO_`PtwGy! z#@0xgoDN2sZuuPd4)Tc-9lj8@trK z;4)x$fg@Y8+y#JGu)aPx=9|CtiT$zn(%L-Nu`l0#`sLgIPQ~Uw+52CtJW)Z*2H{H} z8we7qbvmh$!n=`~o^Rl$hczO!Bqe2lWS>h92d0GjZjfw*g%Xs z1w;_@bz?GIGi1yhNu2=35m~nIeZ?O^J8~{aH=!xvs?kueaqK!7*I5xxDZ^QJ#X=u$ z*?@O`_?5H;?P7-)1=}?^lL9Z|gZ^YG7}yP4)Gmz}Zh11NQTH(zTgRZ{S>rTQM)%4Y z!Lz3eK=6;kNUFTh?uP^+=+E+AsiH<91Bpl2%#x`bEY?bc?kLd3y_bmu=nTn%LH=h0 z4Evz!k;S1Gl#YlqQvgUqv-k3C+BW4JQL`l$_fEP8m%s7%Lx~Nqi#S*+6w9NXu%5|s z`=?*4wtA<3vwpZ-ujpJ3J@n}u3^Khg7is*;3y$H3c0=l}KIFoPN=#loyEdbZXT`4{ zuwj8MJGVPyWSB^M0$+iJQOoJ@qq;B}t<>$K-d-UHUPRe0r)Vt6ZE&uZNL_68O{Z}| zYzkS)yTh<9YR~9I`DNiP^!QF&+YYIW9oqFRp9snY>-6&9u&{;2;-}vi7JmD}!oSl{ z|5w}izko3FzkqNq$=d9DEFhpCn5uZ2Cl$r+4|rxjaIrCTn@WMvuZD1Zj33iE+B7 zxSZICn$kkpKSwVy=d&9*Yt9rr8DE9RG18#U%6&4&W>|S`8KJ1RF+j`aDzF$q@OO7D z+AXV3Q-F%gLCF=FtG(dr?3Up*q!vDBg>#9gWuxR*q4dPS(LVk_%z$C^ajvO!!hX%OGPOa3SKVBXWaau>di!*`hW|}990q3AHj|qT4mPU zMJJ2oGp2@hLb~as0B$O4P$iQZ{Rx8xKYF82!*gWG9!q})#hq&%PHdsM9wg4a@e^L< z%NsGYZXquK4Z-2qLv5oB;aOX__TQjcV98Wh?vM{Laviz)A`F3Q+gt7;_pN>okI`Xc zi;M<+>sUfph^K$D!AE0?vtf0ug^#1zooO~xv+=w&m-;0O85rUll|S`x>$4QBD^s6O zitQ0RNQioqggj)0SLX7-!eI;;eXsme2tQvZ>}t)VR&a?CX( zpJ;D!$V$le^22uO@OI0$hwXo}>~m5M?CmeqTlqr0ziVs$Tg(0nsyk9_qeYO%UR<2aLSd+b_p$*l+I1kjR zI;G76WK65JO4in;N-y3ma#tl@nYcyL$d_XT6xkyL0rqg=sjJ%ULRLdA&U=Zcpwzmvj{$zgKVMb1iij~Ea?~@x^ zeI#XGrw8_fgy2B!F~kA*!s%8R-8Es(54}+WOS2VbUz!WnkQJltndy~M#oR>?O9-!_ z^v-Hcf0QRoO^G&Kr1(SaAgI1~VWI@Pha=C~!3Ol0mn_X1G=vNY|14{{rUKjtdP7hz zroKrwb998Pp=!=7bI>9j#O65V*+sD0ACE0)Np0##-!sBCQ4KNBE$K2oUUcX(B0AsJ znD4?FgVrB@Y4@;@49|V*!yt*xO)1p!%hf_RJUNps;4eZsLV~$HuYQi`SBOZjWe&@x z3O7^d+d&M)GWKChAHaI3S>d{+U+n=zF=Ig|xvcyBmx#un9X$yfNHPA}(Yr72#{3^M zHh;IHe*uBa|K3Nh74@=*_vK^pGXqC0__0Ph4> zMrT3=WFx$%*m#GjoyoPgF-jkx@}n9>K8!K;^8M=3m`*OUEP6!@ARN1?qtdH}^4L-x z1G0q%h%a^TiFa8#!|43D$CR9wg=2J^?qIHI?z0ioV=bXR_1u;DjcL>(f@8E7(}t1_ zq9MyBF(ECN(603uam^rDmtM^~P8~M2*1mTZ*4c$Tj=^y0ZJT4n#}EifCR6nfShO3 z{!P&JQ5z`JSMJx5IDJD06$$9+Q zxUaqX_J@)DdEtFMf1ghLqrgUEZu_OS`S0SLALU5+TVESb_MhUSu3tS5hI;yzMzliz z)Fl@FpKrt*jjaAz$CDVh_7xZX>d~CYVHqUm23`dPgsvw*3ZTr_2EoUNkuR7|uWvct zDBMh_z`|TP3*$jiiEZ8na3$-Huo5m=%hi{tWBi=-+{=8p;^qAbusqP{55i@qdte+d z6+EE;IYng&PSw7U!*T^&x`8U_yBa*K0vOo|v%t@RUh*s(1t_olIui;N#IT5ksz2em z5Zayo!S*=0A1Ikyb94U^Sk#G${F<@vrD%`}dN?P!!fHN?cHH7w@5 zO$iRjVg+jyGwU7y3KfyhIPjrKnY`ap?NK&4wBDM9EzE}n$>vWMDKl>}p*k1U0HX2~**u>8Jt2Dkk7V?>TE)RTLX=EEMFJ`%7-Cd53*^~F3)9KA+7#5ibqd=3KGLjriJ zhH_tNxClTiydtRv7Oc$~=#l5*aGCiQt<4*#QF+iBuF=VYN=x6DTPRYyo5a#1%surj zq;wVCg>)+2?gD*@rum#ZAEGnWdC=`Q>c3{NQHwPi7r#vH&tRy(ZJhZZ1EKvpTd|6k zvi>9a_v=MW+(#Zl6Ce=UcuNUYSRhwF7E!WWC{%#Y*l*ih>;4+RCh5UCHkJ54JM4l+mVj*2m6Fgs>oO_$`c5Jv&ktZ%>CJwr=0QqU}9N-gw?RKZsA z^Tl`)g<4bVE*Yb@**LrO11Gi+>#GcD-INOtc!%zWmAXVK!>aP@(G=0XAh2%KDva#TCT zv-Qzg_auG$`fKasn=N7+{k^_qPbL~5TDSq08oOlwbg0Ze9eJ=!!9^WgAsu!fl<{73 zcng~QbxZxkP>m1muBwnUj08kd!HYJO&Tgk)6;e5v5Q*g4Jqd{4$b2cEX<@q=Sp9+I znrdajZO|Rxlt#Vd;V5QnLn&wB`cfpm&6p#Ih&{-UwZ$i=Ce3Rm2Nxa2N3Ooj1nJd{ zyaPXzghObHA=}!1N(`K6EU(c!EJmFhC_tn5mRg1RNAaY?Q;*dfIhLl1tJAcCHDRkj zk+u}61xe(o`g&ro;F#Y1Pd`3M8=rPZ9D;%?Hj$q7_|?hmJ8rDLcvw4*(f$^!rBB!q zmO9g9Y=iixq=z`e<%Rt$ANeQ5W2^2Ia*d>#om8WA8ZD5y+R65v`2C+o28(3J$YY$T z3FpE{HKIrzBHDPP3#HadhSVupJ7A8i)x?c?9!9CwZt4ilPIlJg!2Wb)U$X@3^u|+b zuMs9nPlF=LcdaxLj@gXqtJ*X?JwRX;JtLKnEnJIt;c?1TlhB1kAgGXum%sYJ;7xhoMJc>}^179FatN}usyU_cHpgrj zcgp<^$q`KT2oIpzj;&s}$6upo?YokGW$g=;syPj4%D8a3Oe8e9$4SlpPI=c`(9>8K z-+Z`WzIGqfkeO%6yHXT&EQhZcyhUohXpx@EzOyNNmuXUQo=Lr- zWeo5sMf0?xEZAwzuM~ zVKLhy7x#%2y#P?yc(+jRse2XnKE>+|z_P+rAq}|xyD#Zo3|&~lR|cLjwh0MsVvpRj znfvZZoKu|GS2_H-JqFf`aYDaIBSAp!bIJemDfzS4~ zO!J5w`P>W{m*8K;!?Hln;9jYM{=B&HFtPV%ptCADw&y0t7N*2CV?>Gg73h_yq9O>N zF*|E^L!>mg);A%~1o8>Qp;PmrP4c~P@O}w&5tvTkKkaGvBw>xTbDZ3o!P~B1Imsep3_A+;H8CNrr&>0Y|%>7%iPTbr|d$dLK!5$ld54W z{0<~coth&ZNHF!>q?5_3hrJd-eHXDEQ(=r;Qv~}-{Pj!3P9VqZzR|^$qG!dpFMB`# zLjL~LO^9wIY!BT1Ia$M^ZIa!L*4{2Yi1q~i99}c_)q4aIka>NKU*6cYE zy0F7->II>~N&URZYJwG;fcpiVYrAC5HF8ujnxpsZfKNC%rlBw%%8dfoyao`%FMtY^S=}2B9QH>B$Go$R|aErGTDpT6}4*iLcxe zDt#rIEwjU@eFHz8mISh&EWSThlFGV6D>8AZC1B%T!E0Kz(#T~P3vRA`bj8%a7>N9A z?6Hdofch(Y+Abif6wpUN?UFMQcGMdvF7z#B$6w`}1%KKVaq#dD zCj6tK#ZcW$sKvP+caaK?y+YfhTd7NJf)Q9(d2bjwZ{Pl=X7x?I!Nh2?kt5 z?X!rI#q1*M7sbrN9Xof-B9S!Z*?Qf)yX$3uP>cD^81pF;9#I;AAHrQZv%SLKfR{97 z%VWELp}o{-NT~};Q|^Or)rDsmXw`8Y2_l9kbE91C{@g}3xT!a|G1duB763o^W|PUe z@=MaKGVT?mMSIH$S<6pkOBT%_ zEBaFR(YH96-7?%56>9KCb5GyRG46qnZzS-CZsC>JkL^S4Dyb&?3-XUOZ4HX84T^s1 z`Nj+!VrR%AZ%V1=;@xm_g?W9diqk+sFN)FaH4y?5*`IX{{J&Wo@jaYz&<&jf9LG4D8Kp9c}Do_3Ryt z?1}#Q_Rq^ffhxGG=7Q5lv~m6ulRLvB*ho?h|7JCn8qOZH&2o~_3QCfp0XpOg=na#5 z+~D{il>h{|ge~f9AW;FpTmTVMHeB`qImQYZfB*ueM0!BEwS4RJm*2OVBbJg_WBc^7 zVG$#w%8>bW*>Od4wCOPU^TXrP^8%H&6Iiz*;}$PK4w@V`j7~WWZ?beZBM6n7%+7s~ z*>log{%G&6)ODn9*J#0AxDR#onxgZ#2l+YfyUyT?yyP}z>4OsSodrkdWsmXik|&L~{68&t)cBMk52y&pJKLpsN3Nv8nw1Q-}EGGa=$r1@Wg`P`DohJh^cH^Q9&=7eL>ln+keJ9U{f|3cbSFkmm|WNuP~GuA%e=2S4D zUcf3wQq!O}c2X3uCx^I2?69v!pQP-1PGe}$-N*U3%Vu7L22Mh`hE*tteKhJtE9e)0 zF=k4dl=LPG3%smsE)^G>s%*X0nkQ8+V}_Jv1K|qWD&$AltD4;pRlKy2{zmee8MLQx zVnCDu?O4*ri3t04Lk~PG(Q`Opiz2b8w3=q*yM`6>{d}C-wkG8It@_Cn z%K^fXl&#gqQ?ia}q?3kuUqHPwZuHX{{U75vMpQNy{WhS{X*E8t(k|jYpVXR(XkfCD z2uEOmdBj+a`cnLiI4Y+XDUICkrURx1I;NRdvP6oii3etpWNc|D=N`#}*&ddPE&8We zl*UG&IJ{YO2BC-9$hE!TJyH#Gc1&eBxihRt5U;z3F;(^H9yA$xG9Fd>B6hg2ns)87maRbG2M3gQy*Yv0g@}ym!x19vv80c% zDfDww_+hi=(X0*i#qZ(2fvBQb?J(E;fu*M*o=BI^#G!5!Bpkqq?=?aT$A=Od${;ca z4`iTf&cz+^^n|S`FHrV}U8|_O+5Hv5=fnQd@ zPe;mX6P;Skq-GEzvsj9#Sv0~SxHtwX#ez{QR>^8uXGw2ZCX3B2m>y)AjEPiSTW_{) z-L4}0NrN`a2c?-TD~w<#<&0LV;9R1>gi)(;ylWwvO-lWhGN1C3ey#33f&br zde-AbZhpp9g2fT|t}iz2LzM{K>ZIZ%oT#sZ+1FNz2|-@t0zZXak_hBAq>-Gl*x`rA zUQX2e_vo0Zl^Ww1*L+#2H0Tw|H>j1W;Tj^tK`T`qMt=Z|xm)NKIT$!w(utJSj)fQ& zGg8yJFbp)I^+8**uO7j0;=WM6VTS!|EQWoOgP;}#J&IzA2+dXw^iD#o7D`P69WUk} ztR$GhZ274eLi@T?Hgi$Zths#@!PW%sby5uJYvo(R_6@!vtoXg4j2I2*7O7U~7A;9B zcc>eQDiSWuU-y^{*_B}+jPU;Wq=7E4uMz}A2Bp7UHQ1b#3>J0TGfxx9{nG-Vz$Jvd zgrHj#^n>~XbGmjA$ZijGGb|{`#RNgEGLG=2FZJ0*V}KQPdCZ2ZYu7!XS~NB-w$0pd zy<%6QmQYR>lSOd6=-s+wJodFgJquYmWh9!QT4bcIQ`}n3&3===I>e#hpxbw~>r}t1 zwD>T)@l~4yg*VlZX2~jY`3H>Kk}#$)HW+NQP1qpKBo9;w9d@G3OQX^&xbL09%*f8Y zutV1aGIdy@Ruh_QiQTo)NkbVO^US&m1j0ye7$kWO@%C7nczUNx$iB`V!*N-87uY!t}H;#sg zs|gK!Cp!ecaUtiB_7(lRHzkfvr}KsSDVrGXk<(G`rV#6#nl`rILSQ?yL$BK6uPJXz zNW9$ZI^zf8Uh7d7cY-)Ed=#mT?wLT2wD%;3n|q<%)0^H*|H3VEDA1zrQ*44VzEkcc zv8g+7V=sO}t*{b?%4X>neK7z9DJ{C8POlWZ{`8FG(aV+Q&rF;*2zWQOhS3qTb-q`v zz6@OizS~XC&6AG$2Oo5sCLQW_yL=J#@Xv3wFNgS?sG`M~WfLb3-?H+~TLHDlsD8D_4arFJesI1R53(t9ajj`3`h|<3 z&&|ynC(=Kb27At(%Q87+olQUGYo!b$%{qgERc2^0l@g68c9|l-`6r<(s0b02dhdjS zJnyQ>#ek`U2G5bK*ns4X`Xk>E-L>-(q*gQVqR)U~ns5muVM6luTd3S%AJlB!-%R?r zPocJNqrq?_%E*u(EX=2Qf3#U>KopACiR;&(@CSS=-U@utG%ge6ZoNpmQf!mXKQnB_ zkzDdjUSr1Hah@ou*1EfxQ1`zsvBe#GdwC!Ud-)E0dOGxMkN!h$2~9K4cBzK!&;`7! zLGIWxsrCe2SZ(7}4$TRgJYlKBhkdU(w`>RN5Mq#y7Np7|zHRnhO|ktRxOAQ^J@L|s zT+?lonhxW$KHimgtjF%7as5rj zayv|!s+asX#`@{;vlAECas}*mQ*nyXpVUzdwE=W`l+}`gic?sT_trhohQ%8k3 ziJ6-e%6BpftgH(-Jr|oG(nHW0^4z|Hia+&|<%2&}ZhpdlqW&6Kuuk@XT8hYRl@?*| z){mt?iPo)2%M_RZrf8Qq9ju;DDynIqGVzxpGjYQzU<07F9`IZbGCCH)mQ>IG9=u(2 z*ue%Gp6BIg%e#R&yz0wg*nry`%tqsU)@O;lQn6()X4Hf;cr~YutG70xHpcz|h9jl1 zPs-(+_EWrs)%Vtp>gu)$#G$+pjw3b=Km4)4ZxAL+uE^{iEZ1~#I|kQwr$(CZQGe>V%wQalKJ~P z=iI9E-T&Nst83S;-qqDr-OKA;>v`UL`j~2D_q(XdrZvrJP8#5ln}}wLzhf|hr6GS+ zS0u+b>`G1$l<;v^>IONe2lR(K_y+{2qgOe(NNHP8WI1BTE57EygZT%;%7+A$sfJlGy7HQI2`wkve1ho28GZj z-k7I)Z>i$NQDN`xp5;vfIcJo7!5w}XeFwvC@2cKS;qb}X#>m|6)n3}LquIFQ9c)$J zKoXiub;TVmM*nO#LFdx;L+4tKVXkItHVC#ymg=g}eD+?gbb)t&8J1uEQ)8z&OEJXgS_g(1IfhR5%rEt(R29wd1M5j-Kjj}tH# zZNvP=VmG9jCATTv2%!s?eKvdNA%U&vQ1~lpX#@m>rSn_6Rb7>-t_NgkznW9@537x zb=&C(uWFEMptjY^ir%XiE(>;c_4W!Phz5&XPWSLluao17di7TB_Au@ZjhDY_sL~#& z!TSauvMa{gJv@8E*xuOdhTWn1Z;d$m?5kDBuhSC^{!BnD=w!(T%2PEn)K^2Y`Bsewl)^B!_%rxG%6ELg3Be6uSUthzSD{8qQeT~rT57;-oG@*@v z6}u1#In}Oo#p?eXhw)z}?6%Fu05J>@&@TG_+|T+yOW1$auIlD4sOxB7V%4iLYSN1! zAV@gym<@c& zI8*`3<)l0K3H0G%3RFK-E!rbCVlCQ39{?l=Nx1)P^9%uPZ*t4gIGzn!F{b_FkRQn& z?Y<2tjj^rNgU5S&eBme30MC6L(9hV{mAzh%{E*+E8sU(nJ^DkCq`Z^|!N~k7u`F*5 zA@LC&5<}u-KC}U=Zyh1c$oOe@(9roQcM&0ghf$6EM zj#@)1@MVsYL#EL2(iw?&TuAC5Ba;05L-rgK| zw-=W?7#sc;1pYYK{A+maLlh}7M%j)OHL>PHx@Ab~V@qiV7G;a{1$FiLOzv(N zFt8RLYKvr^TJf(gFR$WWudo^`zCu{)Lzd#p!+cUvZzU49dkW_E>w3W2(gLfJ;;nF^ z-zYdjf6to4V@Y3L;IGDMX-zTFts8<=VkzfF81h6Rse;>BZ#xW2r0SZ<@-Uu6;{a6v5x0^lpjI1%1-nRdg} z1{G0)5zH%?ro~1DfH&5#pke~U!h(t(pwnErK1N}t{^%&OW@6R~a7ba!e0VQ89IG<1 zZPNhJOt(Q&2Up=C=W38QZWW+96|*+uG%8t|D=@BjfRYQE%m`q6tgNCYo7zTO(9oJY-u@vln1-8Nvk=1sEL}zpvEzM>Fep&_7;?y8|4eJ~R>bhdji6I3uqP z?Gd+-fRpk@mA0}O6U6T$@n8`xHe}B(M&-1RA=s|lx&dboHrhXZc5;vL50%L!PQne23EfAmYCVkhvpPRjw`}yv%&TX6IjWKQt?t*zXGGeob9-i)I)DN z`B8;$@AiyccBK&|NLL(-u_>!nY{ooV{Y08x?k^L3+GZm@o3eTJUN8zhsel!ot5mF| zqikI3luo0MiVz)xtInFcqgo?|s+(SHBOyU0H)L0;SC|uH&6GM99Bzh2vAh^kV@;vD z!BVA(FUv!Uzg(mO-Il|&+{7)}g=cp($mc#u4zBY;EHdaWvjJL$*fNC_zW>m1Ji`P} ze|@p%IhVOM!y?HXc76mN3+I=iJ$aaDo|vqF%V3cAJ5$qAx|gC>6SbXlBcpuAdFsT) zRVlU%%XLj{md&nhB7?1Dd=fT~X8wBGtMH_+y=gIkH0X_sW}Rhz(q_0NDQa$sA=|P2 zNr@^q&_TRM18p=NnptiAriYT{rDoWPx^Q7a;zVr&i~6-BVEnRzhgrw@Nv4`NWmmXFauMKCa!-Zykj~0HlTgc* zdt#2acb2h7@E1s_GCw?&&MY*ORVOZd)AUvxTRVA91B@uneioh&NgGR#*Nv6I&)WT2 zuG*;vO{YJ=5d1*yM{Y1>C#1v6BSpz3Yigy?2oOuRL}!q%;l1Qe>+`%@?b@(DpD4EN zEbOk1$?=v6=MlHP7_DGQ-%h$BT}pQ^JS$BO4(Avb(ety*TYnN1UaT?_%R3<9+ksT! z8?AYAzIF*_MV~zg?f&TI9u&R4!++)E7jUhtzJWt8$S2}s&7(BF8Y^fkK}K2F*5H0g zkrTQR{i!$dlVgg0^0IL~RWP2>xN76aa%oAXH+Y6H^mL8^ohndv@e-!yoKcXDz}NAg z8o+)i5Dg1Q8|q_&0>0$MXiYfX?7n2C0W5H~baW|LuS1rp7(EpW2#T2shbF0Arug{+ zyiD8+_0`XG%Fq|XuEx^{nAnck^<4Ee1nV~Ts`D)2?;aq(0G&|b?rsuYkgU4zqbEcP zjK-!l8T~$$SB(#q=)WO}hjWEp(&#BO#?RX^L{$gyOsk&WT`v9s z*liv;X1AUY8WOXAu0FNn@F6ZpcW0l?eyQjM+~W3vKP@&#Df>smuorsgWS`Gge3ec73F3H`j=Q5PqS9F{mu^c`a>3B zjMM&*61w$fVK#CH7>skD`2=zev zwoZjR9_>jeFE~i)F?!kXg%8Vz|qn}BmcqfKAvcc`q< z=LkbHZ*=eW-BzTn@>QR29!;e%EwA;+z?MDS+C%S4c=szBXro!7U@LBI+VYdP5TqK6 z!2QXMIcUWM&tgFGY&#Ib&JA3jY|@cHKT{$RG}LStbeg6Db1_3?Yizm%yfC}W;Stp0 z&aL{bZf%Qg;l?i_)m-u1o7I|wLAfw$OYPLi)YkeCy)mgY-#Tv$y*|X3=$8(X1Yy00 zFMdP_>v1OllAJo~H)#y?m+TPfst9yHBgY?Uvu^3L<5tK*yG9T2YH=TyC#c%a0Bs@b zPxS`75e%*GoJv?-t`69-EqnR)ruiIiXDk%&T#b=P9A=TKIX`A1=roHaA}_HTTbD%b zodU_e$b5ip3%8oCqIDBwWBea!pNZ{GSLkBied4{4hTz(icz!w}p`lhPC|hiq+Pv;F zZn1`MI%hu@;&sY$x|rKFQ?2aVnKdLAxao%6`mhIGR>o*J5e%~PMqYP_<-W3VpVe$i z>UP1-7bsT@+Ecyn+&`4l6R17m-ES|74j{sdl*~z$AMg|zq6d;aVOfWqZ<82b)9>64Tli}0+LnqF z=eHg7%Q}4uFS8UIO`yjevxy8j^{XPS4cA2vXMWbN=um7^;-XBXJAZK!lOlXn4>)Qj zh2PlAw-QU!kv19>VmQJ=TZ%D>O}K4EB;44DWPG_}{N&fCBpHv#2feSh{&3X)qG8?0 z>K*hzM&II}i^E*sD34+&I9Ot7Ie1`s5*Ix)&o%_nm{4GL97C31N{Y3RFa}ak43n1> z4aT*^{bty)I%dW&?-eD#fWLXb1g<5u5Cx+Z6q2Yv=|#cyOq0pbAgLl#-aYIHURjU2xkD1>j6ampT?p7 zOXUCJ`&99CF#UJg116{Cw*(M^O|1sNXmLNGty$-hG6%D&tYH&m)* z5<>W^Rw886#G>UUyaN($&CLsyX$Fiq@+bUvSK`ij9wt+2LF|XO0O`WR>5|eoa7iyg z^><(XgW#5GA4l$oZeq2>r}h$LU3_X=TMFsK_;a4H$HNT6uO;=F8$VHdM%Z6!y=0&pqxsdy=SjI{hE zhXbNpVW$Rot`M*N?SqWo?zCaYkel^dGiiR5-591KaIIo?xUVU>)s zs2Gz#)lb@J0yIVQ3n)wV<_ozHWzJzmx*93KC!41R*946G9;b}`gYQX#=I6A-D?lJ> zlyyt+74g}W%HU1fu@mQbO!BQv&rF6c=F7ihx6O}cSZ*<#y07aS))*4ZI|6L?uC&U9 zV6ryGKr-zTZj{Penaw)atdx8cS*KQ331jfj6vrOk{%t_)uaS#11kA=jfPcsZTqOUq zpZIr0;d!=S=ZAoR0ELiqgK%?$KoEmy8#y{!2|^ZwP=wE~8EF#v%o*u%@%>X$vvP!N zJxeJDQMdQ8RCJ`$K9i#&2H*xzO#-ytlqM$#v(-xSQ#CR*a`M%R@-@{e^C8k!!zqnS z5Cu3AViN-s10#XKFf}o;GO#oRXd%=HCr1V#{@Xcm%=toOA3)`)0I>5^|JN`0_p!EE zRo%bF+IBcHO&*xY5DB9qDr@O}Q7dY-vI~@=+H4|PNmjO4;U!68;xcn$X*}HISH$-{ zDOOnz4%MxWccpzFBG`*>xZx@Ek+Ark;C;h)n&jy zu+KtOAF>!P1ZDidSZ5?ORgDyK=ZTu!QD#I90>55*;)S}L5qSW+ogmE=mEA$+Udm{u zsK!)&&?eBq`|41pQ6;mBB$0L@=O?3C92z|4Q#HLdm4UN>(S|%1I~TP zakfj(l_uL-Y>U=`NmXl+AJPsm)_ z@+YfR4d+;`((9i)eJwXxYJDbcIvd&V_yZd&M29K1nqsSL*Jk@{n9I4nU@F7RYO!VB zs88EVF!l>I8G37d!Z)H;F6(KozpLBG5;&>ac9}3aSk+ozAaF9<*K@0E*eTYWJxEEI zL&AW2iVvjW-5KY@Oj%VN)Q7b_vdeSAz_*RReQT2Cj_af1DcPr?m3sY6jc@UW?GC;~ z;d1o$qx6u2x^MLkakr8%j!cDZ#h{|X+Clxxs0 zRqIwDpcD(TT~Dq}4nI%u1t(%ux>y_!##>7cntoE_eDA_%PAg;W9bTNfVsSo8WiiOS zj*r3_*J$OC=m4O8nf@-7uh7V=mq{xxyXW5>0wa*>GfeW^rrJ)<(}DDyQiholFoQgR z=HTy{W;>(mW*kwq)*tYePzrO*65N{WADVXlPc%m{Ofy1&Y= z@tYp*46fVQrZ)mPhV4E>_Xr{7-~&-lxe92C?)dhdL`JoK;1I+A6k#vV+<~!iNH^i! zNG8Li%a9yb6d|1{2xL%tB0a+clW#?D?-Q(7%p!4b9QvJPV9Qj4@(;TOPU+mZo6a_Y z_EI*qN%?O-@x4fn{oujT4!ws0-;aNDV}HdyHWxW7EkNv(1B{@P{m)K7&i>yWS*W6} zGzeflvbnCVF3YTP1CprM;+rkvQxO;u_+S$srBH9|mKI4i&L#C*zE>iCNRXevcj~TY zTNu$%M(5jY?|H7*xt`wd{UDqpZE>7a*z7Kpl;vj?7C%-RMiY7(HglD$UB?=%Uwn-R z%6*QWL4{??#PmA?4{=TlEg4C(j3|Rp!Zd1snks1jj2%v38C_@`d*vIyy~~qM3_9P~ zzIM`|@J3Y$=3z1d6dXpL(s*`TbHW1(HJPCN`(e}J?PI3)dp`t={bmPvsUAo~4_R$F zE)?y(jd$H5QbwBfuON|A1Yx-0KjbN}EF_qZ`Y#!;K7J`xEWwToIxo~oAisxVj!L8w zTXx|knwlK`c5cApf?;-<`UC7q-PBTofo=%S)wBYmMiOM))TE|JfN>_Gk^3#NblxT; zMGx3IMc&AFaYRo8v_!u^XBNpjh#S^4&7`RXb4dEX31{1iVbvcXoEd;{{+C=-&fev3 z(n*|^8xlYboo@-~f%^4R>C~*P@lY6?d$6Hy1#? zQD*!gnBCo$A1*rC-8g>qk?uHsPmC})9{Wst8)MX2!~l6(W*N&H=2Na`Ya7`@}|+R1$WWO;wT%P6TyTgi2J4l4-0U^Av@8y*n z^;0bKCmqB)$~)K}2`}Zu7Z?>SloYlKdIgp0dV|$X*bs^-FpHKl3D~Su3#GyhQqxOk zw&x{*hG~WHI*{s#uspE@(8ddvknst6eALwev20i&oD+Q!P9JQL#b zgW(|62S`PF;wd6|wtNGU1^a(TwED}wia;bK>Hs2i00i3q#lGa7{w6`CNdRFMDqnrA zN&!sK9_?NNBWAT78~NA>T4HFJ2*-)yUlMH1dZT&=wbQX6X8K1tap+q=0Rp*nG<9EL1v)tLoWG%Pc z&gZOORa@YYOw@ASg6kh{$iV@`Oqg4bc$(*J#xf!$H_hMCRk8UKsh*uGiLw*jUajL4 zsvl?N!}&Cc=r@Mr#wC39ROyPrLDzM9X!h(eq#YJ2ENVM#_caTtb16jsiCJ>{g<0oj z1D!vO|ImOA(@8w4@X{@Va6YK zluf?$dO~Rie2`)a^|Ru(Cuzze7QlYEA||Q$1W#Fq6t|iOFbyh?0!%etg*-B&6tf@@ zVj{Wa5Nb4`SfUJ&Fs^Yx3v!C-5;lc2kvGVs9Zqt~1Uy<^A@9qCFtde(5DDcOGINO^ zc=hMrk9vbHdkh~^d4b2Mxlwfsm>Wb4nLuY)-R|%*{-=9#QhVxwm$n%LY!;^+P0jDG z;D4_lJF9L`c>w}P1qdAfKR8rNH&1#8Cwm7|Ks90NT&mP7H_V8b2Vem>8weRd12xVk zo!T2oKN*Om+vOq^@^zp4WvvB``NPK7zwb6?r@+VIR-uU*6QO+gP`wcP$Y6RLv|8d9wyH=|mY$-5>Kay*Tr5)LUs|M5)7=ZzsU7@;{2)RaJJv8n2sf?vfL zRt;iIhRP=L%ngh9mOS5rOsL+$Xt}V^dQ^Zg>Q@P+uJ%3`#B5MvfILTIHOV)8mC!UI z9m$a_V`Rf=hdkc2@VAk$kjYm2D>ggOm~}Kb!sOr(ui2#KI`G-(PTc0w*$*;ph$&SF zzEkPCQI$1~%iQTQFGnfR(~u^Zkoe{%aHR@VzPn+w}}=jU@41)DRGRzF|6nJvFp_`m<}Fyl8MSb+ch1+dxu zpSJ#O4F6i8Vh}WPc5yN^c9HqVTL9Y`;BM~u&mulmRT@BWhWJHZA8K+;7E&$<%(mZp zuyuzl$ch;RGb;FPCCSF1BB6E@PvI*Zqq@g?RH^aK!1G~mW4HK4rYOS%srTvX>FM=( zeYv+=zu*4@Y!4Yfyzo$pkGO++wv{pS5@~y27Rru@YPKUR66%5xYYerFZF`Nect0*o zGi*<5ak~vuYf1a0&JuOzAgqxVS8p5B9IEDihcB$nZ~=_L ziD`5%o$oQ45`5Iwe0Hen+@X_!2h=FJ8%_+~eGoN`CMMHW zozqOMWHpU+v8%AjPJ@`tv~?V19NKxB2+wgIs&cJfYB_?on7$zO2XCE#vp;ytsP(++ zMk#C!ireHQ;@qQAT}ief)mMwya14n@o|QD(idv ztEKPsl+wD4UOugxzv+jqdURfGplD!~)cEK6lC%elWcYmP#-O?U|4Bou} zmL>$K8~@X$>Ax&Z*xnX^nPmu=DE^POrm`i6qmHUOo(BsDD%sh=i6OLH(%3kQx+H{6 zQ8EG@xI!cmNvv9{f_KG)XTrNWgBbbhCzSWNklv$I*(t4G;h&8=V1~PSinEi zdDZ-?b$Qi0|M5JZ?GDr@vN{A*_SHJa5f`j+53N3qiu%>F>x3)P6f?oQls{Hy1B! zT{yfcm$F)6)qb+<1d{{Gzeg%Wzk3%B$h0DHW;=<8`H?vFjPuATi`ikiGN~F52S?zz z8;AF7Z0|>=>fl zj|L_SqrowFA8Vtl`~;D*P6c%{X&DHD*2j{NZ=>wwdlY&@~mp>mjvt-{r{b>Abjl**jNb@g8xh_Tz zSSkom2@{l5Pp9^>WC!j^-P5^X=iXPOBX&C__EF-{%@+g@?J{V(uS1Yx#teiprGe7U zDt+j{8C5;vR`90~mvF@+n4|o}C`)9vcm$QI;Y_KJ@{M>0KeCa0bJk(}g)q8}*!aq0 zEkoV=_r(llvU{u2`3*cSzLhk2owF@j@{XF^gEnb?vatqwk{F}v3-~{vj}qb2DF|?OV2q@Z`6-)oTHFy~npaPZv1@=uJ`aKA z8P$0BahZQoImfCV!6+z0eY%rmA(fFMHwoPbX)`jm zAv~>nmf}rB)xM~F;Wj+OWY$+bBPO1-Naf5FNA>w{$p3%kr_9V#KBj>3LKLv;_@4k# z{$~AsUT5UAn@UYhHcQDxp+r>&|xoVDV0^s6f?;{ry*=W0T6k3NKl>A3Dl_Zm`}ZT zKa4S}A_lhXb5(lJ64bLtj%W&}v&DIlFZ#tVn&^!n7&DFu?}~cKqP z4Q08Dd{0zKU(OwL9vj|^Ji;QG2u9PxsH)W^(a-aduGp#_IT>6 z;OA3It7RHz3PP=``e^u%HOq-f>USs#Qi$)QbqOS$APs4pdQXMe*goU2)m7k7IG9El zH+B!2C8Dt1O}Q#U$#H9zT)J&>G*}wr;33*fj8JgM@eQX(jCq;vQMcf-|FAHG?SGYF z-H@tCN0l|F&m>JV8eu;1{o1sS)(8QPgc-dYW7?iyv@n_^!Rkk9nqySz@Tz`GBf111 z=aVcu2k!%Ek$++bb*#pI6^cclI<{U$c*6f={E&`fE@P7TJ?jvhrdu4Z7w{DZ&E>KL zL)`lYePw*mC(53jU_6n`)(x^fM!C`yXV~NZ3$oFYdzZmC_yvn9?DJTjTqSz>VbVZmT#BVAv{B@4C+DjrywLkJpgTTT41HMb;$VT^7?D1b+!R<2fbl(y% z*aNLKCIkm6!ji*~kI_nv!OLh&7)%Yc1Y$u{JNbAtxp%qy`AjJ|Tz6Osp`}*m(c8|8elq@62@i4N+abyO6OC1ay)hDA1AJOwr8kuFq{2w zswXL*)8<8}PbIn4iknZ3NIfJUM0;I=wMOdiP5hZjY_4dX*sA&RQP=5;&Q2nKC0)z? z3RzoHZ%6_;EyiGm_0Fwk?HAO>6z*wt_UDt_~g$jW{$qZ z?(pqGKNiYp{;tILXe3zI5ggW>Mf#~z!C9gvIIEBW-cKNucZf86gj}yPnd{}B;v05J zpr17H2DVQ%N6PaO-$^_Cbj71yRFyPIe4s&7Ht--Im_!yuzNBpvHN2kth@BV3UZAgt znAVjxLevN+9EiUMNk*ZovOrIMfc;&_{lphJDFAMg5Wqax|B`O}(?cnlx>-6~+S~ni z=aj0Z>wp5-#I|diB+o8g5Rg(&Ac#$9D=Ab&(iV|wK$OrfQ78axu5`(^*>MncQ=#4w zfV+-C669DCn1)@*jOAm&1+l;lb8^1VWPjs-J9@i%E6eMagemc~PL()aT0KcWTmrL!+`o=T-@V5Rf4!*j3bMO{5f}q8O0P_ zoMefa%gADkQ-c{HEFQ5eW1t>*RT0q8wGz&ZlapEBlznC+CZZNZWmr6}YwSYZnMahA zLw~ezmuq!W@s!Qajl!+2(ek7@r5SJ5*qw7ZPtY&$v#byA5oEDk*O*;eGB=BJxOy`P z^EL_b*bc)95pz^B)ySQfu`A?cF2IbhLI+b0s?gVB4_gVI{-##kqh|>al*=kplfbMp zwG=tm+F0DDhY^xFHG8lMoUw~9DO=S{b(xW|aWK-7-r}34vXz92VtrqJq%j(K(^iYXQEULw6^kb7Z@2btD4{MFbl+QX!P^-8*fUDEN_~y59o+E5i zSTMT=t)SqdBOfYGtOqmI_Qq5kTS9GghCdQeQ!59I< zfB;#H%X5q2$t<6LZsLx_OYuhUo5iO2JbqBE0470+RP;N z1sf~NFcR~8^d_~OhH7e>1oOs1kIKSBSk{^se6XQ=Ft?=wSL~HXO;6#LE1$Zug-*lf zMv;|<>#C-;RMlKr_=-v#B+*=zm?BP&5fleE*>eYPzWJ)61FyI)O6BPzPgEV{y%1#m({AVjTB<0;g2=SJ24WW2vX1977=VXOnlMdFY+$V z;?46KGecNkHTGqX9ie{0TO+M}h(FHD3^C>w{jm+Fdqw^NR=02XHJ{`P* zpgJNU1y_5>n+>2oHsXt#jeB-Mkkt`S%Hz5n_JRhOKNN?%LM;}Q!`$)l3sK>tOy5ox ztDqF!Tj2T`HN#X6sfA>hM(?94kX6CjiFxTSiKPPzbjGRzEgC9=62wAR=nywmM2iPk zO>53y5GMtDZgh<#RCwL{1_)ZbEI(!MLq<9d$P~mLd3&Ne)^8TDwOYg$9ox(h@@vO-6dG)!N7jK0?GfKj^xT;zFa z(S+O)KO6PIlI16IY56Kk8GT2|Y)*-~ib5vZ7k`3XFXcrV246Z&to>mx%r>{6#Q2C9 zDhhSvK=!bpWHaK3Bu?2WE#3JC8xQPNX-r=X>UTw!S7jRVk6=)d>tQ0?5kt~MGR{~( z>}ycg7)VEO@q4T|Ltx>KFqDos!xTs4S4Wus1<+Gqv3s7eJBnWCuOZH_GWEId83u5c z=tHPmA#l+o)9(e%Bu^b!7MwGjK zF&6(K3-NbY(QRM=_*z{089HyrSliO)RjFL3T=`Wo53*!9zufB0MWtK%52S64vE92E(XjibB!?|*mmdC!RB!hkrw{uk)R{}s#sKR2)J zU}|h>Xd`QCXlH3>{?Djhs(fp`3FxBE>qpXmnpR(5ZI&&&S*@Gxs(&c4Q+6PnAif)> zl=qEE$VefZeyQWwptAqqM|csB-NCSJWjBr?>dAJ$?F4i`WdLa35AXvlm{=u>Qo^Ho zye|MiQpGvKz^JIIpmG=ltRxJCTi7t0-tqA5hE8Mb*nwu;M=s$Dqls%^Rdw^Kaydeo z{mF;MV-3MrBE33REMyA1@CIquX(aPtKWPtp&uN6t9rpI@?dBujBpEQ>X>$!5oyfM) zYxN)=))YY=SKR&FAKS0stJcrb^Jn)+uRGHN4Phk6NKoGyFAP0M!qV(J5hTmHxu|za zNfM)|f|?yhTb;whe3wtX5hBa$=h*&2ladGqpJhDu%vWe$MeoU z8>zZ>T_N4XZyyR5I_cAsd%(kb`wfN9Vd603{+!wyYUEw`?Eomj2OQqyV}6vnbIUS# z#rPeGzlo$N$OKAepXrok3nnVcsMQbhhc%=^LxD{!RmK8qh~^OwbF<&D`3qeQ>pW_i zJPM1N9Y(QZ>7_Wo~^4l))JKd4kh(blq!%~UBY>dgJB)s(` z&|PeN1taFdr3Sm(U;Bi6aF$cz{R#}Nm&h?sUYGDqpRz-al97QtwgiiiAu2*cwY){f zH})5Eb7W=}^YlbdgauzR4+3@K{>1sairPi2Dv<%yGXua*@xQbf|8pktFP&7=wEqhc zW~`Afj%8z;oK;d2CUi5o%x+rE0hLj12|Fj0(@|1m3CH_Nh8s&f&k=A!NsFvvl<08= z`T>GZi6~x*TrcrKIpR)%vL(4GrTFP^``mfzbLwN>`O^RA^O+-Hx&v<%N{M=`7|Ngs zW!OWS-hP@4@AyFu469RK%n@Drft5~vy|^Q=hPQVs^ff`52}P7ZNy$(RdtUP12kf?5 zBf<#r7Zf^)hLWO!qw**ujMsy<*dpp$43W)p9pyq(o9zm7ngi~zqJx=}6?bonw$ALl zylK<<_Qi~f7dwwPUwr{bJ5ifx6X1N?NzA4cRfNTv0mnuu=aW>5|Mbsne0Ri@@7gnYLTn{wb+7#D>d}`Pc?-yyY@emFtdG zp}1jKLQ<|qyBTfd(cMl3}Q z2XERy{#m=SgE+^%T)uDGQ?##nZiGj^tjgT>4VBJNJxMcL5Q`0KAuLFswt`TF-PVu_ zlLx6@{Irlw_IDax^gYEn5xBbik3~IL_hwZsq(-WPZv;N|JC!^%>>CiEeQD_|2Y7HI zCfXWik!LD(xRm+)X9sS!{G{ThFkRbLb?;QW4Eqc8LLos77kT||Q2i1kXZ);qHK%Gj zst&b$U7fA)#b;%4(#YeYK9x`jZ5r1a9}`EO-_&`tDH~+Nf9-(^-q?`kp>A|-gEo2h z=EBeL&EU*|t#kJ8l!0gCLHmA-`T`0x#piZIT1nLndD^2N>iVJxg0JwRT@pCu`$j$Z zj8&o2Pbd)8kC<-=l)wBd-Q^vvus;leO9Y=&%yALc5-#0m9NYyF5)`0RM)y7 zTYKL3$!*VUTKSu6p#9moHr#$(IB$pjHOaJc(s%D9R*HpJ#iHCN2CR^;L9T~O?VrN^ zCTjv$^j^oKx16p7<)8_tyIK5@NC)qDTz>JGeg(S(nSJ@28t1ZVxCXn%N!>lLNVFf; zD7075w{2MAS!4AFY`Y#on@K7f1csa1PsMpp=9?c&Vtm^r_+yuFvAvPjvt3$xZv!Rr zzrN)V&;J+zg`U;PSmolm=+yk5zk8ise&(JXK#}_m&~jz^zXGF*rLF1zSNkYQ+XJB8zSbNM zlCoM_WT%S-U_wuTGXR5pq7sPERH=c&#ZtH&bKEvZ9*bVeRPKHV81yOuA^%{mmG-FM zBARB|otv5SVQJp=_xXa^- ze#Bx>u_E?lj%KzKF)aE~*_RVRQVbn$*8Lk2POymFzOyXFd)8w{o^$lH_-xgH7TLMM z!txoDx7FT~?ycq&IFhJyqY&Js3cs>aZp7Kr(w?rV!+bfU!YI@5H|=Zr=0plbS$aA3 zi0u{A%2!&fDt{A4Hj$PEi_2HBYuIY@2NrvdrIiV~>yAc;VwM{-GWkiUXJHs~s?nL6 z*ypcV;qFf7N2C|D;rD*wmJbU93&H|O!N4bO-uFuNZcZU2%T3~`YvqP-bG~^dqgd(+ zBv@ZC1=5Q=Gbp5At>XP%75V<_~PG}*&;WC?^O1TXr>g;tG zOR5F|Z4l>D2CE%8!Di)kK;aV~|7t z@OazC1H-*E-bOcE+*2YazO-Vof7uT0eGGo;T?#zcQr7+H^X+vYL9QC(dHPxwP8VXy&h5+Ha<2@xg0Jr;18Kmkrffx6L} zZvi(5BWZCFpg(`T3VO?v0Z*VEBs84?-o@~*3%KHYxh3Esq>H4iDC8}uCGrvnKLrvup7dJ0$?V)yduQ~NC~2j!hBI)2pu|~ zxX<{bG!uMYb$P{lsn-P+;)seOU}%DZsP{%1AizmL&>P8;G7PHE+uy6ay1Kfn zx+$PZCBFY!q2SwDT~)pP?VbPWsrPG$jRKUAx`Ohz#5l-nz=!JI=Kv=p7nRnzFyg%) z6bWvCOJa9aei!teX1S{{L0p&YGb0Y0(V zgDpUk4}lQNii0M-XndI_gU9OW1%LKC>JwPWX45o>7ALEmpC1Gh$tB}O|I zZPDZ&5L{o^O?A0q73OGpF-=8s#Sq5bJ=7Gpl~Vyj@!YSQ(PZczNJBX+fg#`ou(Fl# zcU9s%Rsv_LvSK89s95cgPIoYrlE$U_mGfKK@D~C*f;<2 zK-|5zaEc%U>Y;9OAf%b`2#^?eRmfGXSzF+^2mSBb`FX(@thNJ-1EB-=1+lXUAYLOpBqf<5GLFH3w zjA_va1?7lO%}oLe6D`iT>5F&a9?uLs>j`XpB=NiI=5LBGKCK zvk`r%2Be~EV{T1)LHTixNR=T4?fum6C2T>ve4AL6-mr@S=PX{ZI+Tv~92Cm3ObIfS zTHiWu@JosS)Mx3);g00@7#c85ggaq_tuLPjucG&9NbCT^J>`LA@N)bgZgFiVb*J)r zUSFQd*gQ9lxjMf_B)}EXN*@P`2VP&>Zo2hc+#LcS_B>Oh1qhHF9_`~|zqPox&2BYc zjePr(mNxz^Ha@Akq)2_qe*wCJ5-$8)=@A+%#@9b3wkH)DONkjad8hH`qjqOrr^jH; zI-kd6GikTFYjK-=#3p}%6()ZN;-krE$ukk3lnvLFTOr4c|IYYNMl7JfO?loT@Ew22 zbH%frUA}3Id84dq)l|MX$I`k3`X1(_I-916_YIQG0&b5$ksd5F5W@kC(2Q+ix&K$j zv$p!zV@q712C}{B3X;eXkf-`$Q zDzJrDug6V6fpb9qerxv@WUkmRmZ>$$Y06WR?5<6W7PgTrUG<#@mxw8HH++FwSKXI@ zWuZN6{ct|;jNo)hE)bou?{cT!@GAU!@{S~?AZxNH`>>cOb-q%Z+=hKY<@+#g^g zH19UNS&I41pkmh^T>IuA&Y!>da12ZTbb@kUL|4~?zM=(_=ja61SE>j7mQ0D;JJK#Y zeu}@EFm*EK2&@5Sf7`qvZM!xxcA$;glZhX zg69v1o*N}>=*w9aNru;neW2I_*@Gf1TrkIORPCIZz^gO1S4ACfWr9Ni1y%jzAF@jM z1Dpfo0wUROF(=N%6+$~ziBeD*e0&TdkE6%$LAxY{))mMTP#>n*(TY0FcZ7FvE)Z2+ zH*DdRk&{ejMrI+`#*&9coGWRFjb8PhL6{B%ixhXaVTh|B*c259Tuj_Vbv9hNEG=ga zQhqr4%MX-R*b>2^D0hHvz#j37Su?qtlTZ^%t1HZKuZtd(gs*~{PF6XS?V8c;sm9pE z2WUEGzY8IP(8vai9YQo7Vy1>$K~GI9=uR&sA0$3v0yK(0702pN56%2EVYvZ{snGbz6vyQv2y3RN%CMa=Ben}&MwIS^@*@Yjno|EA>vy9sI zYv5HpWgj^05RF5N^+()g{4V63)kQnejIs;kh>%u{)Ayl%P!93fR@LQLm|Y+~yP(rI zew<-O(o}qW>9OqoR);m~9a)}yA6aYTQ{i)+3s(~3&(otTmu*HPyN;b&vImtOz2AF* zik~7dOg;$a8wD7k@mGff^20QUyr6Vo#=_541_iVR@M)fdG^Q*t5JUP3{9)LH)PHG4_}!?L{TfHC?qLS0z24!9pFmIw{8)oUQ9fKOjRkWP2-v8t5EMp^Gl5}luGc&ZAncB?E>^9qFW@hR(Gcz+YGcz+YGrP@j zeRgKGdq$(Vy7xy(pQ=hKRpuL!k&%&4B+Z1hl46X7+Z?AdJ&t-7W|i);b7-V;npvL{ zSd%u>+<0`T8tiIdgYIZ_WCQn23yeI#e2lT#BzmO{OeexniD(@xhV zWvApErxe8UD7FXkrnPn_DOd|1gV6bgNc(;Bnt7M&{)UE!YRJLRESF7r$i!hRqx)7S zOygEYNEVpfuMbCpqmjJf1O^v^uH`iE%skcDG>L64+j!xu&6ZNfd}l?zcFx|yNWI8_ z&Ww^KI`v{VuZaY|`$RQ3hXZqMx&BR}u77VYx{2#*&Jt&nLfnL9Pi*E%p=9^+-Y3+s8^#)!fsmhT!(avbL%kN>I-rxW+%nDr^r#HL#fzn_!g4&rFnEI=jwBO&BaO!&mCoV*Otb#=w9$%O;cYV@JA z>+EPtP6|%7ME%0j(sS$ZFFY!AtitGJ?uprisuw6q*BEdPmk^IHpmlV_y!Vu93(?Qpb z&Sl=CA(v&1%{|7(-R8Isnez;QD`Ya*Wg{(})3vPA8yB&bWiR_q#*YaLhul`>-Nc1I z7dATG)3^(8+q&EHZ5i45d1uvnehnl(g4%n=ufzfYlCi>(Nyp ze-p-Mc~qP?Lm%uxW_-Li0*xU>(z!p_YJ}awd~90Y_>db6u-AT>~R7rbZ@iXpbxn9jLZUzjurIw zz*}s%IFvU4PF6Aze|DNV=A1Gh=E74V&v4(*U%quFOc=%LC-+FUkn~b*=^{{Pv_|Vi?rYh{@u{@mkm$u> zjc3!amA3|E`e^(0kl}uUDAMw#&fWb6@}$R$s{fpuS8GC_WY##IY{F6ES6X`q3514mI#m#Jhu4R$gEKZ# zPh%Yk3T>Ml_wIUC!w;v++HlM}6TG3EI=RV-Oz(Kc)YH%7X|*dsprHww;4 z^4*(5gV&%&`ucIOKmhj=U;BHaRa+L`YUdG$CApN`r>K2PJ$#XS5?qmcTcKRW=WAuj zowcNi5;?nbrGPLKB%j#wab3Gkdjto`{E-5Ww({?Af=9^M5SkYZUYPVl`p)Yu%Gfv2`V>TtwFdTVAYn|JLsZcEJP z$Lc|Zg4~P0FY?<0l{#RI>*?R5OxDg3WXw{YLFcM#y~9N%Rmb}%9YZOTNA>l_1X8ID=V5x8vXqp!1F`YA z?wCNVfomy}2-bhwqdp~?prMUF8j$|3lP^3t8nsQwO@Lpj!KrJxugNobFGHW=IC(WV zLBd9^c({KEa9)}RPxn4=ljz4W6K5HK5Oeu7ph4eaav7X`48io$Y|HxSadkJurdpPr zG_%Sib11}@7?;j2rSw0G)(7Usioy^~$~94@c+-U+r(gY3DNUwwy-Sq__PhgzK`p&X zOE4v}X;RV;RVAnm;_e zwycJR*Awud3ErJ_*K)>&7LPwu-^83Ns>_87TL7mWN}48{i}MTz5o+8o zoCvShf7s?x*P!s5>)sY^yhwF)K-pnTsb~r4waO%m6n6rHf%X_|iLW><_m9g*qajG1DqNs zDj?SHP2H<61}>tum^@Zv>8Dcc=8Y1u__&jBT(p-me;X;)TJ_bJ+|lDtMLJop-Mv|P z`EkjbOEy|%&eUvM&`!)*4ixK zfY30I+V1lqVYtHRPTfoXyN^ibr)0*2ktQCk(n899ToWlGxgWE_c&(aZaxyYhn9v3j zQcfb2*`3Tbu0S9f+!=Hik}Lh_0p!meG;knTf`G~IU+w09vU(p4miOQBfNIJvuXntR zK2SQyo}_bLwGIj!4Ax338u+QH;x09`q4D0VCyI4`HAB4-`Wjj*DW#!=x*}RPea)%X z$Megrrv+vA>$*auEs#^qA0Wpap_QmR_4YC}`e@)U0BV*OebWMyUdir|LYOgJYa`=Q z(F8bMp#zOO? zKb_tJ&c&xw%J&tJ8J&!ZoP*F>XY{F`Ff`p|m?;b`6;^Fast$3O5pWX|g;-)>FM&;2 zJS?rR=W$7ypMjB$D+st!onghRi`GVpYk7P-BQq~_|Kk@hmOrv?m0d~VK< zX~gh^HrBz)tgX)bEyj#DVkYzHCJqPXNY1^9?y+b+oy&8@zDX|=3rv+C=Pa1ssYPEA z9=tO9Q><=udSAnlFw|*)Uk|L?aE#*Ks^CN;#<00we6q5<6OCixcF$Qyd+_7M+YqPY zJblP?Fa6GdG;sAO{k4f;<@l7iqp@ArZN7~_akUs*s1$g{smwL6GG}LL$tC2MaDJA` z`RP6+QH76tVob6iHaVGn`oO~4_+HGh(rHh_Jl?21rB!WoG`GawY&C>eqrWm9DbiJc zVOduiR=Qg%#mObfnMTCQJ8!|2vL*uCRJa_Pm{Lpj^lI+zSa_9H%rjPT?ap&urf6do zz}1=-5(uU7y}f*rG6{$r{3Ell)I`p<0nx^(e>3;F>7)2K&oyo0yRQ8xYCQdm5w(rz zGwo=QCmr*^BTt8fFda%%_t=QePq0+O+yJT|7P7TP8LJGpt(`l$&++gFkt;_n4~jG? zdOK|#<&;gvti!<{E{63%j>cdD*iGl2FTLp*C+pQt2W$>4H|it8ci)U%XrC<{47k1m zyLy&}Z_=+crS3Sr4h#3b!_6_b=yEhOJ4Ye&o3UMLCGA3h3zAfI%Wex3O%7K~FJRCe zTF3~LTtPK0KO+q13DnUH*8^J0e)=@Z&Lq(-^ETj}>T2-(YoL)YWFYH2filsYx{TPN+IPari@IHs1wnnW>?$fl zKPZpo@7H|W;f|>rCd+Te#Z_!(y2T%j{PNo9SC-%Bp-x+alkefIT4!E{$lTuN32EaDAUrj7U3VZL3-3CiU3SVFgUxD%d6103YF~tSAJqvNw8-UaM`{6{7V) z|0et{7mJOrao?NRg_k*XfY>i}N7E{|5o(Jw+=VP{0o(j}=Qg^zpR@p`1s0BGbWkFi z+)4U@Re-Z_r6S#4D$NJ68Nk5iso%>ks}Q&Wt%p%PtceNi@;mXxH6JqE``!SCDQ4mc z-hT{?5oWI-p$<)@PyZLj%gnVLxDci4x_R+s3ObgeiihkH(h_!{lMERbXKLNhR0{K6 zaps`#nL8T5)p04Z@&P<4(nRz-*7viHRXcm7+m_zaP(snwU{=G@L8y2f#CL*Sm(f^c z1ncg&vL4c78F7=AbHd(v3Q=mJE|EVg!-H`P9qktK-hQ@j%@f)^xR04ODY?vHr{y41 zI{SM$^>N&xw)oW>ckkCu1nNNQCx7Z2l~v`sT7-r5q4B3)ox*38eXINI($$38-KG@6 z61~beIGipMwWmI4VoXyxJYEzw=D08{EbdseoJLkp7?C<1#D@S`Y!l1LiMdUQI%d7- z+ll(xWTRkE`wFJ@d?J#xF?yFFk6axfTNOXxS^K@L!JIKXfi<*?sJKNjyqy69Ki-k4 zti|Lj!Bax7o#I$*sdns?Mwl(Uimo({dy~9WULUaoncQ_|5E3SkgRx}W--`GURt?rL zXB>mWBDiUZHW&XEu3zJXah^1x`t#LYghQM>N5i61t9Z2^BX{Q4J?#`dkWI+4B!Mt~epi8q8wl5l$n$6VC?Jq9(@ zcB5R1)6wK6#$;i=o9s#ht0kI^aEnNQ+(DK&*<31#ZWfwxVB2x^A9s&MGQ_ zJsmyOMaVZ1o(!@hpTa~z!JiRoG%;3^vTi*L;od_vX@^ssKNt&2V1{at`UqHgyCZqd z7$(#*jd=0GNNXdlhN!|)rp2m}TCkp~vnM2#N6eG$v34dALiV2c+woje-^I$>)ndH~ z*8M6J4rob%W=>n{dHmMm4EBWXXo)}KFI;JLuy)NLWG1){Ll*WVo{8|#9x;|s`@ml&3y z)^o3?W;U>>_HABpY3NgZ)2Ti+X5zDms((qeK z&_al{Vqu+`xH=*bm+*w=KO|R{DH=Nm;v(^J!M~yY$t%NVGA(FTv}4un*+p!JM^GF_ zy6$o~^FCyHe*T5q+_Bt4p`vf5;rxl>ftNs8?MABOoa;X2|Dp8WxtQAuAcEAGw)n^* zkXvXKQXT1C~ieTp=s6K6SK*mH*tZ^V!i8=;F7C#sd7p_)!3Y;!aa$0Y7BajV4|XRfZtfuS)^Tg`^%7)F~i*20#-&oc32?vkJ6>rY)c#^+*;l18N(%znLIy97kBqsfxJJt+T;*#&zy0sSCHk-NikdnW=C~d_>*_>Op5mm z)XS2|!w9P(#MD*=g-DdinDsu?*G!GOaTJ_a!ZIh~0+6Cx`s1oN{iG+{hAF?r;1y5DgaV%*Dx4^Uj879Z-bYLfJK#GzvuQ zrglV+DzI+Cb1?fZBoBgETt2LEEx#4k%tC|pu@VQ%T_;t(%>^?iemDE&y|!hoy70>( zeZAMUyvA(pvf+ldEz@o2_-T9A%XZ`&Z4ceW)bYZt9o9D3_t=b`Cw)=cKbo3NFc!?k(`Y_2lked;b16Cv%7 zf#A;}1S?5^y?G?vl&N{#$YL$8m?ANP)+w8WEmwu;p!cIOkgm*gp@m^HSe5vhn$A5O zoK^jZk;aNh3%UEeM%b{M`{Vk}oC+H(+?DqmM`y=tQ!FIZBqpX-h~T zsY4QoXx8&h8xxB%^KHmZx%wd4KtF%aqPNnkHdsZ4R&_ufL{i1(tZwi^dt&d1Y%M3F zE`VTT9FT#c=g5vaohK00sDy-btm$d@|`;c){zGP-gW{L=I_CA ze=BT8C6zlK6AL`WpqD(zxuPd+sdt&WL4-P2~Zm_X#eg?rl)l<`Tk#6l{LLR=L%D zX%ZE#4?BAHzSSlz{`zftNAseKg^mUl=-J+nN*xYP-`igll-+!oG=4wHNAe?iT%BeY zfQ#dROb+B@ay>z(awPCrs<^SiUZ?^k>qAvour80@Kc##xR!+0s24*O9Ml79>NC>s^ zHFC6CR^GX`b%RIM%KZ+3PMG7kL>0OcRt?!h5ob^8b~B8SI-`zI*X^s}x5|`|GTYHo zLEKB-9rJ!GDOTeX)_w1$_UZ@&#Zas8Gv-rl^gIxwURO+aU+El z#barh`_nB%F(;A_Q#G;Tm<^hPm%QslP=usH4Mh0O5OxNDfZB>ywXw=fafS#nGeRzi zC;svoPueqtBo_KrCj$f|AtEbWDX8cB_qv_C=&GCauR1L7ubMrIuW$WpPgg5|qk*ZB z{TD^hP39ku|17}z0_*h3V|q`fm(10k&vlNU3KDA|Ix2x7LHMi$AkA;s$#ChTG%D@? zIwd+IqB#C`pO^b+N!?farbd^3!#T11trX2LJ<0li4OZhpcPIygveK_ zEcZzLjWp1+NHbZUyrt^a8wzqZ=uA-~yl5Lx$`W6}oZ= zgE|G>Ty33O47Qab^)TJ2-o7dKOuPK$=#-=Ym(dm0Zp@-eeK zV{oK#g0MHJfsDP?-0Wn1rc-bEi}eWx*4;mdgo15AsKnm0$`#YS zBc1z16N+3Bc5%YW9Ket_L8`E}KEPH;!A#(@Li#8i4-?3gDKiKsFzV9z-N@^u$xoQS zyt8pJq~50}39uQKE`T}3pP&{BMf_p#M?YB_{;>U=4K_IB`UtIpC(%XX_!am8ws`TX z+d!_K#ryg%m098J^DER}Rd$D8_29DqVTMIqzhDz`_KHR(My|H<07pk7d+UErImzEX z`7y5(m0 zw!`Sju;~##fPTf_oDY}_h4m-POpd!aPd;XhjX&b+b^)vP^Ps3NlNmFl^*N0jF$Ut0 z9WvrvSRd-;jw>7#+s$J!$+%Hy4KU0tL#0QuBLi&2I5vA?>d52Us6me;YAYG8jS1Fn zuh9ZF9zErF^pdIAICuHkwRf5_WYAo_Jql_k^vWM}Bm+JB?hfYOI}%|Vh0CNe_4AHG zFB>7-A&X>%F5C(G_BGXv_+A;JQsrYaZfbXnAOmJ9BnKLI9f8_jfFbN0;B4dxq9wX5Z1-qk-?epVg<`tr@u8h{ zdj=1bcc3c^q5ohi-7`jh5iuk`3URTG@K=y2f2R%FB z@&6~we|Vw{r3+c?FT_{hQZI-~$u#{MRq=t)hQ=tp42qDYx$kl?Va;dYMX;2fS<=98 z-aT!#jJZ-AFF$_iNrpCvS`SMsjmyJj%h5WQ$>C#GRu@paFrhzUELE>KcnxlUXsAlN ze2l25fNFqmx-V-2KPC7X^bgF#uUnMX_-aA9bd!7+4w`&u=t725ECDK(x3Xf6n7$qd zqcgHC&13Qu8EP7SkFG^t`WA!gauzKjtE`2O>x}_M@Q_WIy-t9u6uh*wR=wduW+gZ4 z_?OU&C}n0PCTWGsM)O|I-3BrvkhMUwWgE=)6X^s(Rr9lU^@Bu0J_H8d*ZFKH)L8mE zbkakK)}E>6#eHM#vgJg;qJ%JMx9ywY3z?yNU!H6SOUt8~9cg>Wj*Pu%^Is zo0~+dwPfjpw>08RzRK6VhSeqL?SqBnD{N|m;!&^R40Oxw} zZw-OdR)Gtj%x@YMZC?BJPwNLVw~V}(;bZLy&)w1KqMZg0f&C?#vKzzwPb7C`%lQ^4 z5ZZ9=-=*Y^N1rL#f-sFP=hi?(p6|TC&y@1(L_dMaUtzzS?Es||QPh2$lX7F!U$e_6 z5LJWW$GY;D1;g|TiG}YVLA8OMfr8kKui+=QNm3gWYywVDin!F>#nma}f}icTc0NH4 zzJa_`Qw+68fr(i@LVhze?WM_8b5KLEKKQLtnK^6d*nH#3t~uHRv_tJ5NuT2l+V*6^ zj1F0Q3`rXko}NZW0VRU;0`vD(aojsNw)1OM{EM^7`+pPXzw?!U^N|^`6JI_Ob1-X# z4qjU|ECGEU0>Fbzs1r;=h9*wHV@o*4+08PB?o#CcA=2SWs36X5OL`N<)XCgN z8EQW*?aVYa{`z+4R(JP4)MNovRdWo0oVvBWSr-D2!=1yWXE(-N2X*rvl`n4^NP!eY z!UJ#PRGpc@?(=g(qkK=yslPwEvG*It$%u;0k^dR9ewxW*)J~q7!_q7(NCZtHLIH#8qU$|f6aY(*HF{slbjO^@a_o}o1B2y&O z<69L4bb4LK^?b~FoJZCvvJ9I;f*RimY2Dd{bE}<{H5H2UF8xvkW^xp_v6n5Z!}xRZ zkW?i2my#kT7~IqB+Exn2ZaY{q+C9q~q8&MG00$#iY(84SRiG*RS}kn)tqp+ z)PHgBtfhePFqiT>nu@xj9Hv^D_Yw(U-qi)(Rp+)kbt{Md|1ZdWC(KX5RM2{Jo+*Zj8eY<$-NC)l zh$D*O8Eag}fbEfP97UvWkl8G^ABxQiN{;q0S2%=TNpcGVX&U~^P0j2(ZxlC28ZC_o z6L*`gaHW(*uRujH!-d`=3Z6vHtVcsrnGt-18J+v+&GL=MpTI}O%bKQQv)awjoJ>8M4M^BWJ8AQL&tPi1KOV+;B0PI63yGYz$@>v7TMy z!9GBHfn6+$c|hbL)^P*}Udbi2PZPz0JA#1JnkLy6V8!-P@vjbCW0~_pOyp(`m62U1*G5ASwUBbdBybKnz5!ars1EB2t&xsanKF&A+;2VEj+w#D?fPHM zl>b7abay|4Pkf1S`U^V1{U6+vn5B*W-?d2c*IR#gQp*1b)US}^s4x9t1VXQf`xl{AIwBpFF}I!01Gg}yclEaJ3cSlyCiuAU%m5gF zhjpq|YxVO$_(pT^ou@+DivBmAIfG+&z{)f3Bh&?xDLpmXjV zaQuGs?&PgI{GEJij}v@`ZW>CZ_YVV2!)nLaJH)!3uu&4Al~m+x5V^9i$q%+que2qS zN_46+_cSdr1|@Sy%CJSIxl%?--8#nu>gX2Lm~P8qy^yN_;T~riCB`IzE{kF!2(gG! zU`8x7?>=(^*Uv~6(ak0NSQ)Rz#+0j9{1Ob>i1UT(OrEl0apn)+Du&=tFny%+Zinm> zQmT)uK|d$ILV7I}tN{d@DVU?8guJu=Zt#2`MJ&HTVVqp6)Uk3zP-SC@hAJtu?#u&B zANesE#!{i7n%ERMMGbL(ZdM6Nv<*3dZ5bgNLUs{|gtR}13j-FkG@HI4n_W07d;PY> zFjCLPU@{Rne}PShTEC3r$G?CMBU{a2IKIpz;>%|<{6Cq=Kli#y7B;hAdtLaZ#Mu_O z0JpAi?Pkk)xSKKbxPan+IBc75=V}s^8lyyf1HXD$koJ(j&?}=)nT^2l00JKe*H^90 zNA997@6RWwZN^Xq;hIWI#C0aQ|`;C=MttXdgvnXVQHvefkOOJv5h8 zlh%psL|UmPDYC0S_uu`rDi2#DwgU_|r^(FSIfW25xO` z|A-R3fNPXcfZdP2QNz-uh{jDv%trLFYx+tTBGk-}nkku3GDffE%v*s&yuKIi8)6Fv zblLYKA{l!LtppQ1563HmY$@5TwcYlU3@9ZlG`mu*qF*j%Xj#)3)r1v}UdL>^s!d3U zH&4SL6}i}xk%-ONGTi}G^&sm0(S6t#$_V~xl~{eWOb=krUOsxqoeqspw8(rgneFSR8@OVr^pFYB?12YX97_)cfSl(&ddlui1nfJ#Nj> z0iYTwVL4IxPG9Xe2h21uw_|J`A{<7x4hO?}|KtC~$o-4MP8|1(I^|1#EnlyH2Uz{@ z(BW@x`F}|4*3N&y*y%(e9@hI~_rvG)|BhmR-;T{4Z+HAcv1f;l>o0}&?|-q{jo}cp zsM)*fDL58rnaLAke1dF=I_1$B5m9dEZfO_Ho zL3RHj3Ly$X27#!j54_sb-P;Y6ua33+n}~l+U>6qmUkL4knc8vMU%_%L6c7;ge=xCs z{Bk_#)6TU^DCo@hzOwg^4E0dmJ`CVD}QIlqIg0b zMX=o)j0lC{>yD~zZz_@?BJojFOt^ggDo%CTI{7b@r7aAMce)Ta|KbJECBe=Rr0Bb8 zpLXNmTl3H*&r<8v5NP-v!(gA#_wRN$U{zk_J0XD*z*|DpHXJA*a52ZRzaP~B6R4&# z8g35GTutVyVT0z0L>D81gTr)KjRT#~?ir7&3VH-B)^!_9R_=ux*eO=&lV*PmY@O5OL0GO0P91<~p9P*o zrV^)d%p&8^2^+UCV}D;e|7S_3sZV3={QYU+$kDGo$F_Vpt7O>`tO(_mKN45a8{Sh; zq#zj!(I?#Wi>?anH#u_nzb*=$ zrN-<9WA?}uZWN!2UCo#57HBT5Qf?V_2U*?Er+j|NAg<%GI7ed?sZXzCzCzptz#?#( z-H+%YYO|bL1Ji92O-!tFo7=^f;+R^8zzM||=6>=7D^SV3Z%t?pkB*=5rEaFW zqdg`ZBaZPvyQNZb@M8b*gtkfe@=I)ww{`hX%voIJ;X9a3pF-yYbf;|yy|m|&A#XTu ztybq*=#}5D6oZc_SSrb}NmIyrA(Iz#%Y@T0z4A1<yJ5>c8|u55NLMeI zx69B+pUhNo_7q&JCjO4zZz7*s`3$WN8WwTu>d0yNfa!$TX*6U`f;;Nq=mEjJV9Feu zk;iFnf~gZOjR!lC%ovungJ1yu z9Z9sFgx_7BtV+If!LWT)KLbi2Af!5G4p6z+vi1aZ}^ z?G@GsrD3UzIokVnaHB2Whq3R$9oK z$u(gWLZfMJEJZd5mF*S}&eUi;elPKs%*<(1YZ{G6{f-(C>XbLmu&CO0d03H9B2M#t z9%~lwWXm)%Z|$%}(zS;H&Ljp<&_S`?L8EP))~eMw$|)q*!|*3U)az%{mRTDsX9z}l ztm@jLrJunk!~Qu|5Nyii-L(h%m6~G_!S!Q&I}MSz*0haF(xW~5cJN}!KpVRaRr znYj#eS*eR;{S0jxAn9JkuZeY~vr)Gp{uA*tKOw~%eN2)UuCSB-OKiJL06f4e{Psafpxan{@vEkLRKkYi} z2}7JwD3DfiI$5Z_AiXE=06S(Vu4CQ7LQDnM?b+%Tj&aVooF)8qeIcWe`zFgUu;-WA zG-uyxkB{~2*#3v?wP>`BZWY_LrHDG%H&ucpX_~E0;(2ElpJO)BwOF=FcN%`&Q`;vkw`-6#wg*vW1?s4 z*ze>D0r}*|Bl%)7-q5yrIP=gBd1=bD^4t-c-qc+F;I|S7IK7#kNx!2o$#8G5ZEH|p z{G*>Zj)~5hB3na+z6)h1-=kr5Rdh~j{=^XfHt~lyP-1DUa>)Pq`_&Vco zGI(gIr?Z^mhOOz1K3%@;z9Ds?Ndq(}e~3ltI7|g|D_}%!G@mzFT_rbpC}WjCiw)xi zs+FwkCzrONUo|w7&pY?e90XjCoczoRd_9SW4C|jtIMwzZnE39(X{_Yld!jsAw7)MU z$ML?LZ@hD*?H~nV7o1wI(Ls?l<4DglwuwPC^Axlfs3<|~V~A~lSp@Zg6$`kXdnw*% zNYK5B!qN|rrGdxByv{XN9jFoef*p-q%+O>_3eKq_^-f<>J{dQ_G^L< zzg{%|VS@j@1^!2D?-c#jf*=9vX9_dlV|zzeJ4kbPO^7y%hky87<>DpOz@WTz0A46XwO0j% zg00B#!meq#NIt$Wdkp#mRN&EkhVxi2Frl_h^Ah@~f5kz3N z+RNHiQYT@(qxFZFDGcDu3SpI?A?i}}oRQ9;CYfwVT;n*Bwz(C}8u7q?@BIi(Kd7R! zC_wn1VgD=ppsVf6_2+BILBFSC!DT4@6U$nG*Cq|D;J^FLx43|o zCd5WCTp|xjLPZ}Ap)>k~vwqIfMWJq3tkZ#)`g2R8v@pC#CC;#vW2;B2j;`tXnUen6cNlscfw{4 z3+F?f9`EUCbk02$ukp2(sP#`Qh?=X{Q5J5jz|dKb34^`+{S;Wgz2O;h6Is3rM@20% zdOw>tQPEU~{edIh>9KC5Tw6%SJHlHjxJlM+YbTWY&`YjB~xQWH+=TyBX0=W#Ly zKj@)Cel%7eB1<36M)pSVN`rttfb0Ed2jh4YYnSDtGL5Yh_7gp#IIT(Vt525S>Xr{Z7fkY}nLY&~jgoh~V z;%9hAOhx_>+c!AuPuZQk2RHDm5X>jbgfD|7GB+}*GBvvIqHsQv583w;&RPxvc0_A8 z`#~;#96&DOa# zhj^wOGk%--nsaNCHsco$>ZLoG4#T8l2*wfgA z5XMSYG55nPFf}c;ScIGb<+*a9OV}iw!;UBelCB*34rK=@+$s;0(JS3&)B4r#w0hhQ zVk?XJArh#lZh1y$WENO_%)lTuIhIIn{_wEV^R}ur`cX9~He4o7EPa*FRH&_X&Kev7`+>b7|nydttpV0q4+zFblCb#}>?;X@edS|eauM(ek*&1FLIK$HvQg%d? zRHZryt4r>>!T~uDxn6yEM0{!1h<%nE=-Pcxaq`JO9-rxqqt8<3v42un1WZH$QqKQ7y+FxTlX=LLgD6i#kd@O%fC97EtJV?UpEpH1{{jK>2NYIL9hXaB z5r7%=Q2rY{;|6Mmk*k9)rdA`5_vW+$rUV3N=4SnTxYx(2t!Yj6FX>d3q6UDDxDPGwdHP zT7^IiKoBE=Fy#wqvHg;z z0Oj9RVORsKj2vtM21fKUiW0(#U%~l5GgFFIa&z*i-qveQnphxfn4@Q|NR5mXp*E2E zzJvXS;vj+km_n^H5wSC|mBc%Be1lb~kR+*3Gk;}lTbecq3WU4X9lj1f-6rqSA0D%= z_<(743IchLCDwb8`MzK80dU8#^`}u>`}g+1GOu5hyxkJJB|)b4)FKQb1Xf(uA%t4( z4b!pR=c;jDB9Anj4H5`Df1Tsjr;$ySRsxpb-MTC?nTjnEt=!IFsRPo6KTA+uLe3H# z`1ifg#(r!yM3oi3ZWiC#orEeer?v%J+<3?(=o07+e!y=G_C9&HjB#pJ(CAJV7HN+qa6caH^jk1Di6gxaf88@&WqIb(A zvWd1AS0!o&5=}T;o-Ow*1I#0oS^fg%p0tg#Pp=K4f*M5Bqm&HaeKtSwtz^9p_dB0- zGEz_UU0ds=@;Iam>?3i2IDpU~M$kC#uLrkY=}jU-7DOftN?|CNlt@&?VDw!7fN^Bw zOLW3LpJ@G`!{j#=J{|bM7utd{L-f(xYdO)fFD>WaE-*y7w0putcR+Zukfe$#fl)Ib zUu*yl0~Uu5t%s5^X*0ds_WQ<%d2D$BYo*3`|rwEwg*@{7~9xe0UW>3$$#0we>2?^!g-*-T1ojIJ!3?mKm0&nw7!Q9)g$zE z_c3vu@o$dVkRkY4cMbGiQmdiC?u)q#(K&SI{0$L+NC1h5-0P)~s-|j2=RafIr1Krt zA`SJhmyY(na@;7@Zoq%DbMcafE&}u(>aM>y+@eurS6O30@=oMD!9bylF%ApZzemG@ zF)Y0TO$xJfhswlDam|3NhFJJBmhoX7qSM^HuL^xNYvT^;UGDg4(d&Qh$^SC_yoeP@ zrmy}Kz=%LVqW@;e`@ar=jJ=uRUnB9iSgPWurVGjv+DBx53qcsBVK~xY{BMF-OJW8R z!XFAfU>Z%0IfJ8ROzN9*0N%Qrf{Ad z5!(Q1PvM^4i~TUS&n*P4*SR5QWW4kv^vO@TA@nIvwINmFTe=BjOZ&G@C|eBIGN4;b z*H*w*j_18A_55QAJ?a*dl85EJj!YMvE4_|c-HAnaiD@Y{8MWP)slo#jhp~}7R#W6b z?LyF}|{7o0-)) zO~2dM#t|o^Yco?LVpE`69!XD9C0Rk=Bgk@$s9W?B*G-sffX%l8xolpE4S|XJlBx=o-%-lNBXs z#qt~fF_jGVU}Kruqfww}Eui=CiFR(B4ncNNJC+|hS#PNZs`hjzVw^2ky;&RYJ(P(8 zS*m74V7U;otkKbs?n=BzH1-LsuDleptVV%Eq?vG|FgxqRZ>;pNw8!$>woe`;(%yJ< zs5n$;ADrmQ9zhM-_=;K%@?689ri+QSAm4Yc(WA#+dyNtj*F0KsuQwjnQw#_s${H*P zf^Ek%t3A2%nHXf~6T=GL?_RJcqh^Dq#yWF+-<*v%nNBr5+>4G{YGG6Dvs#+m-+-NN zx>5FzAbaR{&@H$f4_6LmDK8uqsdS1k8}wPa|FoYQ$5T0ZKg-8QdbwxA#txgsE!_C?`10S^48~R?n z0%{Rf78zwE5Bxqxd7kFM7bls>z#S@PTm~Oyf7o`g@<$`h&G_4f)sp7tM z$Jp}lys$fxorpxkw^MV?q=kBq@H55I7PSHY5`;E?rl-Pemlj?K}v zGL!p&HPtU#TRsClcZkh2G{k@4ULcm*3DGbt(J+*W=M8fh&xS+T5y}UtpO&3)s817S zh7doA-ybVa?BRX{=FR(19y(k8^I%~r=NNl@d=lGmd91$se>i)`AW7bDU9@f6wyW)F z+qP{^+dXZYGi}?pZQJ&=ar?LTK4&BT_r$#?A}gx0@>|Bca=rOzHIKS>YrIeY;8x#* zqs>MITQ;t^hhA!wA50_K9>zg1l2`<2#j-~jzG6gh%a0BJ=wk1r^5!2hM+qz@322|; zws+kc-1=esw1TqM?^Skka^&aEm`cN66DD9@edH%%zu4*jH6~uZ)o*m=1zsA~RPju7 z*v^}M^GSp7U`1;_t7;CpxJpvBS$?MZ*Cgd7^lG1@W=-NUSIlbJ6@yI`^>mRmfW|2G z0OuHImQ)Kp{CkeWUMIx4qeG{s2wZXtg`H?rG6MYlSkUuK7<^DzG-^E}D&Rw8M0M#) zb8p{+WFG-=EC2f=65k85-)6=mcRz3?1bH?@aW<54aR0gG?25DL#%*U?#m#lK^6)AF z=eA9H?7XUA?t26k&S0X5SQZ8&4P96NUzEzTg8_7AxU-x4iV&%AYp$k@v=;2EBzk>G zS#>5Hb>hp1fiouSzGR$<7=Y{_=0}amv>{+>yKVC#(`4*QJF))xXRvAdMizkLpQd5- zy8u4C23_ONo5u$YqKyQC`97XGW6u`04~U<*}L3{LlN#6Js|B)}R`mdVC51UmWTbtN7Hf2dgKBVFUjlx`qifICF=_Facg8bCLEBML{mcPWUczekI$KmIH>R2F5A z-IHTN7s#oV1o5SuX0s`oJ)Cr zsDSeEYD#PV8iu+kf@;4i+k8WFOO;wneoCX%V2xBCpm1->FIs=c0bDf6q=J@-sn7rv zG5qXQwy;M;GXOj@_nfH?e403L-nW)Y%B9lcEu{*AoV0PxUr}^$SQQ+d7X@~8NPNMi z&O20c?rAodZt5gGiHFY{;1jma|%yC{swe1ZEeqelR{=xYiG2$Ng z&#Q@Tqn78rmfWBD{UZ(@MC%h4LJhmHuU1+?LEdi-q<#rc2Idnb*%W0fJv*btbdEaG z=61Ty_ukqv@U-qOOU;DjvimGltine!%BOJsA#+H%DIBLZcJKOW=GYR7PGj^mQ#X>L zoJD0#Zz72vohghQu^vBF=d)%rC_}c)>I6-lHe4G~{yK>qTl+#+&;RvIw(D9xS%MEA z6;5@OfW!9`laM!#SQ7Ni6iOq@v9&<7IRVN|<_rEK{0dkBh?KXq3Z|9^tCC47l|5n& z$%d`Ff|cSd+3ZBqh4=<0ZHSWvADU%>Xyrn3>Z-2e#Keh(6XtJMLhLcuqN;5MV|{>P zA`n%R8F^W}*iyaV%?djRB2vxjhr2e+kDT@OlghQ>%C!O1obNEUs<>VvvqVl`o`G)B zn?jeecDfON5&Jn4Vq*O^NDhvK>)xMhVcj4lcbk0#`}RW7C#(;XLP{tcaie6nw``DJ z=F!f|COk77s7uJfd(BCutQ_&_a((Ie%PJneDs{ntm^Kd|jj@HJA< zZ=3;u@~@M3|MP`I?i+Pb{s(pVuXKH<`inZMI@%`z5vbt?5}lTo129PLkXB)3NpggW z780xk>`&YTXaoutP8MKG>&DE+%1!n5^}#E?N6Z;dxi9}uMZV4_)4DitP)`_24*RY4 z>-KHkt@cE}&yRC^p!M5O#7p;y&|$!s(L|`RdtWH!tqS_@Ar{pcrYm6};w4zx84rp+ zqrgE&42VccLT^sRUsOgN^ACo!=i0n1gL`DKnZNq`Op%{*A?Ep64ML)`?s}&)%{-3& z?ZTcW__XSdM+o1fkytNmg>T59CO9LFyJU`ctRc=7e}IzTd6>W|Fl_~F#TARphXXHr z)q4M$dy-k%TSXiO{;W;VpUzR{r2d>gqpd8>Gp)O1bfOLw7UI8XYkW#?K)S+g2NS4Kj6o=!_)eSq zZcBXcsmFSA{fDXeG9zcRMi1Fac+_095GflV|629~=$uXM(idkL|?i#t>Mf{=c8N!n_`im^G9a2~9MaMi-~b0Hmc zn9ARDW|@z2m<(RVZ5iK?>n6H_+wa5ET=lVoGnTu9w`+8i?cn)ctKVcq+`H@c;?isl zfP>qYy5nA#tb~8iYz=z3;2-G;Ak!1LVlKr*JlzIFAZmIC!+rzpx6u5i`4`4N9^So-mEGpKYpD&8Um_M>6+ zfhu0h1$1*8?qBU`e22*cmh!xEdNN$5AciPi`6~iIK9Aeiz?X_5Dwkb!CgBu+Pk;RR zC?eu0>q-$VC!LR`7ga#k_>tS*zr`aA0SLhV)Uo2Yuv<@Q3PMQSeMm^G+MOC}CbJ5g z9Nc^Zp$+#e>es$!nwno3`1fIOp`8};mF22(_3ShUh>?#m=te(zUm_@C&qhQ zpv)5vZJy_9lt68!Q6fI@)67?RwT4OIcgY}>*Fxx|@lmY}_$yH*U>=9qjV{#oj>&e( z_Ta{K5OqZ-a%;EjjZXgD0E7+N$<%%R4f*rrhW7b>t}vxn$fPEL57i_y&_(H-px!bTisH$$B7)Y$a+Xv5?ogp*$A*lmt`D1$p?p)Z z?pf2QIOlFA4tANse45g* z_ma#O1Na}L)$j?*alVF4(?sw=LwMTCR+f~)|)Bw$BVi?*3ssL&Sm9yCQ z|G~bd5VJu+epBl~-#z7DNx%MkKlwKl`+tLWD(m0UFC;!tSm_k-q|Ce$s%A1B6xIlk zJ@7CwA%z_G8(RqoESlB9O=weoQNJEc!Um~ZrNYBZRo|qwdN7e%lg-NP)6>%{u1%kx zT|QsW*a9fABo;ywLM(e2Axs-#$WiPh0pEiUWOSMg_9A|vRapgDV+=X!YHu_Oa(}d6kvF;jdb?_q8p)RG+a=$%zweMZcr26*8F3m^%oG~s<&u{aFS87> zU`=wfN$yQ^gbmCkr^Sz_OMPOH*;|2E7^FF(%B&)9bNST z)K`LFybmU~X3;N;I?rym+Z4{jeq}T?P!Y`qw<57mu*hzr#C}C;ycZB{msJmltq2Fl z<)T}24+Gv)DIox4LDkVYnUmJGG?Cv$7_tVRkNFzAmQwi{soO(wl%Y%?|B`QzN4Xsq zc6w5vt(#L{2szqjgM+VIBMq6dxVY}L<|{L0;%NPYDo-7}3#R zekN9#buGYVmvu^L8z8c86)bO}D}L|&4!`2H;OpO8!}Jd93ODT#9qbvx$mC4gZh^HX zYSOn--|(Aw&eTLdr|=v1-*;Yc!>-nQf98HT1L^}JVf{_~LRYvD&557c=h60?(IAA? zQb!1)6L&dFxzi7aOl@F$>9)5y}7x-T|(0>5oi1#4+f84kM|3B)9`9H|d?|NDg_^zjb z7GfO{hCOs(M@9h*5e0z`|C6yg8U_Am_6r221-rmex3ic zg1!@FTFNS`($km#mPQe|dX?ijjFS$4_A?&bjy_O(RW7IUy_OELK-u4za(40=CSmld zI*klT6N&dpE`=FpVZ)>zlmskTEP8@WtmcKZPKR?5H>odD@vN1ajMI^^t&D%$%2-`I z;S6e6s%YQSNf1EGJ-8qWiZ0F zytlzB(t4}YkzA$q)@$;H5}~!Tf&1)oJ8j{XxEv1i1N6Af0Ar)2A^eB+@44S)wjv7b zSH$1rNTXRet&IsZQDNDg+zs}LU&EE-JqKn`^5~r0COvBEh`;NJD)9VH@4KF$e$USf&yrr_wi_K-Or;FA0)9USQKai0fSGXYeflPF4^Bc|xO6KqJ z-eYk!L+Vb772{zZLB)iMt}N=_tr?R5oyqIf zvs|_1thL|e8N;rNb7dj-dh_s&H_gohM9G)=5xYp@p9(xn3#7{xB_8vRmh?(TSRu&v zrFoifRgh%-+SY&*R=IHHy7t!&rcmP8bUEZHegLImCBk=z6FQ` zv`h3)Jr1&+lkGhoiNGF`&R=zUmTHkY75J-dwRU%JxHh(#$D`;nMpC_4L+Dxk9wD<$ z1*+>yXF8aj#Xy$km{w2?Op3dT_>DDM1iaICT&r z^eBU*Z&yG>(@zBWO?W$;&6Azex16`)(_%D?CK3V^EGUYTaf;9pz5pmIe2}n?hd{F4G4x8U0RXX zbyJQ++T0Ji7Ew_#MuKL?(51Ft!EN#Y7pW0lL1%e|zx(_I&k7G&hkj^?+P{2ssS2IG z0tCxWa~ZKd=@2&gm!Jj}&*;O!#z!JrkqU2p0gUhegZ;#3&P#~>7Czv8H@knONd6a_ z$NyA6Bqy%_lRYrhO>NqoN&d~kk{RV7+FV8Y!#1##vrczNYM$51 ztILAf=3-fQKdHI(c)_Qi*B*CnlxJVnu!DbNow|MF@hoQjK*?vN4vedawrd`s@H?~V z)Sd+nO?nt^G*vEIAmm9_8?PaQvXA~Al~%yHY=ir#ih6n1Y|hW#6RuF32!Xr4=4Tc0 z`(_sedt`H|y$$iOHJj!BFLv$0FSqy)vsXkGX`92VQIk@U)l)QyzcDspb3b3JO_Dsr zT3d)26FAg5ep3+FsWWJhzXk1ZmFStLba)e{lNKMU4OU@qj3nplCQjkNwB#FNk;1Wb zDtV=l<7{~DvTMm2zE$(9iE3ES)>bxMtq4`SAu4n5WoxJ03obmc?4B{SO7C;Qdsy;r zFFsG%Mi3vcT8tDg&MR!t)`@slelF( z=rZ2XCH4sD{UbfDAAeGdRze*oQmFbnYG_nSD^`C@*qSRd4}yHQUqgsoiW6J5#Bc@5^;2A^zi|#YEP&urs$CnpUAiNoTXxfNln5}Xzy8dpYCRBen9N2GR1MB~{ z#`C|`4W>^2-h+Nc^L&dMu!4`5Em+x`wt84Ky}Sf(fUQiMDf~=?HtDMfe^_l zenmscvD^S+kIz4WnEI&(m_$UdJZT%pqdSo>=2h)PiLFm%u6~tS)v~Wv9^k8weY>7l zc|Qq>MaJk^mh@gSX0nHdAuhkuQ#%yMQ7Lde4Be8c3Hh&W5{1+f;=HfV<<;J;kcVvL zla&4pKB_pJy@3fqR&op8#{yY&g!&3Y8IA+o|A*{4Zw`F!h$s@A=<~a~CbvAagba1hEQuw#aWdG~(zn}gGt)dC*j<@K_FV54>(vG89 zchK0l(s!p^N9Gl63pXNGYcr}bWIz7=D_*^w)We{W_R)|oAw)>T*aAf&F>Z%_M+mo3 zK}+}sXWvL`14lwwIwwFNA)x`@67>#2cD`ulJJ<84dU-ry;h)QNuj?$Yt>fbqa*jLpoqRDM2uvM{}$*uU|gYj#4lyBMG zG>8jzXWs1e;RkHAFSW__*ujs3+oHG+DU*-lC|~-lPicZL`q*uYhaY#o@&wn`GVUza zIz_dR-Wt6Gk7XCIGlvf_Ej2hj=H0v?hdNVjyfiAm$*!f6uM*)^Ya%Gibt)ZY{fiwG zG-MauGlm)+5YKT!gRfAciy_@1mcgHuewR9S%9w@2)F0mColHBM+Ww9@8ZQyl;IQft zfXYy@!x-Ng)7?;-f<5KIVVvWnd&hu$X4X@hlD17wE$z@bq)jVwajCN1uFY*XpFEPa z_F`|cU!7|_#VI<2=MX~>>${c6`_aLd$c*|yn?|!lhI%SP7T?N%GL0kSDL-)%X|j)9 z@dQ{zljjhFfUJ!yoic6gmk?JzGN4E|(rU?NMDGGHqe)V}F&p0RD75q!T{A&Mi%dv} zgu)ys2%Sn|TNZijHx)+pnyi7%D!6CH%b6)Ff*x4K#!HbauPB;kCQYW@-axQq_lnC; z3q)D=is0DD4AnUrN4YebGbKpj&hYTsrGAj>v{^?sMs;>2oApgJ0O&0{Mmk}uf;O!a z0M8vxLFr8FrjVY|DsBZFb`m8Cvl8!Z5@SiN^(7_L$_6~8&(L}V4W;`3mna}Wbg?!^2qDfIH6c0OyF85%(x|UMQlaZ&M_im#8M9T92G zqMw(+y>a}9qcj3g#yJ3%0OOhPHuktEE@62mBzg99irD%;mT!=9h#cMEQJMAe?wDbS zxjXw}gdi{?GOM|!cjC8Er?Zjxje=e$Y13?nGGlb<#; zdm=1IjTr2r5Iw8Lcw<1r7lkfvb-H!Ubx`ZgxFDBh!aXY8Zds?sVE*n!)&R^uO3@5G zOufK`;nacZGpwiGJiu6;RpIpM{;i-A9XRN4tFPL#+h%2C+?B* zJmIy)au^fB2j~N6^r5HwF}RR}ClK)G=kCW`Bb%2SjQ4?;SQcYQHM1|z>zTBq5er#{ z1TaAWmKBt>aSWOzj$A}(M{Uo`htJtM2HoWA>j4#zKv5)B=sudDhK26L2^f-Qe=G+o z@{RfYfhh^+LID+^HN&Ke#xl$otoyYVWaxT5l@o}1he&WFkSTqFS+rFgp1{8I`5w0-dlx^7dynv^k+`XA5b>x zkg^e)Pd0#CH%6^pJ+po*yx?RnLmv{(3Ck#NI>S60Pykt*Rp^bi=t1(67;U|FeFIn4 z9zhj03#a2Q%~P2~*#x=M=N;+ICmqSnrybetxqTJorftGSPCNM!E?cARK!jLgC`XmZ zxY1dbYZ+%9nNLvtUh($e)76m$h(KB{TjR^+9rDMxE#k)?E*ghnQ=J{s$5f=KWm2+p zt2_L+6UVO1&<5My$PyDGG(m&F?Bqx*l?$2Sp6={Gl({+Qg>3#wOP<-E3BLnoEC14L z7dY#%;?8ghy5++>RiP)9G#eNZ>ZB#*!1XD+P=3U4-kW7B<0UF;9m9z&$j^zh(|;@G zPuV5=C5_8v9xTvxo;37VEhv>BDiizE zN;gAhc}b$zpoc#ic9j!?XtTAIqt==6U_j(mBj<_+p6Md7iV8SiYoj9VSs{Zx}OSdkw9af$Zz~p=g~}?qUC#5d-`xOYv&6N3%nqY(K#mSGn!En+ZD| zhtJQlt1K{1tlpKYPrAxYXJzpCO%Syx%SVM&bZYN>vxFr@>g;trOvaXq zTxDK;wH>__CcD!*U$FS|z2C4j;2hU_0-uwAO1`M_>KKq*k1sB5uI&c!>E;lV&6DmL zHqyQ-B&w~pBbtvh+ng*j+QgLIJohu4lLUXU>b?A-3SJ|ZykAIG6C11t4Oe{S!u0nP zXiA&Syd?Bm(K;iM%wJU*lQ3zU1UAmcjvb#SLIrEW3NFjCt0@8Qc>i)CqOLDV%@Zk@ zB}XF-N_%CZ%|E|EG%sW0-|3h|)UbCkS;FPR-->Y2Uc$S?-7;8eh{D`A^&j{ffEi!yk0vxmh|XoZKDuZ*6NfcwwKmLLJ0y7 zR~D3PfNXyx47QJuv+dH!UuyVqyO2 zgflHo#q$`2dh=F{1);Ok(2^?h0*FR(E|};pXP42MA<}CG>8H!?+ zpK)IgpbLkZ1W*u6-eGEB$#3yu#C}XfI$ClHn^4KIa@ymo;5AN!zed*PvsBU_-D#et1w{+%me?$X$#hd4> zbKWrgUu=mkru}QXbJsNsd0H~~hf-&m7>juv`@4dcjeTG@2iF}par5}QqWK5iX8F7s zl_cj7eo2g5vTq`?E)kW6_!4HM1fA2of>wa%jQYNk*xcmH@t@87It6$FS<{$s@o>g% z-}2iwp1jXg3>O9YZen0YpFMkeB9Rh4nw(IbbR=};hsVYzK4Woxe<|Bzt^QS`_<_br zUW29&^2}b2?cbPVbsgmYW<06-=CrV&rv5VtXLx9qEzG+@vvge1xg15Q?AA0_1^ID{ zK&h+>BLA=}=Q>dH7n=MGq*;QQl?3!_(g&9o8H!aoev~hsLB0dYm5ka{LZ=p5k1@ANN__qFLVb#D5$D3*yWw1C^b#3k7$>xWdTD zz{vb>M(i2b9L(tXqV6AKPpoiqyad_EO z$v=A4!Pz@u#$z=2`ba&}2>LL&kczxgXa&Jns38p%G)Y`LY&3vzI+WMwJK&am;3wzD zPmc5&C$u0i2(m~LW`zKJh==ozfh!99|NO{~!eGlHMQJRPAei4(cHwfe@hCS68bhzt zi#^aEp#{RcgYW^$qt#vnq0?Ww5TNMenBK(kd-Q!P)$!5Om?fiK7{oyLc-lnnL z)s(K=BMJq_$#x&1^cVZ96%~L-d5QyO6?`UbIqc1NY3Pek=qng`n#w7;B|7|6p7-0{ zdMj4@RB}8vs&0~t=8=7v*|*z)+!Is;LG5z2Z5)*6VJ z*A$v39kXdW(1xaO+F1fLBt^>W4^B&kgqE@1_pvq~r^X)85RFL+U$WS<##I=-#pf`Y z@JAh=)(<3ANLH@Ir7769OGJmZOm_7$NLMr9oADO35^` z!x1xKF{Nw?&vtVagkasNq0@cKb~4wCShNzxG@I354_tlDq$&?dz9{_!3a2#$;})$g zA!q@Zsw>616xX36)e-d&+v5Qy7e=1v#Pmp(9Y2vxr}8(rSQ2nob#b>Cza;6a&L{Ky zp^ll^8fKV(hZsuFF>Q~CpO;O!IEvfKR))^V{bL=! z7-u38GKHrOt<%B2$nu2B&0c@J0eP77vuAWIOTTKB0-8OyEhM*Y(EjqWV<5OAgLBHL zcBGYgK+_);igsxpjUWJZcM17Ho|@k2Gsj?Po_B?;yWUH#O*hQWt1Sm67M2y-K{GQj zU-ZV`&Z9i+(mLYlizaVKDc}C?rM*|j{-G6-zqG5}QZs&XJxdWrSgaLBpX;-__rmtj zkcXqps4piR@%dj6rhkN7@x^@(;NRG(=(kRl=l>R9`FBL+e_3zm8FVXQ>4+i-OB%y2 z1FOOT{0nJVGb;rVg5+cCE<7i!<8~}OwkO?ln3Alwkk9#1Zbb^Y=)&&lJkHnY-_G0C zr{(K!6B%!h)VJr>#j!jLPfAo~rzx^7k{r`bhmJ*t&)Q7uR-${C1~sC$oHAU&8ZgZq z4?z1pB63y?_afyQ*{dn79cb7_jC$MFzK(W=Z$EU9Zd-sH+uV|H23=UOx`-!#L7;i|19 z?%Z}wHQt?AmVWHZ@4~15Y8Qkz#DJBQoZFHDdL6NyhW#~@q<-T_Y_XpXBt+c2j5)}j z5aa$pxncDLH?|W$D@o^{fnf&(2)O;m91~9Jgd~s0sFJxB=lsIlTO=6$LU?Z!dF^tjw){ujTT5H)`yL0UeuxgZSF?>rAn>FA@CAd>){u`*pK1A- zF|c~vu&NhFsCA3ndEQ~WV0!vRNj-JueazGUkaa*zpOBM%W0&dQD~#p;eRch7*zP|l zG{tebekPktX}D&`=Tdke4|gUkD-<_C!6-hiYFpRrvCRpn8B*JKZ`}eg;K(aD_3NaoGOiG z=Y-Uy`@iB$`mD6mMd~E=D*o!w_NrelWK3m@**Yfms|QZ+dwTbc;J^Neb}&?9Z~n^O zE%#YFe$_ZDdK7BeI&LUdiAmK(H8c<(asTWsvM&vbu9b$htX-T?V|yZj%T$%cU7$qb zF8OnejIfjbK4a1)=mUnq<5a`oiSRQDH4#-#_G0G(^FKl3e@c1p$ ze|^)xE%lb)SgOZ=l(d?r+qwwa=a6*LN}2K;1#2a&WuFmGq?PdLo|42Icu-=CWTu^f zq7AvKm9$vGe9Hw7+9wcV$ITojfl^9SE+m4y1HxC}50DLPt_WiuKFRv1g6}GS+O)sY zIlcDt`@ruJ^qvo(DiU%B;es|7z9Ai^pC_K!(ZMj@DD>y9)E?=O4s)7|W9L2+Ze^qqTCNl`gM2C`$Vu_Uq_i%|~C z1MsG%w8!$aRBfHN6dwx9l+@_8>yx1C6{xK!*?8EYgb&ux1u9PQKikTS^b(lcj7&11|~Lx$Wds{V{>fDGt~qxE>0& zjHRNTIov9O7tFT1rH37AKV9Z)$kR~9RFJHGXJQ#?Zy>?U@1_O&X&wKP41|)|RAClt z-J9S{DN1Rg2sj=UW@~31?S)+#jumv1mXS(*aM00vOpxT#w7tNgk#U|V%#U|WG#Wu!DjTec?6*o~(i3b10x)lAZcI=(^ zhwe0%nZBgRg*Ia^KW3TzRs|L~4n4}AviDHvw5fLhBe^&EK1NrHBbK;H7TDiQ;n)Q^ zjwjsgd=IwkhDY-iQYEJbQ*mU9YZ0c4y9leYsWmW>stnT-(ZVDpCo@Zy9JT5Q`c@@y zG4`&I5_pB};=1Z=wp!xvms71Rl@w{wL!;6b>_!tf%P6bf9__|$DPkmSWFZ#$k0h1QlTC}@pJm;-T4McX z)wNlLSIC8oj6I=9_H27G+%UR4CvHIU0ebciXoa+2(C<)9Lh9W0tWD78zIV9@s@j@4 zjGT6|WLLeZ?m%CKUQq9W27BgU*ZH>S35b{*p+BE?V+0OwJ&_7-fj|Zd5;a7^1+zE@ zMrqm=Pn+d;5RFPg+!K&|yuoA72z5k53C{t-Mpr~W7v!Q@1a7wU2;I0tP@;MESXzf- zyt3AuT1nyuU*%AM_mCSJ6T;6PgjelbBpvkM)yCL=HI%l?2RlT|L0#}2_eHTNLeyqQ zZ|L(}>Jt?=ZVs4c{U*elc5cQlzdjAmsl1>eIfb@s#3gTy3*0l1^vTfWpbo%9xAn(| z9b;5?W`&P}oIOj@Gla)lXBYZx`ut*$U+k>Bu69a3DRu(yyzfaT z4HIXHwSuK!Y~$~RvhR1~!`1ILvt<3d5a+Y>$HBtZ)34^CoMimvsukCe(v=z?Y{A~n zL)2rR&ZC>egyBxJAj2xs(Z(tKWtL_;a3wqSRztrAtQCZyHoIk8`yfLS%xQYRkvQ+m zECspiD&6MCjPL2xUOll^2dCSvF&>w3?M*FjQw2{`6mn*G#q2Jb>)NLjcALxnV=8p^ zv30?ZaoL-JgRi7D;mGqlWA%q z+2YBZLX`)DAAb)J+` z7a@}`A(j>1&I8s>W9xMc?pRUSRw6Uw9R@udiGHS;NPc)+h$1FiBHD=xChP~?mLP(V zmoF`}kgoI7YeH3efC&yZ8zOC*+WR80vI(nbzaju%8wUvp$FL@|AeVKD zZXx~78~6%^j=($7A%yr#!N3b5Lj>ekzSjUbW}JR3-~-E~vRUVTtRWv6<*k6KK6NsF zNQW|)7zwO=^qu}0&_SOc9{rRBFwEiB%xw=b%2NaIBvt|He`Kp1m7qeH087yf-!ql$C@TTrsgN{QQ)1Fg5DdN6oXjG zG%=w?d>m~K21RwwuSObHa3%%U(nrG?)-H zG<_TrN|qc-5*Sn((P|%&ME_|gl8`5HG6qoq+VSMYmfm_jyd?j4eZBIh$Jg8VyO;jQ zQ~x|rN;vGtN`xhR>`Q#;sgO)~rgFlyhcadeLn%+kc`t@%gW~iIqXN34k7=9&b{7w@3B+v94 zKSBaPIjBL&9$5B~Dt6IiF0<|yn)MxHz6jm#%jXHeyp^ihXfe2pUC|`<{7$O(r7j(b zRm;VUz|PZPXE|J#Ac<~|+7x5uMY4vAxw5-JfZQXlpNx7G z4^SNJ*b95fHXFTx+wd}w?C3)f*N1i`Ii8W<0qJ~nKZoZ zxh*`TOsSv4%0)QhB@=086h5)?9L^Pokam=WLf3lGw+)^w){^j?L)@tMhUxF^&`*fc zp$NJxWKkz$+Ddf1C~>$}-+XNNP%+s^Kf6aNr~882&J@kg6kwkZu`fCP$oX7U{XjnH z5IppoYu3C`YlWBtsVpXwsHl}f_i)_>f4;d)IZW@k?M`C`6#Rmxn z6Hy8lV_R}DSWVIhqJaT$_H`oDOdtX5!wT#Rp?zXKMJiI% z>?E~2{9}UI zN|tg$zfsksV(p@7*OR=G3esm|Zj^=(Mt6`j`U=J4)y7&p?i~j1rVA!j5IC#aD71qL zoS*ln_+R}8(wg2@SSu=b6-F+ajl~)42;m=xC;XEJ2Qw@?l|-pWD3;S7A+wMpTlD6` zm=sX%OEa^`nyJ^znMv~pMSDqK!qh!|t_reAvH+`u2+$LggZ)t|b66C`gz$U)8X|7I zg5W-F%_|-&gc4jcEM%(G(~f0Iy|@aeZDdlHEcgZf$Ez3`zhT<~vxL9Audb8Q9ezjF zYhgw=*z}<((i)em3==JqKufAwt*EeB9P=gP<=rYw zL}VibrLP>8fD|1)N{Cc3%GD(KUthxylYSH>_hTM*QOPAWoMNF3GX+pm>sX7p-Ayez z62D65mi-E4WCxvk5IvcnWyA&Lamk9bsm)c`ZxtqnJ@+I`^fNm>6l6Hafhe>JM_@nuH zvleHrdbSch?oz9wayTPH-vN5PSSzn$ohOFbh&3;oU2+_P7oWRtwviVJ;h4vOb9iQ| zG*6*RhpF18L98z~H#oY7CYx0jIiHZTxLQtvY}^b-pxYtIYMm#FNjrF&VQ|XK!J=6m zg9ujw>&)4)a#ubGy8GU2+#O5zjodjZ^9YNv`$SwKu4IyW= zUI_IyHkFjfRkP|g#jkifM*$Nt{%ydetsJ=U(lua~y0@uz&h=9hQy8m;BBc>l&Z&Ft zsFG>6aBTe?E8Aowl^&Pg6AM#1R%stGa^&N<6p}3smaY@`_;Cw!0vI-`n^TK@xSL8D zPXJ)q%B%daq@;wa*(`fl7Vmqf!LA#F;2{H<8#gOR-aZ@JE0Nc$I;}sGo)nHn;hYp5 z%mORg&)yfyp_^N4U$$RcT3%djAEgmhBbVM4+Av1?O zh==jtbD>O-;~*gw$k~!DuOL2GvKZC4>T?*n3)EP_F(eorut}ef5{njmS;S&;8-R3n zk9|LjhG5)hrpHioBvrV?p=U5w`MCf!X!@%dGT)Y3)ji%xh;$*JpX9h5^E>?ZmjSC{ z&HNWcVJrh521^z1Jgj}hBm$4X~oHrZ8h6!hV;{#O(Kk@u_duwB3XLGZ$^Rl9M0r%cL zkDBYx#^zmjn_e}bUn7aG#9khCtSa(qp=YCKN_>oUf9OaS>$iQ68>@eVo^c_91g(s+ zL)CQL=KAMzEL;VZ@cDPxzU`#@r|J^6zo5<}YzD5iL8C1#$@l25GX>&?ja_U+Dz`sncEy+7uI<33 zwpYmsy1XaT0b1?=D6}bPN>x5a3dxb|1Vl0Ac#;bv^9ZCXZx_&UupR_Dz^hp-84m!z$P<^atie741 z%bgz`wq|+C22*M`T6+tvX}4}3<(w)~cLanHxAIH3VKa}K4&#Jkco;U$<)<8yJ03b8 zJg@608O@V{Tt8XLm7pX3A64a&ss5!~;q5A~o`6~f#kv4A+X3%~gag?ER~EH-@byz) z6gB$TssWIWbXHFVq1WmjZ8S}5n-cJXHz^&_n!pEr+aQ8HtJbmr9ShgQlG03}N=WU? z<+6kF<}1M!doO$oa;g1$%P&}{dm&GOKY=XEC}$eAg244LT|v#v>3>bPxVjD#Es}gcf**F@sp%5ojCz4t9ry1N&=WaF z^?u%w$*smJSN{#a6^^CO#$jgT24`8h$`Simpz<$_nlg==#Sk-x+`q>&+8#*OErUd<6Q(a*vM!Z}JUdxkp8Zmrao!3!KTTYiHQdw6gkJUH`S=k_sUvaCHaf&C)rHIv zuT0$CVuQ*?vjy~rjOY~o|6%MKqce-vG-KPgZQHhO+qP|^V%v67vCS_|#i>-B)Z|Xz zUUR$WPOtfQe($}WbI$uddbMH7IZP9npx%$x)#td(&Xv^X+>h|=vU{?0*t_n|CZu>e zeZO)#Z-+leL5Niu4rX?uj49<$dqw!HO?VQNKTuYa1IT;pt;`I}{OHVc@COe)q<8zG zz3|s$KGT~$=%gU0vfvR`z5o;NKt;RuLhQoCJCSUH?;D%LXfY>~^~?it{VPyAbA0fI zhG4;q*ETpC2KpOU@TMto@J6LSxp#Bd1F(VmA(yCvkQ>=PKyRe$s_~>35?2nCP zJv&*92Tb^P5G^US*Swzahc&#>RX;SD-*P7Qn!5pR4^b_uS1YL&6*L-jvjz^-RKF=+ zte(H5Tc+7*XNuj+rF;pqCDub%B zU5~&OfU@n9R+3D}XPxeta^+gqkDPgd1{PorVOCvaYGv^amHss!8^T_xkG}3?@nTgN zr?duTd{$pV@MN}SFdOd3`;nIYL16Cl05D7OwXP5YHgz_1a8@7uW!%?G4U6KTl|O2q zPH#wgyz)s%BvkmxOICRtHEnn3Ta0FVHY?T^%p$!F4ONXy6aejw(v&;_@1M-GXIFo zujg9PuY=Ad9lQ~iPoCz1ye?Bh_9vJ9Ne?v zF`Mt`_6td2=T(<6e-6i*0mz&0ShT%P0!N2O<}in}+gs+%$?S8!hz4>fn!MjcwfBKC zo(FOcKV9)}1rNObO1HBOxc9YAF34xzHK0KUNDh5f$%FR~3je}mMN{Xyhheqn#Pea$3 z$2PsW`{PCa1LSG{DNje?s;T1dFUh-+N=J%ZH_>74_%pK9><-799nXE=meBbOxv}EJ1nLNk`O=O0V7LO_@?G)zI`IT1N8WLU}U`1J74$ z3rdr8Zn12x#rE9S%?)4B8Q%pP*|$5W`iqpl10<3AkEZgxVP3xDE3lFb>cv%_!|xv2 zD_BraN(++5)_(qC*i@TndR)0o1k6l!s#Q)ajO{j`+G}fv&N5|^J0`GtMPdy^8w-2& zsEy;5U>*H5m6i-XV(348fq3T1a4t0NCLQMKKhYYZ8A+d8=6H$Ns=bU6t!gs+#Gk++ zIM+IRArN%p8-9UkIM=fGwiNme4hN1Sa zzCihLxY4jsekt+A<ncO;(wN^&XFdP5sj@DY0MnC? z8hXPk!wE5><>=~xiwlg)?M?c)AsosS$JPYJJ||R@jhUc@f&WdrCIEOKF-M{6jn%tab6jA!|M@$o@ytmm*AidQEk+) z4+8xsi2emlcZn8%0(*>s2}zTL%@=S+Uj77Rm_&GDEbuRq*Pp1AWH#tLqV`K8caSFP zqoiK(VEzRh2^Si;%mYOg&*(FD{APWz;#6$I+jJtUI?FJl;YLqR9m`ew|rwc zq&g`M5me?(Kin36a)O8UD@(T&EkRHumlM4y52BT)3uGEY81I(1sj*izD~&ahq3|*& z@RSBN2j`XkB_^c#Y@qp@`1LQ=gnz(3>}p?i=$qTz`rftvf52YV&DhP|^*=dHd)aLz zEPhV;Z8i&?OP%XegB=ZfTDo@u_8+$L&8e1 zgeWKNuy{7(SzCg&6h{f3+AHd|WDtF{YU<#X*|tV(+Uj&{+gjIbY}<5fb$zw$oAx z?|z+^@(^A0o$>?S+CSUGI|;W`SVk$LFc9cF$iw+uc*FXgxtYWo{)nQ_4-fhV^#>=u zy?%v?frHcjy&p-L@1kBnf+_bu;v&sHw0<1Jk=k?Bfcc%E>w~591XN5s?TJo^F##&(a&J%ymF^phT+9+t>@9GR#SgI)OoL?sD`Z$ie9L{Fn#51hq zxcjsul<2yHxOCjKTJetx)b$p7cdS*6$5mxi1MyzB!}@l9#AQfUUaNMLr9=SX)^#h5Cm zp9ewFE!Nc-CyC5RNH1jV*mH?XTf1O0dn%ocTTAcg@z{x@pq7>wCI@3BPd>(flCv zGpkZYsLCv&8AYydMR{_;KDnXLpcWV^3If z3|st(m}(!$iB(?6jLMgB?J2uosWF+^hkASzKpZQFcwY4>pqWr$ZFu54roDw6#aIQ?-Wll0zjc+2utbXaIrlEEzuD?;-XzAlkF7-)N$ zo3k0VR!2Wu_XpmdbbbRY)6{Zi?N8QrxAskaYtp4J4&&m+A{_;Z%oy8HIh7lPB)vT!6q&SOA$$4j8 zSeV=ET1?exhnOqI6L2qgO=30{L9^@a#>nm?pMiVfIz_u@6E=tKe?0f~#~`W-D$Xqi zLc;9o+?jGK&KYc3TsUGSvCGf`!7#(rG3%EJ&3NG{_;DBZ6UH&=ValUJGt@-c&oo+o z3&TEh>rW0vqn^!1>Tb%+j>MYP6C;+CA}(x2g7`j@856a&9Gd$XZHa=4i+@=gV~oakK1c zEOM#ET6+a@E{kALP7Rc@+ehi^X?Zyx_&*hs7drtchMsx}g!8jFYT@|Nd@HwL3w+{zdH?L`-7C=d<#d8mxBL?Wgn{S8nBYa9R2AvC)-KV6dmQ za|*3M(IwlmQzZ;8#x0N0kM?FCIUPj+EVh_^L0&yYQqG1hyy%NSxyV>Y0hK2zhz|N# z7Ku@JX^mOYU}Sef9JLLVv>;*|9h(=UapyWpJ_wN~X&4-DHO;(!oaJwPv8G(REZO+> zP@CJhY5GSHQBcGUtqv!sq0Hi3f|>D(P;5~1GV#SW0wHQCCo1q2NCqX?>L7rQ7tVW| zmGr;-o zoVG096CCBMa-h`$$yFl99m{;X_)9cPwsD#xQE_BQG>RM~eNpJ8bm@+G#?ngof-eM0 zOR7~D+tuab7#ZuSIx0xq8#q?>1W&CXlIB6F3^pEZzza>CS^Vf-I9!>XC2Esp3y*Mg>5jz!>tU4!Ia~qZhlkdkPz6G) zUbi7}8)7F(x)VLI)WlR6iaHeY$g(pIV+ElqS{&HL3lIi6l?sXQ8%0EFpIcxOnBc|K zJ=mGA@^{DUf%ZypOO^Sl5z7?PnBL3;ADu+p+dY|{P|sx}(7Gux!59f%QRW0$X2quPX*f+`UfZyAodnSM!pXLp@L9wUs631)$1b4ORKyrcmC-Pke=JrR z<|r_2gOA|A4)hsjjH040uwV zYw*C|k%C|>RoYM^1}?6rIO|9)^E zN(pXzK({Y)iaqK|AMql65dK$T2(ROH%)>V=ZvH*A(EY#Z@qhb|>Ymi|t-?f$_?w!> zm8MHg*9&BWIWwNrM5Ag|Dp9Q^e=HHb)9I2I)sF*;I4DY-=N2Sm-Yif!?K$`Q_VogG z7lj)^8-W}=nN?EDAWqwfqCTf;8$*)_g~_VFs-fmVu0|@Vhx)Oe$u*jVbUyBY zE9;drYC9s^gxY4HYtYK;aIAqlo!PurojzSq-1lSQqf3b;r#_EA(}S2J#fdkY;5VY` zZkC(}ID_Rr>>?VXAPz&jo;;&u-H{P1FDF?2JpWbHw3*fFAIGfN1`wv-`i)1ZA4gUV7^2 zUyc^u%agKO<N|^6{{B8SXPK6joqi^N?)Tj9I{P{su*{t>^gag* z3a{Qv#K2o}+DHV!!wI$6Asy)p=L&f@d+CjMHxCesD8Ye%b%sN<;Uc;f4fleYfV~Ij zqZ@%1^m{QOCKxKg=|7gFMwpy34e-M@L|#l~QJT~=FHg}u`MqxT(j76uzC)3?j|8;8 zaz`&{aRe<`ez1*G@OZ@gQV*y2svK3}|57lszkUZQXmgy0@v)Fd2$*K^^SU-D*_RsSNo@o4e{E%G zRdSltv!mkQJ1MeYI4Ui8x{ns;+gm8o706M=+3(ptVz>28I+eDMofi#u>hs@k+(d2e znoyufWJ(t~V~flJ#8OnmdqgY}vEjeD>&B=TPwacM&gFBYvbXxq>?rZK8G3+&s<3_Q zv8kpwDKlxB&To#062LJ{c-IhXN&WXkV}J^q9m0vnuIt<5nR`zUp-hv;Ho+73lY^8X z!_#*$e+QK!$=kd8CI;I#Hms z_4ADz?e^lssE~x9WhAXLHld!qD=06Orq3Xy33wj&N#*ZLt3tfN`>ZzGvV(T<6qV8C z(&!PuW2O&L&-yF>IJD7-#H`V86An{=P-2SMSI(u|F${)Nco`4l8uF^fBetdGV6cvP zBb8I6@y5U`56|<%=GSHB{LTRaDnb=239^AbgsrVfa?~dAu_}#Fn{J6mQ23gKc#)s3 zBa*MxA1AhQ(!RM1r`#0di#CtAa>xC7T>X~FOgk0<85E0$!<`)_;;dY}V;MgWgd!p7 z%#nH&m8?wFDXK0Wlu6X5oO>_X;@Hd?UYcpAUUyB;EPf99n3-4KDM{{IHy^=+nr8%QuhBidGjEZ#NTljrbsrmfzQMb9T}9IZP&GSTxdC{)*mb7M2tFcAnXes^-4GVccewNctcb zwaR)@6Y!lH6Y(1jOn+-bgeT;|!Z=!&UnQ7o6DHyVpn)E$WZc!uDVFdhYV9uLDZB|U zHda^2^yM{x_2rX`^rW06eMwv0t8>Q1vSb&+`||TG^fZ@O;pElNZOZL(%Pd@V!;_DP z@z^z0e_K6B@l;|#SNO=}RfIH`rJz^$i>Ru1S7(%rBR*51=WC##FXFHpPGGcNZcGW& zC-GLM8yD%6*6>`dE{5}W>(pkP+f>2W*kspd)S!3kRFz+BL|pSQjCp9pYc9u_y^fsj z`ey&3$F#&lGiSHaYlAt9nGq@6T1XmD$sP~`*H4)|<)(5%d%j_P-!`9ksoj|+pR9(yM>rlOm7bil`5_$aW@QxKBIWISYqLA$}&{!yRy`j zWkiPJVWpzqs@#Vf7F6lRmep~)motCtaP}1;UZ^}qlGb#C|zT+mRmIIbdY||1Hzg{l&_Yl z#6|boYHxAG@I+@Mn!V|!AS#=U^wWbh_ZQT%fHF;O)*%Zveuao>|MuCVz^lLJ_|S>U zktuUe)z8m+Wii<`3pPpB--x(33AL@OMsJr@u^OUy)it z_(1lPTRj@uT4+G+oON8A>a>aD`r7;DGXjjt&vA#b!dF5K0mf(u!kC}pAJhCM{qA7} zTXuv+rIF3(`x4dwr|25yvSj&Hq;Z+q}1=!l4$6Kjo6R(^YvQ+ zNk8h0f-OYW&_y&z4EVd%frH;AVJI@xoLM&hl5UwAU*7ZEu=ta5L{)Z{!JasL{fKN( zGkG}*$!rak3ft&^u+p;XmK&sZn?{^A{YT+sKN)XoePOTdan`-nm0#n4gw05F>xSk{ zCFVgIF5%K{im?g!eIe}fUSfI<*MRoX+7jL$6_^dx2iCY9<;_B5;05nTi*KO)LItl# zp|NPgfg!`A2gruVxh}LTZjmG9qwGBJoBRb+Z*+^-*|6Qu*;S5Xp+8K=89Bl;d_als z3*U#Q-$mS+8W6~BfhgK~r>gm1Ad@`0hnXvJM(Ys2VVsRp&l4(k|%hKB=L|P=kKrfiE$tyO*JcE5= zpnmbQFGg~$M}L~nydWqy`bcb0|FjBsbjQbW&=;ixtT)kQ4;T%iHennm{7(l(GZVj7I+td^{^bNOeSF{5JFeD$V#&G&*L+ttdRSEmIOvoqgunxDM8 zZZCp04JrwWdg8~BYbhTg2j9T8`akQaza&1t#-e&{_^< z)4Z|Q?*i)8!#fpLo$5z$S5;2oy1EtK!ld&ZOEj%k+&K3VJnvjGkC<$n8F-@AV3D8Ew$62wl$-WnBdPw{1%4)C;EK9nX%L8tek@W4<_x_Mq5W7-;&^T4 zNWF-m$=!9QUcZB6OV)P0f1eqw3MCCzp8t`_^u!c4&J0C^1+@Bj2=V4Z8^0&x+VErO z-O3JewlC&(efbBjbC0+wF8tQSbXWePl^liZeL!rpO~5OVz)z};DVR56oD*XmXk9Vs z;f+FszE3VIWO7B%gAonx_b5{&j#CH#euD6e^2BV73uoYz^Y4kJ+(IG+X?go6cJ}S$ zou5(}3$wkATY0cOR!F$N_*a4Fk#bzMVJ)1VL%-HDiXgjv^`+3RzSHiiju-C<2TL3n~Q&LMe-kadOa%Vy>5{iRPw#wYzA|zXqp6 zXI)54c_rlC!M?`b`f_cpTcgIl?5y|MVp=Zf?XMr9>n;DY-E*GnJoobu>%L$sEKqsW zECXJ=sTm&a5ivt!QDWeDml5R~8l4Nki|({gRR0c1A?cn8Gvh!E)6BFg&KxdpG}Z;1 zvWEzf7K>#pT-7-zF0$uGQkUGBGX(0K+YvHXY-S63t(p^pVvQab<{34Y;Sg!IW?QNk zol;|j_iD2btbQjH=CoH@h&v2}voJKltk@qG26tg@2Gz#ki4z!tk^>lUTy#4ZfQ(+* zfem=#iFHeeEt+1<0S_iYbu0L*)?AJV&=PD#Y$a zIPn+s^hVtQG=tXg3@IPV8I|cT29u4F0}F$^^Kp8tw5D}%+Iuq2FDS*+O=_5esiR4| zs5+Peild8Off4WtKz5u*2JXB?#@XGW-rhU&-;Yu7+e1ZkKEVks(@d|MU<|)-86sH(T`Hgn7@t5KgAC_z&0A zkO8GT3k%oSkdB9qiUWJTy*Y+1(IMXK7Y2*pvY31E11fg};I}8#)&YbyJ_8|$Ok<%8 zF9h$qo%kKpouQa5FP1_>kzPBK?LJyVl4v_8!;;w_%mkjaFIO<>je)>cER4)-B1Lgq(N2*^1 zi4Wx=j?^!Z*!vmx_}Kg6l~(X?C5wkoQuh*p4T3lh>#?A@zOke_o?OM4gxlzP#xpoR zk2eJR>m*R#e{er@KhcE)D@%$aqR)u9aD7F6D#{^sknz-mm4pf-jcBtwVT7xpJFKC& z{{$zs*H+Ys$FjZZhJf9#MCyJHseefYtz#%H@q#LcHNQPciOUtis8kNCRg&lvr!aV0 zy|DyhCS#__$t~3@CxVIKhaEuSZa_(&?IP$<3=gafmP#X~2!v)xum-)^Pl7HE zd9S`M>GSqViH*IY71Ow&0IqvdzB={wtwRJ(u=TJ|I1c|zac$yCaU1qsLa3AjWNS*T zh2=d5y$=yocK`hpbw?&9tyPY? zT)ri78H_SxM);0DU~M||TR6~ex$VWU4pliN@M~iB%UhrP!v5)k8=`wk-6M-Yg{hTt zyCp1N$tyL?7*Iz`-?e2;(Zg@A+fc4DJmu)AO`xk0ig4f~U+pjX6ohgm`}IKicE?DR zHMXX=ka2R3u*J548Me*W%cMi%;2v?v>i(Hd5{pvpW|LrF6Wb>UmBO143DDY?gm zZ$fGAs*jBqdSN3nEPDBI-ulH?!dG_m{MTxkl`yqY6&S22r9zWs(!?tvciBI6Erqn~MC_YO!0UD==mYD`3LAW?7`BN_-rZVm)kfZkBy} z+PcJf$opZMrIH(1i`(YuW!g{|Rfnr&fK<(w%15N-O?|TtM=#(cc|MASRywm>za?L4 z;jjfHw`j_Cy!ra$b-B8w!v+yF3Y3O5U9A^v70Ly%(gNC@>MWKS!ON%X>=qeyF?h)} zF?@hz@qQW@F=B9gW$=rnqgt6cmER`qtj%ifWQVsWYGpCTCS15qVKluarF0TicfnZn zvCP$2vU8Y`P%gt!MK0j>-1+LK*nU-%Whn=+%4>(&xqddKrBL{4aj1{121-*%;>XdV zV_@2N5}v+MGDR^c%*q&L)l?&nYRu8Mnah}~pFWCdo9QjPdi^&A7|S$hn9FL+qBCk^$R-&y7O^rG)y{;)ZOqHVqaiUSQI~rb z@la=t0x^n5D?@SBqk7s4O{Xn74u+PUvX@Vujge!?#X9J)cf8swmBkuxnPVdDDaz*4 zlQ?lLQgjwW8u{iwm5(7lWRzMEs4D38G`QpHlJ*P3x7 z5W1_=g`vA>XwRzeTo#ASG|JRcY-7J?d`{{5P~&m59Gi-_(5ywZHET(7P6@GWM+rBT z#vI+5W>_xbD{?E;V&Za5W&d<+gTgzBs0I7EB!RIKKqJ2PsUZ$~$%xr>?Y%kGZaZ?T zUKH)2?N(W=3bsMDI4BMAB@si^JV>Dq2Hy586*A5(FKt1qK~Q=|XnP4O7Vn)D9-)SO zs=Gq3VB|XPlw}&m{*zr>ZL~GtG8hF(K&2fxnmZ53!63I|?nh-cmfLDeH4Vx|bT3j_ z429d`NEub(N`+M_h3YTXhd1GVIn`21mEiOMWUYoJ%X%(1kx4AJQVofMAfZIih`mu?FK-W8^v;me3uWpj`;(q4tm|`ll3qFx4$Hz1_1YuE zG$Y{r(!(tS$!+)DeW2Crh%3? zf|(`1RqI76bZ8h08cF(yCK%SuD7&kLcBNek%dU7xk(Kj=sv?4|QeycAt*+vNu*6BK zyxooz3JKZ$-Pp!bvUDdUE;BO~(X?q&077+@vI8BP&w1{?< zO&p#!LxVH9MqZ>O+pbh2GbEuqSsWmhY1kp~n;B>b^?e4@QQOM*cwrO`?0T)V(~QYn z!X1`H%q#8Isrf)6e)WOERqicis9yQV4(>s%uP)QkgC^|32u5Q`5?hfct#;`mk)cF1 zHB)3f=?#A60Yy7VjoD6sZ-l)pp4-AsYjU0jDfRjHuURY3aKSN^*P;;xUMBmuiNX*$ zr|+bLZqOpO5pKHcZ58J;Gpe3!<|^a^B3T)C86q9W#}GAo>zc*$;z?^Z!@Xq@{5<#A zN)$R`%rrXVj-FIF>1I|c9b8*MA5*VVv&G=1nH}8s;nW}=(8X|z4lXegJ=0%y#MynK zC&H_%!~)Ddwaro#3z=`CX>}xe(90K)#K={#A{i=#>?ryc-LZ@j6{8Lh74aW%M#~G5 zi=oC{$#mLft&YJ}nrk08S?PC*xRhhHXkgv6xvd7>JJh)2TWdoDs0d0!hn@+&Dz^Qy zND}F_n~LeFpvPzQ@YkWen5G7pu~k}GE_4h`dvs}LQZgTtA`tLmxOEdSfwI#FhjF{> zl_}ky=MzhpNBbd?u8^FM>j$loRc+=JMd=^L*{|&51K^2N*et|OURiZ?lljT7Y>*!& zJUg8$O+9ITeX>u!oT_idtqGj069DIM$mc#i)#{Sm^QSRr?iVf_Rl!vhhh?Qn)~fU= zrw34fV1~biP%|mpVvIt|uCQIb8}SY!k4AAbQBlN#weypA{A9w}nQk9i9{E|pxn?*sq{zbsN+MTji^Wjp${uwgxS62G7q|#0aGT3f z)q<7p==dbRmn-Dymh&U95fo#0B)ww2S58p9a1BWowaYab3i72r@e+#G*^f}2x%Q>G zTR(ls*qj!jn9v`La)?(gRYuLdrPgdC=n~0e$$K4S27RSj!=L);ZX;_~d5L?vdhH;O z?IL$%tSOJ#eao&7s#-HM)qoDNZBAyN(}H=JID0u2zm z%8s6Rc!37U>Txd4-9nubF-!xV*;1n&KzgAav4J1VcdQM^^PkF)F^036-e-VbM}k4f z0-b_ZRDE zairfPZteWyb8rZ8+2x=rNC}Nd7VzOrywuGs*P1AHDVB2xl{he_3_~}e-lJv#f_Rf! ztI}Ep;A~f6ITl+Dy9ltf_-xv2K(QA|&6)&3B}nydZ1=SZsjDe62>a_Bz%Z&k4BbP9IQFHTH&c9>-1U5w8kTr7}hqOn?Hu z|MC?`)D+s!r3O?@-gGZjpF&d}BMt6}Ih`=_;)iRv8yhOdkRT=&* z0qe62^bum0?gI&I z3x4}R%L^%|DqagVFzg7RIt4%}yU?>5vRG)u-MTkBAFNx5J`(}z7^3Kf2=QWdix!EB zaz;W=6~bIDl3Yn{x&(+Vf>B1hr}epUiRVFA#MB(HISb}76oj*m;yRVTAk3ls4Q{bN zaZ0d9$g_QiVrcaT!QAYRh$RoRPl3slIdRHn182xAA3;}v9pVMpNJrY1);ZO=A?Q)& zL$1rN55X_tJC!_w?2z@rbx1i5)h$IXQ2Il3NWUL=ygPM{2oT(~GKTbAxjS`yLU*oy zvGG|2!oOWR4tsnXaYmG3Kod6al8&%8F1Qc~Jn|3|xfsIq6W#&J6S$4r_XK=5FF*xO zejtidN5+YIFuo@)UNQv;+b1$!8ubxp$0Y~euU1~d2EdF{v;cB%{9d|_VOkf;KZh%9 zfGVb7J2jBo!9t=~IwpcIxLeVL4f#3%X^XN zFIXGs-({XrHN>HF2F6NgTo|gVQ)sVlPZBRMU%=m$!_N7^XG5vi^F!;U!LS`E^aH_x zA-D}q`{4U1mg+l<`VjlbXLPzFeK(L^7SK4W_Cww0vCL40-{ z1Bo0dr=xlkAZba4{QKN%#i2$l9SKbusTLYF(yTRgW!Rkg98Qy$$`au?0Ff@}{PW_7 zSJesWbBS~vrJ=t{_UwI`NE{v0%eB1SD;$n;*e4GArOnLCT$2gO9Cusd_{5C!&B|N8 znK_3|(VPISwKyEN@Y1uC59F1s_eyfXxV4iN13~NFUu50BNANYy(|q)MEQ%v|O9lH) zWp2{~lm!Z34T2c~zvD1)e*9p&=lWIA)eYK?7?9qd`A9?0R0|5x;1|0NF?{;upW?oz zQZu_VR5obC>3C?@(AiTaj?N5{Mx(0fz**FnmJ{F8I)IM^SbY&)LX&0 zf6!m>|GGq$W+W6h`&I&>emj@`U1`ccMeEic-t_-^#u8 z#=Oca*M5VBqd)p~`s2KP28ja-g)gzFU`#mc<5MFxfA zLpd6}Cdk!iy@H;J1v~NhL=ll=*dP;mv?%0Eq9r0;sULeAU80P9_?M2Gf9(7Z4y@Grzptz0 zJJ{{tRZ#ug>-yhUl_u|4!t{MrRV#m)9;)KO_G}ai@|5!MQ0z=oKj8E9me+kt$1ipeT+g++5$v{n) zo%8I`?|jF`=>d4gj)e&F3)~56SY=}CHom;ssQc#7r|X7*P;*+3LOqXq4M=OH$smak zQ%#bNo4Z5NWsIxX51uhas_DoAPKTz?C)$Ua$MY+rm+MwPSBEP|_Y&SO zw|@B3kkFL;z6MT}@73)mR7Qvj*ZmK6SIahZPICN;Gk=p?VqCFTu>sh(T}j?8o{xn>8bK0 z4Lv)iUwOE+dAq}K>-$m*zx%k*VOs!IwoqX3g*_*krof#0nF-xxv{@cb6mffsAbL|6 z4VM2>h&KUEV2X`Tvwzo+w@#W6YW6?`C%HF=@JM()zX18Ra3}gSlBN?&$(AB`CNw|_G0QaZ#MzYuRUIF-7{$3K$oS9%-52UX+a8cNj@0M4XL+% zM@P@0289I$SGVyQ3h?=iXq{+-9kWl*P{MTA5tZo6EAOvKO?>kuANpojaep8~fqM$# zHW8=Wa&dB%M{AY&&0NR$lj7dV;;B;+#pj22v=WV+ zSADT4so?k;0FD^A*y$Juw+pcAsWL0`X5bAqKq(8}uBdQnRMnt`DWOSqJdjLG)##i= zf0n4b+ScT#a=ZCv1HJGJ2mQ!myScZ@R=^OnC_1oezY;-HY4~WU)v)LZ6Ef63XhG>{ zun70BA-vW>K-z(p#i+M z{*iHKdi_n4neq-%`hy={qdIr?>teiK4<=mFuXqg1SMzFTjg-3SpLY3SdSzdA#dfZy8{v%%{O(0ifN?B^VDk`R+uGD@y%LBoJbc8Y8wrNc9V()Ba7Jh?v$t=0sq|Asf3#P|x? z$nep9zDiJSxGQC4dBWuw(F@jO(X8CweSvRK+yd1{tl z8S5L^V(5gup8Aw`BZ2PKmnUjrWv#`vv=Ij$!|GDb{I(vY3nResFNqIyjR*uG+}~>s zqXmB|7Z1_A7k2k^dZ&C#p9YX$bco`K!wD*mR;L$=oX?r%X>0lE_6`bMxZQT;2k)PJ z1*#XfZM|*FiE0pG$1*eI&U2yd_ChZOHs=Uv*}6zpD};3j4OYQ~ehSmTIE>AqM_*MI zJ7qHqfH(P8Ks=ZgU{@L;egT%93?yw01-$ven8h-R`D3D2MHg1QJKob2dXR zk_s(dulaaGke+O!e{HhL0Yb*G&1L=VY_PAC*Y98ZADF|&N0dwpnu|~J$zI&Y3`E%L z_4en-TJGSSFO(qcY*BB&be5B#;{OH?T;XjPx-wHm^n036smrXpnhiziAqC)QG%S)#?`> zIC4;~Lsu068Go|=O!E&gh?g*Zx=(y1VJtcXt;#>+f$UB^I35)b@0#pN)b>h|HM2bO zF}NYq-%<3!=U(7F={6qQZ@qbPYzy zcIv5p%RNL6{5j7^M}_0rjH-?@Hl^VJlqZlVW;k0d=2#+JuD^54l4C^UPcR{^1M^E9 zh937ux%2#+r78G^_yMVOm8Oa*JBP|kGr$E_AO?}VPiUx*djJv-Y-!RrTxzc#IhwX> zMg5U<;;)hDYFpvG3{Bh%=485dd0Y5LoW)VisiqT6iIjB}_5IzsBO>0=RmfXX3`P>W z=ImjBnStZ(x!B_4NSBI7h$Zjha~VZO!(=_XExkyCOW&0+tk&mh zLGuDR@Aa(5n{N*usE`VL(AfzG5HRfmh-5R^L=G1Z8<%K0W$KAYK`$(qC6r47iKWz1 z*(6-y_O`6`1A6qsk$WUopV+o-+qP}nwv!XvHcp%q+qP{dCr0P5 zx>Xn5x4Qdb?Wg@cthK*6*BldLc;YslIG2XRfnCJ!vl0~CT=ls6I;%{#As7GZd2g+Q zTEc{h>4?_TC9&6VUcfcx)R1TJ`6yUBr(cixRSPUT6;&!5t;AHw#S%Le<6BCHOIAg* zx4rh9YBQz#(eGHZAOQSFI`bLqhNg59;nsfS=31~y^d;eC5i6R>DylYkTi^T9_PR|c zkgxgUD>aH!o_f#4cbJ|Ta5sqqD>VWc$EI%j zyAyL)j<&a8a2e-kTU{&NzYK5wAR zB*Y?~$vM>DQIzHnmII;U@d*kaLuwh+NVB1Mf!I zPq`&KGBdKL%(pNXbu>7TczyH<2{2C=h_Nx?&A`g}TKuLS3>cc=UA z3%jjeE0@>H`giD8YH)8`N4zj&p6W$i41P{HsE0l69uZ*wvMn&iYN-XuB5iA3B3=(8B}&6>C~;e3>)qzfuC@ht zVO=9_x6d?hzd&HDpjj{ZLY*YVwR*#XSqU1f;CR=yt+X=a$nt9lL`R|UNIdEga{8dn zSS+yFkJ>?eJL+vu7Or%wfNFSxSN<`x#)rh@ce0Z-9gmdk=xK3RFJTx$_z}$+6citx z-+^EEIgFo-XdT#{#Rh|uY|fWrqL$#{LMIN{*9leIFYl^XT5)V+XDzq@7X@eIaWxgniyfpzFo+oVIHgZV(ju`Sma_cGG-i z;QZ>QEWwPck)|bmw+B}w5B}*^6c7D0j8xwLv8-gV+wbE?=>lxtxM;Cc0NRcG3u*>Z zGwOAXZvi^wE6!O9?_vr_7kGokeB&C!g2}tGjIvuQO;nqcM-OgG@NE-T^<(LNv2Ho| zIxit1fopnvucZ?whLHQxgxQ?mcB{^2`fxWv}^ zju`Gdpda{d7C<||tf?}YTd!O%OO`=e0XmCXA9nrm;eH9PwaGo_XqW z)4z9Kdxcwh(M&iDqlOh7(RFcN3lF63;R4-o)EgSNX@ian8@9T;SVg|P`)6`e=DAjm zFRVL7LAN^65eq;X)&(tj7WHrzbvmeZL`}tir?w9xc9a`pK5V~n;CBJBK}K!ljSLT& zwtC9GSfEp6DwrWiYs?Bz*8u_Lym`7om!%g7HWzCMhC+@iLVnNT77hP8;VA$J(<8>C zf8H=OC*%$n?0T=vAjq|S4nV1rb_mYNO!Y5jQqD%HuEFEhmE(ho0XPbhS9F@0KWK2K zhJ+!eeNcmWNNDIkA!R9(*;5e@j@i85qmcL&vG1zF5#gdu$GnBdcyQbDRoE%_W583= zW*{L`O%&RHiir6r$4DmB5Ka}c2Fu5e%h|e$`PTu-2_{bOs1p;uS@MoSPsb-zktJE; z4YyXPzD)qzpcG>eHNq+Ki~@_)P+a-MeH!}j^+0T0{R(GJ8e^bfG}jam<-K$44>6~G0bw)AQp4s zI0SB;r2q?Y$(;Mlf&7u|$p?LJ~&605_o9p+M0^43_|E^=CVS7URUhnX)#ms{O-H6fqVne>e=3L!PCq ze!NiqS_rgi=bJyyJEAJAzyZB-?ut}NUK3`yVDOCG<9oeskPEp zp=xuk$Z z0}6H9J~!?1wo#ph9la`pvt*RNK1HQX%<5@LG5@ydLS_ac{cN?Vn9;@KLe~t1x7TdlsvZs9`Gxq)DR24o-lp%YVS14Ehz5iSIC~C6|MqdY z7pOT>WNM={v)(cVXs+&0g|8t|TlDo>T*-E|1t@{&OJxbP6B0moCD=9_Lk}jQ}eSQ%XRAV&W`0z!tX8R>j-0feJi{XvFbT-Fk24%V#2 z`#@BVKtZRM&rt!b-tH&UVx^p1U-ei5H@wa) znxB{iL+Fg}tueToQ2A#*vsk01MsX4O&&b+GWugUsZPnW;;V!_Uylw6zaCuhk54SAYZ%XxP2r!)Sj*fZ(U>qe!`I+MlxP z^5E?yU~TmcVtqU>BI6CyqcrW?8XW}yQ#;5yzULAQ%Ej+$=}^_r$;XOFu0SWuS5p&g<+&Tro!6IP%LP5rJ?3OGd!;_9I>Ca2xkg>(lm z;W+~UyUkc@5@ysC;ItX6H;d`nZ;PH->`Od0jI4jzY4{OmT#Jvj7j^Z^xeU;94+sk0 za7xNIruI#xvfl7Xr_LbYKGQeQDZcQN1!~_^clGo2H0tWx~YA_-l|tRAE1~ zAHPp%C^u(AZl^Hu&3eYLLo-ccv7^1nigX!C71arTH0#6j&avmBd#S(?aepVFhV`&iKIs3$lvWjV2ynwj~N zn)vi!qXGm_=ib8tNZBNUf%CRg^q|Z zsKmB8-9=^~_FWT&t}UVG+Ma>7wz%Pn!C!eYXpV$5p**sxA}J`~CK4$}Py7qfTapnq zv?FGK4zYGHrjQCoK={PJO)n^Bq8uobs@j$8I4n-tWsU??tDx(I5yJK)t@S0%cx449 zU0*V8@dN$p!d7gZs=26twl!l)tEM}kOIOyhGq1++r+ze`W$tiLwJWqczQ(}KW- zEx4vb%A^5Li&CmkP7}0RB9J)cq)uZ0hb5X=Iel+SNto1$e1v#Fih2d|4rjfxt9F?3 zE72-La>Y@inzU9}NJlgtI)9-GR8Ux%q65Ia3CCRzQzWUPE5Cxvg%4-3^4L$(u_hd8 z?j1y;;t`FwAGDSEtqr`hm`;xl0DA?Nwk>iI- zNh({?4fn9KD#cF=@cRSozTVcZ8pHk@eo`PCdFA6c^pAa+)fBD=CvG z`}e5nU|m3jpPW%LHm#2>UAZ0bhwEuwjlPN|V|7X{sMB1>O~_l*42LuZzdPGoTjga} z{|v=v`6MLUJ)Y6uiF@#MwB$3u{I0HDl`L@kC3%IP;NfKSQ+R>Zpc2cz=|?8`vZ1H3 zEv(=^Y}r8ixjR%uANZOmN80P$2&HDz468)bL;%lf2N?7)T{!vR&hJz2A3_Bx)*x8Y ztDDrkl=VppScpoz{^1;uNpF``n7x^mWXKZEEK(mAb z*&$ERT{OHJa(kIGeJK9g`1jXv0;J~So=!Vx+)8`h7 zw@i<07x^bAESi{9rks;i?!A=EayhH7%MPE!&#M2t#p((BGf^!2T_R!TG+s6|+>w#FYiyWJY3Db-y$&Fr3_2O8jSypln zdS94nYgW~)G%)pd+4-RtiWgy){L<%C+jwHk?joFd-6Ex}yK1yFKe=JgwXBLco#!NE z71Lf~FM#J_AVRJ3I}y_QU8MSV2@xlYZ%uX&T6;%3 zdy{YZ2@|J~xL(*mdKms|;&)*1T3a`yZsXPbk(rEo8Z8X!P(L&nLd-#{``1^+=m>*| zV$pF*6`{(A0J5rG;R!9N!TMJCHsE8OWty@-W?THqp~o1u6xi?-cA`<{){B-TZFvVt zFxuP%ZD_h8-)+psf`5qbt(S%llC`SlPdY8YYU1!$GH`YH)YNE*z`=lLoD=CRh?;Cq zu|8BDU-C9>?!l2*tfO=-{Ir?aH~ys@7x3Mi+x^Y=Nb^00^Y279{&Tngtxf;eEY9B! zz{uLb$*EW^LJ#{8!#7mNb;X1j8xV;SBq`2>z#8#{1XDzsG9DfaB1M=4m_wn7ydiyDJb=5!}@y_b*&8Ojh@~vz7K4*J4 z)2`bUqX+k$EP%;fc__@-n>_$x>h4Y*$RaEGHXg({E2a<+@9@xw#hqJV`se*4nfnVd zogDEEF|SIL+&&W{Z)VT&jfZYm96wRlh^L-mG2Q*SQipd)YVF+}i*DD{IGejiMl}!7 zerD52PXmiPZGheGy7exX_3rNuZ@Hl-lXv_8;;E$_58s^q!!XE;zMtP*T|;ul9ry$c ziSssMOw8jcbxs#a?M1Yum-Fomxl1X`{StUP-}7y|$8o`D7(zM=#LQ4H&axz@ki&%E zSTB1v1sk%wzABlwxTdT*-DU1|PI7JTuB4i)q$we%QMrH0GKF52)9cu=!p6;{x+Xys z&B8gErCkz}gcK1IXosju)^!hwDzqVw<25UI#il)<>y1P>fk#Q$YG4BXkjAJzKL!oe zjKxYZdlHgtf`f&vSd+8cD^tNtpwz#p_GsXy>QenI%V}Yo5KP9Bv?1p_=fJc;Apy^@ zi-kka>&b;e%DlcRO+uFyiD>C4Y?n1tEPWxRz?(qKtNY+U@Lt)jdz!v?jA!^S)b zCt5v&yls+PysW7)3_9ady5@j_XO5f$>41K>EJYt)2G?-EDfYCijbSp)4ORR-F1T9Y z_Kn&pX9tom<=%LymD!N?$SH$<1%881UxQS{T8mNM3q0kxv7<0ER9q{$S-P3h7j}Jb zt@OZ_^3}GG-oHrcL^x~^ID6fh5WvIuF^P59Muo4I1N=`GYyP2%luO#{lCfNINp%y> z;z*gQs9$j3dbT#5k^;@qkyxO#_`V_Oi0i4E6A9Hu#MMoigS1=X`zYE-?#DS1gEfa| zil+5QQ&FactC@M{=6->RvYfWy`A`Y*LUohqmRZ>^XQ4x81?_UTs`->F`+S9ZvUlV) zMqkQ&sx}H%2DcK02tA^V;$4-d4z<3?UAX-crx|MWbbTBZnri}0B*I5&fxejYFa^x3?p`~TcUUpxcU(L2XW*|_qAlecvUiPMJ^JFE+UHDr{dpqAUah?L z_&LVUnjO67(m+5M%8{KSAe@Do-(&H-rYj-dTL-5u#I+g)V89#}kf~ETA=W9SkF00u zu$w3J(xv?^GYr4y@^|!}TLMABexqn)&@a1$&MrX6AyV#E!k+%JR4Qi>{R!f|f=J1O ziKsE}7$%$rcZ$%YKY!h&Unotheq_NLz5F2Qky-+V(`4uysx`Vv&hBYzqY!zDnUwS<7t?8+Nm>WtXrL)^0+@#^p)z!y-1&MxtrQl-aW*#`19$I)7ij$E; zf~2fcy{jBeTOA#j(k%T7c{l23QL4~gPcLVeQ1T-KHg#G8DLN> z@*ivrlcPCfWK|7Uq6&Cd>XdGGT%~s$s|nZ`<=zPuFCC`Ff--fxtLL%-`Q~Jsf9CVJ zunWreJf!@pm2VpnZ8XcR}%}ND1dLdQKl5+Ih0buX@YE67wg7gXt>Gv$}#y2%AehiP&_6??D@jAUcb~ zvBtX=AWyTCdTsB_QhQGAX+YjNg1tb0x<>EPTZl4TnRx|oy=Vci$D-ET5XB)YoEH;6 zfhun81l08s`rAiBIE*SU+uPEdw{^Wh^lRUJ&?qu86X%3!rGlYL;HhkX`k^ zi7dpv#+ixd5`eEbR>8c$qMeqM&JJ{Mv^3*TCTfTkBqxAc!rI1oTE?nc#v+GU;0Yu} zz&s0s(eEOpKLlCKVhx+bRjYXkLoj|WIGI0=E`$=rCy=)pkh;Mqa#5J{7s$VsD}$At zjMw8m81bEg_uUw7;|$ayzeR?Bb8?fv_=Y3e(~;;$L!IA%6>CZMF>F6E)W!*?9r6=| z)L}|M7wHM1o>4?hA`kykqv=u`F00oWZz$5Rv|ncADKA}TtKYZZK0KTFY&NT_t+mk`Jo3Z+;bSwK_@*lcF5^E% z$&Ksrw&Ax81^z5h@Bq&;3BxigkG_*&Zm;tX+(KzoD~a`vGQPe;u3Q#6 z9MnSeG~s1^S&6?($Rs)-?jkQ-%yV)q7TfQ7!>B%{qBgfE$n=*RF6DY92JAs2>1K8;TG{&F5S#4p{)09=s=oq;PV0<)=ClZNIDj7^+B z(N{~HgtcJ)FBv6&a?VcLi z^c&D2!6>~?@&Cwy{T~#l(2&NE-{r8PZ_zQ@e^U_$|BS;%H>@H$Gft z9XTWcWS;q28!IY^#&CS9@ z;q4EFq2Ke0dA3PmolIPR%^c^XZ|Ze-e*n-2EwU%1MG*ve>9$^nfa|)Sgn0b;S)d*+ z)NhFVbHA~%Xg4CX6f=iG7>Y%K(F(>olR&#}lGE&D{5s>UM1kotvYrBGyoQ>d7@B21 zxmI{}t=>HyzzPNpn#4fLcAUF~>epBv%5%V>WNJ7X&3b|qj8J;_YV-0^bAuL4K8gZq zXHJL7{hvg{xiqo_`b+y-C>6G`& zYWp@v)m+w*VcfNmTngdBWK?JT#6MiHlaBY*n)?O4Hk!w#*#xe^Azw61gut36V zag*GIH2YjxsF{R|&Esd6N-ADLimUjHb{oY~dhk^dTZ6km=1yerLjpivJ7d--NqAJ=MIcprYJId5LX`qwy%(1-6a^Ou@6fyJ-ESavoBI+Q*YiRZG*1$vHOHd%zy{e1LZ_K zkbrXsEs9T7Ff8KETk?s%1hq;#gl}yTg_Fm4UO`Z^Eehka%?Z=9Z3&a7!m=Su6*rO+ z=A!hYL>4|k15kvD(}_l-Nz~>dhmps|&(UAf66`q`f~WzqU=_oZm>LB`mZi(C3b0_6 zYN$`v%+`peBeibT*he^ayg$2{U%wWJg@0TuASz@9NiuDYotY0g2w5;HcB~#TE^w8V z(?R&26kw<_N2m&BhSHKS;@IZ_!}?qR{d@^*=-RPobMHfwMw>3Z=qaVWDWZE$v73&+ z$|?2kZDEknz;%zEFvGdu=RLwIMUS0iJAs@XgW+-WZhwx1-qe|RMRim&nf&}0kg;eB zS*Z7IRK4K;zD4tIMkQ_F>G7{Nb*?xs5C18Pg{TPx3eo{UsGIjg@@7n>1D}$`ALy>1 zFI!#^GG)kukcc;OI**Cb$l)OjZbyjYs)V7r-X(47Vzq(e&1d^6XFj*P>kEKBV3OGL z20uW_eZ-VN;s_yAWQ*7IK6p}zRqCB!Jye(5Xj% znfP%ol4(khP!&q|-$0U6o@T#ur1G4k>FH)NKhbC!DDY|6*9VdrFA|#WT>Zu=?b5VF zaN-MREl+?^(hJ~3bxxr~RK0IHcEwWsAJMg_1_d_?{%+9-o)^2M(9#z!}zpK^Zn+l1m8yeXiz zKNKznO*rp*S~+TSUS##j(#ki4ut4!)uim4cDn~!G37zza{b9&2!k5X^vB;3WM_E(e z8lgp5VtiCF4#PT*n#ZB+R~K&F4#42iS`oO5HHViIF31@wSc)(9-=kI z*;Nrmx=Yx&<;{@OR(o|7@qpn3JZUv7c)*6LNEwMz|aMMtQ2B|K0w4`H%7%H~4*FmZ+mQPT3U-5C$9tta*ulPc78HWsS4Q4M)5ei>K=7^G&I!OP16C)_ya?`(yS24 zUpZ~=QsPSdL}GW+0%kR3Hde@WZ9-P)*02LjfL#eLXP;4yCR4s6Ruvp}6f9jJ1$?`k z-H$+ZD572=tMeZNfjuVo#V0ILBRrUV#aSXHs^W2Ts-`VM1-y3-OlOaqK7D9L~%sHzW> z^yG_4Ri7v(bEl{tO3R`u9h+nQnXYGw>+hfJuZYF>LM>zXFY5m9h=uQej#&Qw$%O3e zJ>(tj%p6UeoTR^XvQ2FNo5VfIMs8jndHBms&ZHQNo^=2m7i5qJLIfE_02z`rK?DMR zE5Y_R7D=(rn(ZjBf9_yQ#)!1{u9V($e)O@cj2gZGz0_1E&r{a+*F)C&$LIY%nZJnj z2>O6FA|ozjVyXhaf+*zAko44g0F?{W5D!8Fi9RLBX>_ok)?1C(n@tz6L7Fw|XAw)Y z*p*imp1%tp__ZZX0gzuk%cn*VCW3 zbal08Ot6w}SIak3sv>9u2h3e;@cMI2U z7>cvCf5P8bmF}`{Yq2;MTrmGMj3YO@*@!;ysWef0@zQa&emrxfhR6s+pr%6as|!S) zL(HLa4@gB+MegXUpdUwELhcx94`l1RM;(Wu`r-j?7ynpZDbKp0Y-+ffwtbv0^tjzR zz3*k&J*VkekD13P+_u@c-DMH(EIZv} z6ZR#Ll2W$*9qxkg1*5^WpYe)yD4q@!!kIgdT&ck3~QEJ&nQm!V{w zl#Y0AJNn7K$+dmpD6Q_Qc4MXJ<<)75r{&|_^9#T}VjiLs!Y6>7?5n7R zcm{7^RCqF(I%)K9L~ZS083+fJc_t&kS+lgWI^`}sD_e!a0gpy2!2qtj zyl1sU&E~L^!tC?dkmR>ck+P>vOq6}!n}W`cELzs~*1~V~bkM0Ugh{%OOOI#H`~~QT z=G}f9U2^=H9!p`sFF+vwRbh1|O(!%j7A>o*{XA2wu#4+DE`3)I+}rkmeY=15Ky1w! zVlv+zNFL57|Je`n7B2AY&~>=3^}Q$LVavsF2=@MYM7W=OG#f)z{eb3t6m z>Qd1n>1*>0U@GFs566iNFEOOIwNFEFISHARJ(CRcEC;++w0Hn1bntefk4D zU-MfxDz}S=aqO67>yc)efN*qw;1>rHWWW*zDrp;f(*BP61$qi;F|u$?Bj-ZX5&-_(Fy7Wm5KZRJIX-7=wmhx|Wa|K1GVobC~@=eY3 z%vn8)k1iId>XPP9LOeQTuFobqn0uNmVf@rYHE^dE9{jc@H`15*x&{|a8}|x!n*9iB z5Go~n2P`}o;2psH;siVpY6eXH0bEY^2hsz)R(|NcED^{9-!9fup)3gGmMngV(bf>F zh1@IsmzsPp{0n;497SBLGNkOwL8=BS$jljTgGjKD^pVH%mraxBu zoEg2%oIYgfoiA!?GWl9C?SFkuzf5y{xz((Bzve#i0oX$x5v_zYAY2UT7;tV*j>{Qi zN9~oihF$v(WqFxIi#g~;Iq}iKjkwDX2{GcDo*|%mCZ*=y-=#(Cjks$MAu;+=?5j<@ zxj=M7?v6r$-6TbqdiaH=nt6E82FkeS4C=<+5?<4V+^oa&$StvQY(!_ zBhRTx#W5l-MK4wSkgC<(_bj$}9>EenaVokGiN_vg)N|Cr;BkC5XSLaW5D({I6LS)S zJ(_#r)_W#?;6yvsz7mgZ^M#z%er-28_0D&v*U?w)8RYbot_ws&+{}wIA_|)aA@WizR;xZ|bJ#X+V zWHl)sV``w7FI&bmsWhD`aco8ph(wOTD6~W|JufPX3s}z(?I%6GdW0;rO}0`IymqAM z96$x5Y=Z1`%+n@_*-DXbOEJu_EgXDoKz#IODJv#A4T(f4)chr@fPihNtvWeJrICq3 zm4X$*N@S-_>?$aD6Y1DweVIz1eBnvX#Pr)Pxwe+lF@0jE739m@CSgN2lSVD3{^&uX zpZbK11Ku(vh_NQqq{OCVn^VPBe5UIxAh28wODQz{s7fB++j+Y8=`JkrI<{tG%6BDs z;pA7=)@?Ujj9GrTeTdGV2fvY7f?IR@@&rMWe$4q&3W!@{)0s-4LgIL*z*aJj)-h5= zak@=cns{vOd=1Y*;2P)WgdpYvPb?g3KSh2tSDnjMbx~0)+s4r=ch3MF#!MSFn{C7m z*Y!Io+6Z;WHvf_0%FBN1nOH^-VVv*RI6e;uRQ0!^uUJiMQyB`z+qK=-Vb4N~%%oQx z^`6-Ak(uEQ$MxXZJ`W(5A`V2jHJ=wvble!azq#Qy3h<*+QLy`(pyt@&`=};9I|Dg7 zDt5e9@cOKvWDO((0w@BlTh{6pC2b}6%h_mHoz;6GY836^m&r$VFg=%k<>DN*sVvbL zC1g3IJv5j>sZJOyPHIN9ckC`@m&q(sg~DIBq=i~6NrS2pQW$t~*``YllAk6cG%RG1 z%IWN0UR#G%W+)kl2XxD}H1Dad_f}u*9BQF-1h9E{NcG~e(`s~7@4UUAypsH2h`@eP zn7Q_JY`T~0JCao}h$Rc5$*ZOpZEw#^?6Okn59uM}84fCtlZ{mu&bHPxBbl zl1*WmGMubii=`rY6c_elt6t5F&L)hRnV1iJjB=BzbCV~xfA$F-|!A3H4L3&(c zhz}3}l=F60c$Ku)ME@)jd^ZJyjZ2_J`yOI!dPs2TKET8tnIz|Kc7|_7`odAWAPyle zE8XT(7lU)f#?Sh9*w_6~i~>H|&ZPG5nV#v&k9$i)-A#JBNiKOd=$}`;vKvyJE_}t$ z0%!SQS4>w;9k>C^QV7d!-rG~0R91ddwy6<&Q@cPV6}4~Vrcu}!>y>VPn11Wl{Y#hVxU9Da6c1X$Yrrzr7VAzt~h z;NW!eQMQ)%_TemPf3dPzEhHeB%5bJ8asj)M<08F(%9hQ|`FC6A<&kZ$#YZ&M(NAT1 zzkJ!d5>b zxv#5VD9+ZPBDwahw#5_+I9=JO;PcLY3D`hSroiGS2!HKgYXCw_LxUN50BI}(3PZUAS$G0#EJG4Y z^Al15q}K;z^b{+^eq_GuqdKSm+gH&`H;z~Djz zjn;r8QYIvuh}!H;Sh($tpZH?VK}0RX`KKkwYs!rFvR^!xF5l>c9{Y+7naYRI3Y>Bjic;pF(1 z9cujmLyDCu3ro1EyJ92UHhEwJbrAJJJ5N|=KQ)}b>KVI&5`t! zrOkBvsA5aTCjSNgtF3%LKyhsHO?K$Eon-;$=ZeR1-nm7YoK7R%x&&J$_dy9xj!4-2 zssdNF0M~ffrtQ$5Crb#jH87SF@Lxu;p@S4``ww!um<}C@kK!3zF%+{HjXY{OK{A`& zJ9CTG&~2Qu@*&!H>Achu+$YKUSbKMAt=eq6&%m<0T&FRJCT94V%}hw6NL|OKr0wgd zQ?ddohS^MW>J~ymRmW##iT9h^2^<4ysAz(`qfpySm@JlH>G4>9N4d85UD1w z$UR>485fs|u1gZXR|IjFf2n=cz%?q8qU^z z?%ouGv21u(%;Z~3KAOvH-3I;O$)7`jv?WK?O8KOLzk)kHYU!F#rnmrfnVqt2*1YFM97tI zacFzp8>(^zYau0_&wT4S2N@4nqM4y52aC?S+Yoajjrni(XwN}W=1XJJcj$_SpW$mV2uvjb&e)h#CZ8%z-}36Z*hH|MVL4K3W@JFAmg;#i3U z*Cdlkne#%NLBCW9M|B$XL-DwOI--Qv02rp-<%bD1ss)6n3RIB}V1mwS(g<`5g3{A2QX7WH^mkHh8u3F0v-N#w^>PgUog z<7F^guxK%0S)!m;x1B%TLoFg-Tg1vRoq6gbNKj28Z8!@LT$|gwXTjX)Hlq7ZMjfxRKP6+mR;*S1%AC@C_B6ISk|l0+uw`?& zKzUT6P_3h0vcyxA3E5eSKIiKD7+AxmXo^x<7cXmPI=HTWNqoL35@7>lgqFQ6N&7Hip*8!E$6YocZIu|kZ zeBD(FcbtZvWBW|>$9w7#dbV%LMa^K;%|>oNvTC{q-1ZicGq=!&p|& zD8C0?F({#B^?@?QW^~#bk5smkNvv>GtS|=<4Jdb+v+O_C3jVsA*6mX$5x(mLsowyb z@&Ea5`p4{AvhsiAntg4b6wyukZz(AW$!&qvvLf#YBO!odQ~e2g>58IZB}IQ%h4lE% z2_qRq5Pt&rCEaeUb4Zqh{CarUa=N{X9-uCnT1fq{lM%SdD3y08kyr&E$7d43< zML!;oK!InPtv;Ti6rX&?;h zDCCk_<5g%bp0iaUncPrV&Wbd+f+tiY*B}iMQ%Ws7t(^1v#R>(>Cc{WB5m+%|)!bli zgC!!gZ3<@k-?n6@ zqV!4oY-}$GoEEDY9qiOR*(DM2e2rJAlx(v@gV%loAl2)rEH4$OpV0=xsZkFpp;cw; zZi;jq64_Z_R{(1bg?P3?AFvZfh%KEVXzwzM$@ic{NdOlZ3bjpwpn8Yb(}bErKE4FC z178jfyIndkXWH7sN{)^l=3^P1N61Pi^{^e;(E0qTLzS6#{xR>j2wBox2p0m);uZg+ zX(Ca%(kCA_?hJS#C~}}MpJFC24`OQ0mdpX!=!omAZO}V`CmEwk-NX)L(Zmd-;5O(E z>nd@d@%l(}VZ6UXplf33a>y?16_BCJPg(lvwY()=Jr%fLaCrCo;6S&|0zoPkuY3JwK)31b6_!8nMzaKO$K(F^6S>^rhtdX6 zwBcnzgYXf|jq8uX;X;B`2G~fInm@Mipsqa9=ggJU_TnKj9KtyGVhE}bzq3etvL|7R z#pcj^=mZpJ zFwuu$Aej0yh|H+eL_BeSQMW#>s&&|SD?!335bn6$+TdKFp9ViScO&U;;Bwk}#?7`3 zZY#BXr#I>-0$|W?foZYSRHv%hcTs%QWG?INRb{*jG3uvF9oQ5m_i6xd?!TK^IK#dH zSy&g7`_CKqQ$`l8{7xvte@DKe|Nk48`R~$}jGgUYo!b9-5XDJ$e^s`Ia@Ui8ScWhl ze?j*}ugkCX%7040pd*gR??KRc8%a`VrOqZa!#`$w8xaOP_rdLiG4i%V=TEW4Xt}yx zeM^*GaZFph?jN^Y14vhypA1Imd}@+n~4N@hc3ANxKN^PXoD3_csLptZgFITJ$z3A3=K zyI@baOlr3JXTw}Xzc~(Bc>_g$`Q1lMzwFF&>i2#>57|onqh|C$MVC#JYjscZxvYG$ z2sDgcQwwl6F1tbNp%>y1DjWAS_K5QV02KwW)o^#=wZi0qNVM`R%`N%q9Wp2LOQ8M|j}P4Oe3vG4JX0G$J$cgLSc)=t*0_u~;)q>NEA> zBsk-99bf`>pKkU*t5&ny*DN@h39@US`Lm6{Q8T9IY|)qsJm8Z>G0@UvT!Q)3>qprh z^F>?91N||%zo9B^f+I4afy9YpKk7y5oiG0MrH8IGM4t8P}XI6lZOPPdYI*uBts zoX#z940JDIcTb!+&XErwCFmlM1pXiVz~4Zi`d?ZZ|DoQOI0~E~0R$t6&MH9)i3G0@=+7W1kpV&s2&H*w zawiCukj~CTkhiE>Em-MNnNna=4Lua1S;h&WJX^7{)=BHKyf%6Dwk7#>Z)%VL0~q}C zZEM5p+c4gb`M#A#?yvFOf%s!8oQy!P5_WAdt{nEcFXrrPv0!0FCVXtE`#(V40pL*e z*}4e(g)qC$LSuO_AKPzPzP0;^Y@>$?F%dBz+Z3X8Xt_zJKWyFY`L|%(Z(X=)GjidJ z!X%MGdZ>q38)sNs>Z?d4PZIgC08NH=cb5eKLZN0&_7jJmjC~tjc z{{W-;l2h?H?t-%E4oER}Q1|~dc}0o$PzhZgSXe&1{DHQG9MHntaXAE3|AgakM#lJ3 z1IJ(b z8dPj2e{9>X*tTukNyWBp+qP}nwo$2@zNha&zw|vXd+dk(IQJTBeq{X`jz-6syHkVn zTfB1vqd0@xufwXoWiw=CE|FjAauH!^AhaAYoQ}7rzze71n1#N#i4UmmGHed$=36kJ zin4$Xo=)k>ab?~xZE|xOSww{bY*$8`i~E+6UEkLrKCiI2h=O8ASBugtU?Bvt*}(}< z?}$souK~hbM!Z0)r8ZTorlx4+Dc1By)H3SD^;pDtA15=}0GZLhTak7U&7;MH_TgZt zL=`i3BxPorkZ0|2or7jXJJ>VDW*yV^-JL4~R#3GPyff!fqn>`Tffs@!Y+%B;f?agN zf~;;!E|!)Kl}#E99V&EqO)z*MRaseSt^b^mMLvi6Mk%d!EP)Pm>p~8Raj7J$9|!q2 zzd_AlJBC!yl+#!eD2WEIjT&24#X366xly4eiMpw$x!lH6^42po8(#tUbYN~ptFS0I zi)RYzioO93QU*HlOSlog00Z4V_eFq<8Rk}F_>|$}bqKi`DAkrA>WuK|szm0nZ(~$O zIyOg115J236KgHNMG5|qhd?M+WavPMwF)M$`k#uk+<~Wu{>MSIS`?l4_-WH7{)s&% z@XN8W92s0f!ig;Hk|RqAnt}b9?N50yOE`@^XbV zuY&f3a))T-sV-VprYSN;fQ8%Tihb8)RA_)$^DO%HIlfaBel>b$s^%Ix!U~tv)zUq} zm(pmj@mniwWxZ(rg|VX8%a_`4UTj%N?BxwBb7|P zchKT2qhY@Ohp|k%b8_ug2bDb6w0z;2aZJWA7ds2t>644Ac@tUx;}{O-cEA zM+V_wxn)TVwL@~u}M)%p6-~2kXNx!3OtDm8S z`S=2n=)ez6Lpf#>EiQ@tee1cn#nvE}QFnOAF(6xLh;71Lz%Di<;D|BpqFv(unToya zWF$s$O^Qj7-v+jnA;mC)E#MGnAFHNQPU}|3K0Uc+4*4^V=h#JKD_Fe*-TsxPom3bq zZgW`-P>OY;u5PhqOj%6O)`7A6Ctm?-IFPD#bQ8rhXr@uw5v3m4PHO8?tgiFxq6U zTE||TH2G!;$P}lszyCLCb_XFU^~rCK97^ zvkwKisM|1NP2q%9LqQF2mbcTryHF@VX+1e-V7y`}T1h%FMjsSHuy-s7xjB*$mzDZ=}E z!4#>CKOK>W2uo@sv$@niL}v?n2`@B<;Zw3W$N4|T+Uz;-c`|@e+v6S0np0Sqary@J z${s4+pWodE`q1k=)TI<=%IPCrsYkhZFD43d;A8y$-VF3nmGmDAtNJ9svHF|*xwn-# zf6(N*tOXb$D^~o`trJzX!m}@QEGZrh4mV#Hh*{NCNcSx(`e2@_+=}%GR&QJFBD4<3 z(xkM4$Z~eYl;+(E7q8xvJZYA$ruUU;UK5DcRyTPy{~8&SS2y;my|moqL%qi0cz6RM zW5pM~-|(ThPaMSpYOV%e$&T>=R5AKX~ zey<*Z$cC&#{%kGCE|-$%i5L?7*%g+z+F<7ezIffn5p03VSR>)RlTQbcYrsFB6&KVKbz3 zivWX8Ol+w>6{$3Gns0Bed=ds1SSi(kvQ@4#_Q-o>*NYG2)ewdMh>}n%yb2mPa$2?< zgyfeB+vRB1FIklKc3p0yM>P|FuMeOJOWcO_O9ELC7$@Z&sK~{DVWVRSK#B+E@I4ck zC#M=8Fn$ezvRVSRngLWz$yF((51f+)HtweE9-jziO*4U}s2W=_furJpl>o`r?d9_u3*yEyaSngV~BU5FyH&T2#D`C}k#3 zN-V7n`o0OPG7$BDoXnOtlvvYAz3Qn({ zVzcexaXdz>X1Pe4Ng%GpbnsSSaoRVncA0^^8aIqMpG~$BDF>px6S2r|NGROmFWs1r zUh@F23-7=S`+O;*mRZ z{T6lx)-gNN|Z#b$d9w}sZ`Q-I98f4fD$F+BzPET)HA)x`XZR*$=n&qu5;#yG3qx zj68PCu(zfSem-QMYMSeQN)I=a9lW+J@(zxtW)3iNbid<(wdG(X%Z@(?*X_*EZ^T`= zmdjPgPc*oihCS#jB^rw1o%SE4BaD-*IH~s?K0JmuUf|cSXD#Ehr2iF_57g1y|BYOs z$H2-|(%OMobQQC;xd=3$G=iUSC&wnJORh)yLR+Cs_O3BZxqy{Ly!iKjLJ1E+HTBj% zAm!YD4^sYbyVL&(QeG=AiKFsnLj_@hgw?%WM?`QZ3JiPz6GafgbY4K#sHk zIIN2U((Ts>wN-xi{uPHp9s1_ZOH6mKrI?k&psud_$D0ItCi+K1!r{hv3bzOoMbE{d36o)s?S5%^%0I~k`nj?ezT?V8cw>MuvpR`pWd zvs;ZXqWZk=>tz16CN3}o`_QSofPGNq+|t?F)U@p@nHAqm%mijA`JDviWR(i=`rgzp z*MqLa1XS0ZJPZY!ayU7x>-y@C@Fl3&ym9%*;2Y!U|RSyhKD`$+4Ug&3>Ys5?cHZJOu@C~Ue-~)JO zPrC6@4{e~OGa~+cQR1m3juH|J-b~#Z7j?V5e~D;k%KgmHbJA=@e?UZ%7LGL7^5$Q? ze~;q-8cW_SXhbts_lG6LZmjXtXC$+FEGV*1tY9aYZNv_`^vo7OQ~rRw)Umvv%zbu# z_Y-)iCO{XMun`zR#fA!d124L(02?A3bH_%M;fq2&qK77Yl|}yjiLFK=kZ{cFtXB2F zod(ib)u#}P<1(&Li-Sg!-Emv#gARVpx^b!O5zrv5*o#fWGQ93Qatox@7EoD{KYpdW zx?$cO+M}9ox?$uO)z>O7cDcxSJanQ8d8 zWP|_je@S*%zaj4P{>dg7{!#D!H_CP=C-eWAPoU&v{$tHEG5%jr=>Nxqe|n*sq4|=p zU)i!P{$l$DXm`#}qREUarq$Qbl$0p9#wH-s4)Qc;NWZcbH(f~A5SO&5UqWw!wA4a7 z7pW|0rZQjGSGZfrYu>s2zUkdR^fEPLH%Kq$T%j}dN4+hyKX;SMD%nJU{J`lOP{`7k$uOKv@?>R;ut*B%wED5WQF(YNA0_{4=#dR`T;P zq@g=$l$yw4GeZwxWHsp7^OxQz`@owi<|)w|dJk>NZrC2TJ9E_S#78$n553^&@v$H# zKjdMkK^JLNBq6F$nj#`so*Z8i{!f+AYm7NWv+<7f#3wk|zQc5jl$T}yN;O{(9#b_T z*nGlSnW=FiXiPGD1FGFU&2$);aHP~s6E59h$*_n7HRMhv`@@VV*zGAQl5qOsNj%r=L+nQvId18hQJoorl|9DYxY^LiD zWA%8E&1nJx>_$wnNft17t48B<{`Ul1cC@jJ+3(itE(;2Ev|h%XREkgL0(L_ZHb!;xk&{rGNz94#F^6PZXc*~x7HV~gSnkE!-%dtqYx(LC@mwp%$A8xD_-v&XcBKm19B$_3Q}kN3 zYUYVX$+Z`Q7URlkaa67Chvcws@`sNtP1E-hDemIe-#oN2>`;XZ+%oIycGcdQc;+))=YkJ7Ef)+$|=C+Or%V z^3ubsUlDO5ESrfM6$h)1XR2M3z8fiK{)&2JF{QZ7v>px4n>f5>T2#Ko`ziT)pWyUF z*>2deeqV9KD0Q2vh!(|~*41P2fYSi9I8{`Jbf>b1JcZ*9vYsG1ZJ1*mnX7sF@?^hc zi`Y2$`Hp_(37~qid}uzf*sR5vj$z&$g?-?wcuXkZuP(ATSUOA?-Ti&Bb1j~p$EP+g zbmg*2OW7G5S^;v#pA^H!Uxk|)so7{9-LCIfAi7;5 zTOBK$Y=Vi@fX@fL8^_h!YNVwFBq%Tx$cuEve~Swd0lLECctTKIFy`I+S)U=#p;;1k zB7ijCSRkg;qz)AvHS2#p+H-Fpig9~V7N@}Xvss@4_H^dNsGWbW$1wc+!yG@`KSp$KOmeq*?j#N~KO)O_^QER(X6Pj)AV3YaHNOj!} zO}y^FqA)b2vo@+eJ)umJ3qXcWwE5Piy2d^Uk8Bf(r<6(I;x-5UshiF~g?VcnNx0)q zb^NJ)7Qd3DyPdI#|L}%5Nh(9k^wA4ayIA-lK|FxiGj!Y|1rm?kkUVVJqTrcGfkWum zuft#S=0i$&5#;KbUg@!1{RIIp8k(q0pl=j>C#<6UCchY)8^e~X;ON|DmV6sKTXO*b zX6CaTRO)fHs*0(1@~t#w_RIzIPfERp-uT-C5r+Bk?~HmJhjxz>tD$DDUJ{jhfHU)q z9Q`}Nqc!QaTb;(Ppm~XQAf1!9Dkz(~DJrbMYtp}KPDe$Y^1|Q_q8qNjAKYq-)@09d zRh+bnR%L*+%Bggi^NP~Ox2|P^cbRH(GT^cnLpm9ZeQGbBfT-`6POdR4&x|csRI_^k zCXT_E9MR|&p1v4wY^mA4OGCh_1gsMeG~XA_bAM$Gp!TrG{rE2mMw#puazI z1B5rqs{HksR8LIQ2lv9y+vJi*aR@PQ4zW>B%&!VukL^{YK{Zb8>aUR6hI4$8Hm-=r zrFMDZ2wGj#FPDQu@xx4&80mK|!+Y>5SL1z`RqgS3>ZNwgK_sjZ$2z6+^2>mV+LmW{ z8=2L*=5gwk0K57XwZhMxXaO*ghrkKAn>cFT|C+hYvL}hz`eQ{B{#i`e{~Lbu=VGI1 zVq@oQqGV(*;%;PO?`&ab`=88i{Io5~k2z^}diQtI_Z*vrq?Cofh=hD;n27>ASW!V3 z80C6rU}l@-Nc=VGgWz_f1qnJ25d9zw!B8`^r9vj%ocQQVwiBP;CjUS0f57?(auXB= zgOkMcnYwslYY}xa>P-t2^S9zg$+G;o-Gp;q16%pB)hOkcVc+8DnVG%xe(8~1`A?d~ z6S#;E+_T(41Nq-HP%yN~69|R<;Vh#EMYGApDYBTh`=QP_>$+WPB(_2G8Y@ z%kLa)j%C%38&O79UiV_0bFwXo`Ub=9P(sy2Et6be>Aeu76smZ$3 z^dw;a*iR3_;JqWZlBz}Fs1*zn0cjsE_SGX<2n#Idai!`}JKTc=FESeHOskHjE=AA* zFS07R92lVv_0N_gI-kDVOegj`OWoSOJ;9r|B>U&XZHv0cMTdb0zB z720!Db4qXAj)pj7q@l4~7jf{<29fj4@EDsyT&1~uFeY4^uIg*e*lg`>?WD`5S%x*6>nIOS5vM`6)C zBd)3c))%R~|`ikw)t zeUjB+PsBJ|We4dh^Y~A6;2X$Y*}1|$wb6=Hq1uWoINL%l;i=Y~>w*eEu}LA|CDAou zr~jE}<};1@?P5RnEV=*c`nJQWnwM%kBg|kxh4ct9oUbfgtq=rj27hiGtK0)$r@C&T zoXA_YWtr^*=oxsgq_dBsQ-HfinKZ<_*i`MoSHrqF(5tLTpg~I#vd^~s%soV)UIGT*7G=}q=HTu|Sy&|Lw<#Hk>} zp*&CuV^~bceR4?Q-)SU?3~5tC=}`RN%EoAZD;v!XEt+U^I*qnEYT7behW#}WKhoET z4a;Vo)@7H!~A@#dA=`;iEp(SJ3X_DMf()IZoCN^QlGP)}7&rIotOppNPwLu6N>7C-7Tl zr#Eht{`fve;CAwJm-orv`zy4|&txw2;aeQ9H)Yh0=PCC|E1Qq)3?=Y;QV8y8_u&mc zkdO7ujp>*-O&p+qtN8TjmM@J=3<$eq4G7xSr* ze%rG_yg(SjXc+{Idq|I{B(ZuPQ7r9($1{)uFLZZv;Mn=~%ltZVD5vr&yvj!`Jk2RS zk0@sMt}gO39;A+Yl6A9&eqRr{_#Ebafpj*NA~^>4jHoQq*mLk)8~gOo$@YQ0Km7vd z)lc$CX5y8Sn#^!DFY>IjOm8>{vnNh2HSztNT)C(D@bg47r`R|NuiAm9SUh^CFwQ-3 zz}14BM+ivtWEVK1KE^iG@UyINOS7Jk5JEJLV|` zQ#oyAE~jb(u#P1`O2FJ=W2VBiku5&F5PmdMp$yI4Ny`#{G0iRq<4>8>fm=O) z!x9ycHDKJt3fM$POH7*xU1!b3q+JGKl>?MtTiC^tnPlFGGoit01z1hWqB}tQrl$a_ zV$C43kc!2C^%n>?P$$f61ZCr9TgnykPDV^DZouqZMg=f+{ZcPnj^AmZ#5<3$l@#er zkGRfJmXngi8eka!;GWf4>)EW=xRGuw)YCQbT-O^@b(d44fl1DUEo+3;3U^K4(Bh>v zl#^~C1pN=wkB0g!^A zH%QHW0!JVqY~yjmR3VgJ&oeofe2z=UKaeHVGf~&AO*Vj(I+-@4#S(DmokcrAt_GZa zd&>AkV!deTYg7&CBMgKTq!j1M7oCGhjTBOpoa7uFd>wF%GB~nUFI|PTNST{l`zeX@ z8l8ifzjC!zztLb)zr%YbYA?nJcZ3ecuIsxL{-7_emp0WyKEt-5XoxZHAd`Q|5Ijd? z5A71>12A246WznRp$S!khLnAE)6A~V8&(&S&LmnkHn1_X2#I7QA3;i(A%<4nTt&Hw zvSAW&d3EOB`uhDB`C;Qge{YMGc>z(||FMZsl3(}**J7hfa-SA$hJG>C-MGmjRWGGjb zc z6^lJUuapi%D&-M6QSE`sgXO$y<46j#Df0_$8B}Te+pLF_NE7BrUrIvz`th_vCDSKS^1G)46j5*Cl%zO{O=J znKoh;utlWOM0={w?7>`#Y0apR-jYtSkDkUsg_MBO+ti^C$UY?*F?CfHf!zBEIr_da z1_5(Zn>d2sFO1yRo|D4lyN=AU=)of)d%VOd6jMD?BKYcYV6G5P| z;Nz`D+^lMvK6nc@+bzSJRFBk+&RQY;<#4IYIuL$#u8~ZScKi{qWA(^tXw1Qds=eu1 zoJoCJn6;t4xoPwG3S{#2PS6Fsvn|`B{XsTj7ui z^a(F?XtxR0xp1P-Ii^y|Yt9KpB?hjxs-{2riLr8>GK(~%b^7O8aU@fN?8Pvi3+NN z%IA@eI{iiVR;@KAB{FgOQ-iQp6)#!x?V15aXgh_jBNW-{^TU1(gCaHjfRFXeR=*pN z-uGqeKrKTGv{pT!Sv=7DMmnELZjyHj;IDTS8f9N3<|~LfRJ5#>5Ptp8IYht&_XJJ< zu*clTtZuN&fNOH>n2en`t9#bOizOu%jD2afJYCV_tNFu?<=>eo_`W1kACng0U+2C9 z+7g7Kqk{ycA*V%?EYb&RFj-KpTtu7^DkzhlTL_H;`AU;d^$7mg{*^yN&_NOr=@0>o zGH2Mlv>amA=56CQSkbtiL!I9}I%@Rm=fq$!hTBYyLzM?d(4MPz(h2#=5PQPm9TjZ^S^lnI-fxa0@~ zyVnGr$Q+d{ALX;MB&;OFW>`?^NG8|$q1zOBG=*DQG&U3uEHGI~!RQF-1=7k+b*8uq zIMTkKb8W!Q{>2*6IZGGe$|=jW(fWsEL{zNXM3b{5SC|U+X+A~4|2NqtTI~r{PMhIA zM;l+7=H-f9jUEk*+_y1Sa`h$09f?{B57$r;Tl&0+aY-Z*=vKKSU?ya;68H+|H}=3( zFvA{ES{$PVm1)EWSb^$Fo98A6f{wV?ndlYc8VM>`ii9_WaU0_cPZFM%^_CsAPe_B% zEwNrbzBpKvv{ZDAQsJ=gQ%tRcXZFS(@ZjZDArzrn-=(wlO<_3U_G!S=XW1M?xY6x& zw)T~xQRecPse+;2P2KD>iA=?HaXg`r%SW+OgqPh&yV4OiM{(>7Y(!8wguzpG8Pm(W z@n(H$!0<2SZTo(6jzjCVLcmGr*{lWdHuT9ZIJyrgO&hN5KeCl8k=yJyw^U{7IA?a; zyxTdqc`otKb41?Xa-g?`Ppi;DDq$I*_D{5NW?{sQ1Uv|wohm_ma(bh5fFrQFMLnP@ zL{D1?>w!HM*KIg^wguG=P+A@T<334$OFQ(6+yXliQ9eA_WtQW|gvJl^4kIU-{MI`< zrtV;-(?7h2)?Oj4@_Q76G>cXfG|aa&%*>TzS|p7TvNFDLkxe=O85e71C4kl(1rxgx#S%~Ep z4^dm8yKtYeE@dS2L71_u?I_DXof60KYLVemG;n%RnjvkQ9hh|CB<=`i5fK>rdB(G> z`2ONey-Q@8-N3UX=Hvr;`U73%GOH87oP1`1`8fCI#V5cxmB5%5D}yUn*i5Ms)*^Mo z7xenav+u{YnghC{Ir&Gc+~S)2Lad+ZcwS*}m~IIJyAkC4fDryd=RXjBy(95FVt3$E z@WS5W7s;WjV()EA;%L1R{&u-nL9ZM|tbssPjWt*Xy)hAFDB>0G z{#}jwKx)@f_b>Q~eO(@BEVIo-eat-8h%~JqPW)RA3uGF^zofv}fPXneTPSYfk=O*5 zz{EIy0ZnoLM4w*=mB~2IHinzux%h@p)0xRRm@l<)Cet#)o9r%mtojxGx=^CPR5XxOFnubW2ODZ5hqHI- znzn;5f`R`&Z}zINxO?tbKukhDpN~jdB?og}!ff(!l$3*L;kh&3G?*ElDZbpFRoa`a z&?cEDN`^OB3ZEDaKcEx8qIKth8KY=<tn%=SQ*bhVsk>; zu;qp2x!ulbqYE(J;N1g){tCXxm{F{}bj9w@!mKQM4Dn5kw>R>p5D7`sOD9L0-a znU7uo!3O$dX6UKb&?#v*jNtj?@! z2}RUyGA0V0jb>~O2PZg1%LxS(^eo?ST;)07SKUb{qB1Rc@;VCpF3$^994Dx}_5#Sl z10=C1lL#2Pf+0Z)Uxo1n9bM?rLSe6pCqrjB5+ss2vH77PMHe;11DBt;b!RFYiu}@N zfJvJFd=tf$#)v)|0!A?wQFR5)?wP0#i4H^!{W0#_9R z=!h`VP4|ib$+w(s41gqV{b!EKXarMNr-%WRg+Z|Kv zj-)=aw`JPRf=h_7Y1D!$6uYy^U)?A}RA!E@`5y|XgI}v+Q9b&)IQ#k+>YUm1%?P4N zhs?2IOP5O5eJ|XHp+2rXVqW&=<2YuX2oiFA?gf7= z{&-dX6_8At`ZS;6uazWr-Gu*vKh|#J-XIn)7R*+;qLiX*&g-~fBlPn5ZU0$~+p$}? zcDu*$Iqq+E?Z(l$tK{*@ZHR&Ws?Sf!7UM96mDF@SwuQYq-mMUmUH`$?S*g(hZKV13SBCo+cfFgQmj z`;$wUm@C4>E1CH2L3N7ZAc$AU@GmYUe|w02Ueh;S^G(c|6~A=*3t)Ka(h;~@!u>uP zmYX}*{YADtYd0VHCEJ1sb&%%?kao#Gs|4q-PB>CWPc_oejxllIG(9AurC!I#W7(GD z2g0*bi1R<^?$lO)xHqhphDZ1 zYB{h5)2tT1&ytA!q}w5@fUuo_SrkJ)qX(<>V85nWi+UKUg03W*3PhQX1g!by;AK-!zbSu`_+51Ym% zpVw2usxl4*RHdfxpM;7_u&s*0Df=8u_hg@uN#In@O)^zPDsIRw_C@0)5#SG$z&on{ z(C81|BEDf$i>yylQGwPSJTxamzpoRP`t;>Qbvhy5%;0QII=mv7IUq<-)+Q&GfQ=P` zSwyh~PBdF)_sMiqsVYIYgPhIf#bN)*)q%ApWe6$17+S=>|CtfgCUV)3Cp#Z|T58NaC^Pik zDH8{nGY41;$a`FQw^wH+lq#EFG)$awDZW!U!w*SQ^eWs0}-zJquxj52Gf9wAuUHa44)?s?4q{Ca!8=Kg~W zuOz;oqsiucHg?e#D}$>wcAh4rOAGdsAa1obUsu_0Jonj^`MlYZO3Qd;MZR!#2mHE) zvfK0tsuZEL+UTPOFFk9O=~An+uc~#$Tyz0CY6r91f{6?)paJSI6pNz=j~P{Q2&r-I zIE#W8$VuzMHb)K`4!T+YHx(A&kGp| zLaM7FIg=UXuoHLZ6nsIQL0^BQkEl!<0hVWo7%mo$r(X$lw$5yi^Mw@$(;axC9gB%0 zgwtgF%CXd>$Hp~CM7LJ&!g>0|Tj09C4rKySh^6$Q!PAASj9Y5}pESsT)2+T1N`h1C zZIpGe3zfH({@c;%F~U(sUSQbSRzrEux?Q;Oj?elu1gkH+IHAEAXD8wKWh#c0v!6Rh z1c<0nCp4|Kq^N+fwIg7%o@`L^MsdX()ar@hoP~20Q9#s%c)U?wPn7lSRw?LPM7#76 zS;EUXW+8_Tb+#XR^E3>#hv0(}h;A{1fIxm2PBZ$q>>-)05ZpQRO_T*7NOh<+LTCtD zXb2{^zlVr%qlqxV57P`Za8&$&m2ny5q&WU1O+%uxO==4XTI#%736UxelD9!*YB2}e z{_Vdgh@zjaNC7`{YX0M%V*bCK)&Hbd)GU-XO%Z*K`+Q5fw zA&^V8tNpcYGzoiKj-kingMQd!{({ASa|qYcpy{S1e^U^$ze{A@NCU&G6%P?QE0=dZ zyJ|=L{yu)<1C`tb1|+84k~Q=h$B!c?BBXhj?V&o-&{C`SQzdpX-B6zO2V&w;y+Ptn zx}y$~LwnwrgTPraIfH?Y4ab?$8B#FNQ&IHmM>@jhj;p5{NW|&vcZA3++;eX0%B8x9 zQM;cvRHiPp?=7o9@p?)$(iogT>xvANqfbg7vTC@cSg$4`=2Ba!(Arq4GG;&G3{pLG z!l`i#QMCw>DXI!CQDfbVB?Z;D2PD#2u}(Kr)+kgL<0{na3^rzKZn%`=wI%VwsjudDAN%QCTx2CV7NTXc;w$+ha?pz?ZU{ht>2py+!fU<)UwoIN$yKgRKZp z+0u(y665RGF?6PIBj@?Jl@dFR5wG?_!xRZrvWHO-Y7VNyR_;2(kWv^9N+KY&V|6OZ zck02QA&>r4_?+~>IFWVv3EAxXkgIH!f+HajR5^12*m;u~B@~vXGmAWojpdOMr?<|A z^GsGyo5)b9=qYPXjU-e95=*y*L8cimDDkJ(nM{^ce4`l1AsLK5MuqbFZ)COF5=W+~ zsmMbviJEm0&u?tOtDG(cdux|aXnF_K0pmwUMG>`(bcfhzyM{``Zf%qX&T?6%elgS! z0+?94O4JY;IYB+5&yiLp5mfuaPGQzRR3)vPwP(M^nh!^|^{~ufS{^c~m7+KYz*d3` z0ReisC4M5*mVktE8(5Q1ZXj#lbKpQl$C6f1IrzBvRXtc+H_Lzls|J7PR5rghb>B3A zHloW|R@a3|$3?IYWP{5i~j|aazaPJtRGc{L4~=E7wtl!|E5NrqPc5 zB?Hl)W=;jJD)RF~1Yx9o6dA=Jgu2;t`%mwpne!}^*vESaAMyTPyaYu|a?hBYg`xAi z0_taMF2DP1vah|WtPzqo{ZDXXt{?R#b{pcs*0WRMB2D{^)2HIWUovz>qk9Nt%@!%g|a z&=&i*)orR0O7=JbcDNe`INLv>u2GWwBI~mUWEN&+0~#5_w3bh7C-r-3-u@Q_6&GlY z&f%)4_r;S(>-$n_;ulZFl}&kc7w3ST8n>4?>owoB5o9m_?|Tf6C!FrrL!ZsFe~FvX ztP@e62CC+zm6$_1S$({{QTYTzwpfF0vXJ{8y+VaH*?v_X-?4%x`1^7aVNPO=jgUIJ zAtUG<|HN0mY)Q=>!q?Fc_zhk-!Efvie@FlrAy{$4`$FLs`zx#%2v_ni(pzVifm_O;U$V85D zh;D)vYavU%VURno=QuN;6ybB(1`E9rkc7kk{{9zE@hZfns`N+CApRrR+9tj`~7v<$`4evr-gRd zmOO-M3sX-ugiF|iXeblr^79AP1k@^%)aM(bXbp6b5BZ=W)KwEy?pcAwLTWBHZhT=&e84#&4>ZOY=SEWV??KWQ)!wuLER=DVd2n+92Y5WRCaJ{0^D!k^{WE{#cGBg=| zTyO7p5IIj+Yr1Uli7gP}v=EY(-l zORJ$>={KFC-^3H3MU8D6*!G;?zg(|grDfMTrlR5NOr-7*9p+)>Ej`12sZ<(l2E>?s z#&}t}>#lP=O=vXAx14kk9DsB;JbLav@H7s2l+2Xt)u~wG#_oq)E&;x!CMUW7?ft{u z_1LW3OuxSoExgLe`Awz43!ivC{P-aSHt-xvW%c2@Jl3%iuJUTrcu{{S{%1u%4I#Tk zt8RmsVWIqQiFm#NI5&XIUSO~YaZ#|yUScq*j_x2Kz>bAy1ZUr}cMHTutse!>Ys_Lz zOjHOD3rvm`2l8)}{bz4$NNtrDu3Rj&s=t_P$KFzuWIrob$pPAg=qh&xx=)8U-DX`k zqt?gG-&#t3ZfvK&wr63hL2?@?bB%KDIXAl-%yMRN8i&&-e2$ z^{2|2JudnmCIbV1vIkVYGou411woJ)rM_UI!WL(9cP^h!OCn0qgB`&3mn4GeQlbBLQMn~Jv-Ot#V2BU6Q zj~;(N#SQBsQEr$BOV&)3sAtU`Jbsv#Ivy^70aDfsM1}lGIfOL+yOI|(9+4Q?un3}0 z{Wh?k1877P9~L(q=+KK3zOUq)nh3w{gFAsf{2J2_s{R$7s`8B+_LS+?L14DapDbh2 zQ@ANd#}~eFmH}|ahwAx9V`Bt_H%LIEYEgE~JY};f$YgzP`VaQL>DXE5pLuv8F@F8X z1dH+B1$`0SX&~Ovm<-FAk{>Yb9oct;cw_+`z4nu#{@{GBYr} zf;>m3Mc@BhZ2W&j!O)n?D^o)Q0d=7Nw*?RXuZZP8cY^`snZ zZ59`p;x;IYSf&?-${-g7l?0`fIt(POfRa1z9R!pkRJ7GA1WlZ(trrB- zn|{HR6+wpm0SU;P1Bv+T`9rYlVaJqcyb$;OMf{rWb=!XG{YvwiH7;bg(~bX|cW0>{ zRf|=-VlcFtkY#_7$vSbLnJaWQWsk{QcJMUtEg**ez!6UEjG<0tG`USOji=wu?8MUg|r0z*~vN)!x4hx!b~^l%^ZT8g}8Z-`f8@9$vU-BzAf6NKOtVu zSz))~FMpY~u!npEwrcl32cAH&e9QKMaU&VZjOxR5qd)<8sOKz;v8Ye#qw5yb%UM@- zXi+D|3zDp)Q_dTb)Ts0_T;;UT{q9WHY2#_d41OkJ6*Ze%h9%eVrF1Yudv*<*w47LSnw6iP8&ykOjkNvA4au%k(pBtA4(VnXe`VFO@}#(EOF2VZ zJ08Rlxvy^$(+w1I$JqD<#wA+=BZVRW6@xTV!R!vHAeLb&H z`71Q?SyCFLM;%47ERa^mQHEJV-r~k|%ofj~sj1XPu5vnV)F(*pZk(g!d2?xa9=I(u z+^B*OsFUwgTC!3IM@UgRNB0Go#96rKZ!~Dqn%GQm)!c^8T<~W0sakj#xlB&cqtyqP zl-e!cIa-LT6rqag65o@|&+Rcc$)n9K=eY-EBTS5Tlnquk?JuO*N2_#01=FFFWJdRK z#qv1b?KLVT2R>m(_)Ck8>xFO*H3rXhmPS^0x!$Ak+-Nuz7{V`Me-`jBv5Br=y6e<^W7ttlWfG_cQ+jmPT3nJ5 z0Gx%%`+)Wa2i&o~3*4(!fYlHal;>Z&%d)cSPT=s)%RD^L_6XYt1$17{5_H2zr$9>m;0W z%2k^^f2kc8t9k^_#`SPr_10))6%SR_NB{#>wfI!=QnaY9F1BVn8u=0n9^WyNoWzg^ za`?vZ?^cef&Rj|hvQJF&lC#E?^u*KCkt<)nL#V3d)*#BAYc}%UN6$N=C6%O?;LfLM zhN}5XzHBZ3B!V|ied*fT%=NnC& z@ttFi%>7VCO!Qrhx$FIi-Ee`(N`@d84sPo1jZMH0H-frI{lhWH)=Jc*v5NFVo>V2# zx26i-8};RhHE0|B0KSdTnHn5`>z(47IjUIRN|mzb!o|(p5GRROoim-RvFRH0`dO;N(M-%M#OR!N#Q zc{$XI5tU^w?+iiFbabr?oSOgo$Cu9vfOn`KWgU9e3@UXXJCU}C*gG50+~raqfr(`{ z3sy=q-|v=R!;{ZxN5l%);MOo-Gp~;T>mLf785r_n%y#~TP`xX#lG~@qT}Os9`fHe# zgIFi4PbM7)cdU?hNPL2hJU_lEN?Z|f`#_~1L052NFAkb@&pJhDs49XL<6>{Ez*>n#LY_FOF?+;P8Q->>GtU(tHd0)XFmMgKD zzQzm(J(ceAj&YdDM^o4M>FazqjKffXJq)>VRJosG0`K@D3*{-n_hEbQY zik9|HeCPr}RM_Ca1QkKa3Iz_9umtPbrrPNVb*PVSYJSX-wzU<4YHi?jq&OuOra4u}_GHbpbyyD59Cbu7wnG zc8ei*!o3PIpxW6V%1#V@&y=BLppHjV^|w`ETvGjRotr5YYLz){)k)q#Gx-&p5#!4W z`L05FrJm>@AbU7H&cst&vJ1*O;4(#;HW=Uv$YzL)`%E&vVrsqH3V*K=&DYP$MR43M z+*bOe@Kla^R(PdMy)Yv2s(VJ{y#X68+?r+unED2?%(8W&xx6a4b#B3qA~ev?6efQZ zadKPZow5YTGP_f{9o~DTIAjZ_$#*EWOUf}Ysg5saT&)N8if)ITGVqM{@15vrIpXNv zA8%j+`F{iu{&&^+PfOsChL^YUvkU)7iZiLhr10=C5H<*i;W%4B90CzuI3t*hwJ<|k z8js288rob^9l;z&Y+rArhzJ_FfB&a2`JslQUpP`Aqd&3jYEN}Ac$@B88 zZ|Rv-C&!Mj^q3yovfwA^j<3ZuFUex~qXFM3smfTNT7}yjr+;j<qhhJITSQ;fXPEshhLT=AKUlTR8Cb+x4udMq;!%IfIyTPTIOg{7-#{Nb z1Ztx}I*rWs&fl=w)EV(jn|idpa|o0%PZ~#B<=Z(ZmeV^rh|KELG1a3&$r2mz5x?6-Og?(NqX=QFY-xAHerp?u| zUDsS)-exkN((*{VUZ?Lwlp__ocUq%hJ^Cx7#YI|s9X8vBmR8$tWovB<2v$p)lt3nC zan_xsE2X@tr6%(4QdZb#K#Tdt2?o{)W5T*HFQYJuOptJWjRF(Z^{SwDJAa0u*4$Di z%mo~5s8aZrGeNr>M;r?nayf-HE?kk)r~j17H=7kmi0moz+UVA4)`?S-5SRHh{LGRMRHrB1o8F$<*HsfuC zzf0~L5^N(vmpvl32ItKnCEM3Y4GtPem zX)*&GNIbcWD|p&NVB1vl8VNf2LD)t%UoiJqPK6z|=Wpo|bDp;TZX47XX1Ru`&*UEX zd~Hb?j%t;`b8A3KqUL zxBV*|5lh2Fj=}7y>`~zjYiGj70?K?fNDW}6U`Jh8_|%+cCPXt%V=l32VZgOSOUxL% zzi=V2iDP3AzzOr#VKOPK#F&XCD|w%Z{6a!3y#x(FiD8x-C6X0hL*?V=o`D)!uSYqPXxjE=aOX(qTxARTP-MND+@_`;a7%@;;?+GQ3Od zuEdxH*1r>)2~5bVfhh%r*+ofSh*y1MCG~1>O2Zm|1v#7u3u_4$27|%VvUMBc+9LkV zXfRlITAt6DTGTilO%BUHD_ROYkzeMeD9TyeceRoN%!Gyt7P<&T0Ce7L2`$=;^N2N9 zk^jeFFIGyaa0H#5lEJ}*ON=Z3+c$_?d$u7~d%iJ+%VoD)&7~gSi<20p|k)D$6X23Vlj7-b67f;G{y+fDnHg;&a7OCX21O!3b$Z`fvZVx@4 zXUC8(5Xv4m*OuvK;T=7-eCNWYKg|yChP+P~)2euk@NAB=#7T51_G?tEipnNb%);N{M7JJglaM#P(4bpDgCspm95$?gkl zTPgb;R4;j`5(k6$xvyy$2Q9OJ>pG?E+5m+t)1RvF_V<*7m^k|}O*2FydcOGy&nP~y zBCwz28`k`V(0+V^2ZXGH)-mB0b!w)wr@vf*>;$o2ZW44Z7ebM@VU;SBx7E_i++V_j z!TSf<=;u=&nBr54?W+3`(NB4a1KV9~mu}e|211KER}8iHImld(?iplY$fT}!pb^N9@k1R{sQUI7v{c^vPTUNn%^LR?3(`1I~4( zurQ?&PQ7>j{1+%BKKpPv<~-a-JhxoT#@~4 z&IXmRB4n&_|2$lTh^yFfStW1)IL(!4hQ>Puy1KUGU=`ek)!Rv5lgLu*>`!GY8Zy2@ zLX28X($+6h9k(e7_fu1qQ!}VkrB_$k(0&O{+g0z{Sa=HGiu~9b*%B*OVrh?^CB{m+ zhA3h**y3?GkjXRWN&qL*P{T`pPWp1|ltu%!LLLyaSPnRs7Xf>Eor;QKd*0zKgs$UE~WsY_NM% z4~(oWfY*{zn%5Q?;btszty@9y*%(F}Rv(3fU#I?sDtpgKc%+%zM*LE6J>uL_Q^c01 zd^*&BYg+0QS=-7(O6GNmphH`gVG94VQIxI3$^Z+32lfs5%>+kHJiiDX7lao*CY+F&`w4UnpkG^9fZ3vRxT@{>&CRH&qObPh*$>{x!8*^7j)psnfr6I37&y*31FWR zG|w5VRpGePX6=VE+l{DWlc>#PJHrR8isH4WUJb1L_H4(O2OkYDmEVJ$YSQ@*ezbjd!xu7B&fGGG0F*AM{5dHmI9p-qqT(MJf9H z@pg_;0uJbKI(VQ)D%%ixH-^TJqzTfBhEFgGGMy+Q9Wkdg1+qvg6-&0RAQ~*&gq_+`~??wScz47)h zF`$S4#1kOkn#h|DP|AwS_TmcB%q`p=nP=)fyT_O(V0}lubG!$L#L2sP0QFSh0G5ZJ z9Z1-9e*@-8P6#|dg+E0UP&gKSpvbvs3X(SXi!T^>OfbH&ABkWb7-jjvD<_|ZaA3yZ z1=Y=yXcQ1hb~EW1r3b^elQ&re!vC_9kQW^cAR`2^1_}e$^L<{l@@t8r8iET13bUPs zn!W50FU!|^wlnNV3UJBXI0po;}zUI$w0$WflTVT$M(qM^WE|Lc&l6%K? z==!>XMct(@M~YBGLEn^Kd8ZP3x+$wsu!4Uyx~;voyqBbtK33<;e(j|!V!d6 zgJ5=CCWzZ^{4HM?%I}c}Qj*7gfj)@3eY9<@!5bJKO~e76!7GAK$cIP595P0lAeHb2 z*tbpK4iBx;4PvEF%&!sMQ0V&Yt7XBqhkwR zbG2&(Hq7Fb{V{zd*0DJ5*W@$EDF4{}Zxsy%NZBDieq&ixl4k(tAeHeHs$%vGP;c}u zX{d)j3x4fcIHT+nE{dFK~0y(5dpcGHQnf~8QtiPLq<9-6_o$!Q}$j1BT^Rq~LrQ1MO zcxn)kdSk_7gP%einyB;kj{wf3nVb)ys)Yh=O!Pv3EpiH}>WK%Nb}$Ot2&V3}z%+wr zv%)JTZ$}%wz)WX%o!Z5jKCJ0erBX+}V&UxhZ^q0SbK4<-Nl_y&$@B zgKGG}1AOv%e*j;+3IG1m^^Ete+Itj5a0GbvQf+q@SXLAn4EMo_u+*J70x+cB(Fa`f z5%ceX6yYtAs6uzy)N!D#_|vv`4^X{e$?lp{Le+$OKBl6JcF<{Tut$o}-w1_FKg*6n zc5uqc1;=YyR|>GE2C#p;OPoldKafUpuf3s2zo`(?!Y|aUcmEgd?+hGZzmdvrbF!Av zrQrJL>7PaF09r<6gXLLBi)hReqkv6Tlnr*HaU`$V-yC8V-jgxP9T&>pm06_h-wv1dh*4{KTjM4+VkhygSGRkUwW+m3rT|{yZ5A2qu zny+Aywx+CKwt<6h#Keeg#2`H*ShOHEB=cFcIoF@Pmnf0S7g7z+{x(y<^`huKY)UXw zLROzKtx=&{HLftmY*jV^tt6lCrE+dB@pmz|&rt!Z5&4SDyco@qIwTVpguWq)vm?@m z(1HVwJ&L-T!n#~FQQB2a0lsmBHJ7r*YiZ1+a5;WEso zxUfg?W*^_!c|**|^%J^Ti;2`g$ebi%;|BGgk7l?~a<+Ll2=S+)ck|!}(HVOuj67*q z2n@F}2b>OeI-X_9kx#u7f+~>Lnr?22M^~m^Rs?^i44@kmAWz*Pb%xd#dgl~y%d70b z_E{3_4uiXOoWrz2# z^>aDJkHyV@b#)>(HkD=nlEzm;{Ve>!!+);l2l)tx-3tct}K*7XaGHLNcm#y;m#*MImM}K zy#2<^^$DI`&+J+fB$s^(f3p0QE0=q3s!1dgF%Qpq?Xm5&bmD5uC1Zp0K!GK~D9v{Wm?BWnOPt@MI5zsF2$s5Ynrbia4Q zNdkR>WDEWJgiDNkhuTKO?SgF~sj#1eCqKb@6S(WdUyC2pd zac`rpsw?cAf07jDMZKAa0lt`Db0Hb5xS#5{RE>14eUuRrgWJ$z#6wf9-kIUAu2fiy zUga|FDrJk~Xd~qxy*l@?)LsKO=7VeTaLy4Z@BEObE}m;{<{&rXfrx%n9&>)OJhR1N zqLiKi#SrRgd05;gK7y3u0<)`zL(OGfHGG>LL$u_q)2E8NEaDw9K4=SIKuZPEjo%gX z5Er5#uLT3w{FREu6q;)!xirHV<)UWDp8dDKqIt)H!z(PuoC7V%hpCK3d_c#{jYA(8 zw&SzU;dBkVac@<0zy7fOh$&DMy;>+Z(X9ZHYP+v@gom6Dyr-#Sb>n+wcjMc_oqk`7 z7Jlr-*>exzoUn)4_h#4*pzFikO;DKK5aO@(Jv|A@e)STc-!!56xrg6jnbV?2tb72| zfG(zir2tnWEG_bu5JjO4A&nME;)allh|JVpIz)93RT0f0=vOMhWmsOY7IlUL%E(NJ z+?Xv6c_iHM`QUH-L`HkWKpoQV-I4G3+W{SVe4?-47!3u%+eS=b#7U)azZ^4U+DD5r zYj2|r7nCES#KKX7CWDy<}uoKS6Pb6bbJP*1C!o z#M{jz&v0xT;@u>jf=UzmdD(K40#FT5K0w4<$0nC1 z>>xfxD%K?wqB|j1*r<~t!zvxIU2JS%*T!P?exq9kp?{jdZ@KJk5^PO|xG#S})3=~s zJMC?fZ`lKP#(5w4bmpGYKBjwx9&E5F*@#!nKw=yziOye}ACc*CoBuUyP;HW;Z^KjF ztSXS@qJiBMmJ#et&x-Z}POG|QT9$tE~XugZOvX{q)x!>=v~ ze3xrB6YHp-s_XA%NzB;Ym~zxQ<}kSTrkR$!7S*Lv_kn}V*&N0d{j_Cp0QRNIzscnF z=&TqgMmcbZ?W*3yIYNQ?_+hbEZooQY{Ru9Adhvle}I zs%JTRlv*@;XXXNkRJ~+Z^V*VUZR-9l{0+L_9gg2k5#Ke9m%-|h2)tR(>(S@dvq$ar zI~={P&lA({?3co~(-gz%(Vs>b<52W~_?a zxDZwM)EWGx(OX;1EoD&L*fRIp5Ux&nd;G;4UvGgS@WU5jDm>*|cTm16175s}UU3$0 z6ntb_`LY*xR6c)s%athkzgK^$ys>iQ4;u@voP;vVdx7unJW$P8MFvA4x(UY7O*|@q z^pOVXD_hej5bACjP#b- z88PjqbCQ}l`*Py%jq9%DoIdW7Wg}7^B{uEVP_`I^ed*3drWKoEL$XSqa#*ENCq-tY z1zlnZJZBO@AUdGyY9|@a$g?d)5_p%_w+^7qAHPksw=z+aLfmka5zO7he2mB0-pR=2 z(yo3x5D7}z#3C~zjle7?Jd+ysMruD)zH0e~Yf(+Ki5IKxmn`=jLM%;Wgi#&QS^3*|CWt2hr|274 zL4&kQuwu+RZ_RGXD$sxk-$P){awd=EIGhx zlh91;d&cEsdD%c@g~o$x)0+AC=(o)U_>vN%hNDo&bvz+RjC$-d?*Q)Z(4sRUI`2S! zrF3h98+wyXL?jBOBslQ6Q32DKlS@+n-qGMKKjPr6KO*RS`T{t0-uk;VeNLyz3&%@` z!>??gh^{u=1DJ)lFG;h71|*GP5{5X))Vq+(=t$NQfg{ zaFxoaYiFEuO5Aaf#t~r;kC0Ie_T8STd4KxNJYJZWp3+c34E`=BZmI*RQB7_(+cIkj z=>=8J@~zQ_$i{nlOz!S6mEO!Pk#GKfs=MUKxVz{`?M+3D{(iCyM5=94%r?Zfok<&h zk5QMH%Lm>xWf?uqVh8!iFv*Z#FTP7BS(?pDVg&#B3$!5=(YLgd%8WDYQwuWXG^?Q= z-*?ST^V+%;WRFp`78?i3M#44%TsDWraHov$D0zJ;>NyUG4zAu7X;4cK#K~g?W}}W% zFY5&g@%j*;31$@$D0j`NbxW#S_#2k%jq52vORB|WmV@<_zx|&q^->u-f*yz3zkk%P zg0F`{P?xm}$VeTNunUG(I8dC?LGto=(LpJ>PCm_#I<|M)W17~z&mHgkpPLv+t)nTY z?YkE8NMlfCu}b}^=JRL;$%TSXwO89KQT>I2=y6qUcje2 zIz=qmQ>bc|d!>bFyk#r~yP@DJp_cHrqZ~OBrypS3ePG8fquK})@Q^3A(27=;-83v7 z5-nemAh9rhP8PU4;Nf9lot|}jQrcR1wdjC`R9B)X5c;@;j0 z0dVVm3h|(TjikWbD|tWy+DL_+Ec`%Hv88UU?gY6EfOm#p)`9{$|7lEO`PyxZyuc|v zu;6grqVb_(3ML__!YjL!f7s2~BUYp*5ej@$$q44N10kbK8DP#NPC(rM|+j`Wbp8wkP6|K?^(z72y?WK5&=b)VOPLU6#By1jiq772b$HX z;X$1?LOimvOd9CUCr>mM^EhG9^f>ynnMbLzU&fj76O&IHtj$cuGiN=vAXm19c&zn8 zup82TgRh2>iM+azKg~{mCap-)+ZD5Sgf(G{+hdb|;}u*CP)v_#!Xae`KGcUeB84jv z*^Fra#m}pfN(Y>adFd$hMcH4a7)~vq=rF>d3EOjkp*?KLbyR|1BU*xAv`rhCRB!N2 zdcOnr=Ej=S(e#df3H)jk`|zS9>@e66@AQ^^Zd90meFMLxa(8U5ciqPkV#YAGZ^0JR)40Mhn(w)qZbXFUccCfT7tz17&X2bX`YX(sz;8RIamz+XcO#=-atC z_p{^Tk93M|hUI&aforXILyXTK<;i$UTROs&xkt?QA0L@Y`E3pZMyISRty%Q6#Cee+ z=pyEchHcytw%IBEr@r$EVkC$2;?O|a<5aI%uK0%28ZHIWsE!AtOxbPHNPnq8T-D_1 zu?KW~ia+}EIC&!*d-kG%4ISz46z>?U=2i$05hyvf_D%Od8;v|Ogn~r)1#^@d6 zx)-@Bv#}~DHN9s!?bGk>m0s#2lk*kci2##(5_@xKd!4aAvjKbk1`cCFnz-^5#Bf46 zZcV(6y05Z|I#El7NV}?w<8_M3sb5`;R<;?iakFC7Dao)m6SGIS^|9EBlABD&Nd}WJPvr=9cL*cc;hK_P4BP4}CyOD@? z*k|)06-Y$DgIo}hM$(!CM}1lggZi6n4ECn{hCP?=OeUahx_14kn4OaxY=a};4}NV~ zd(Hd2;dDLr_1x3*1$G1Ygwz_M1HM*Qm68myr?Gfb98$ZmuN5#%j+JBSUSh!OFL$tZ z+q~AJI4%YhUNP^4`eg&Oz56cr@p}@aJr0CY$?U}X;sTsD$i!VNmgHg2mNHN31(W~70Prr33M$5qb}XeT7S(~ZjCfoV69|> zop&2KOull)3&^Luv26c*g8dw&NI-t7=}^kVO}bq^nl>`!D=U$`%4L9ck&|Wk!zM8- zU1xUk3Ijak80E97%`MKwWc5~N+X24epmt`t=vZZ=ljPZ4AwezSE23UHDYE>Q3URzn zdX>D}YK>IYaLdu!*N6S_?a#j5*h-uf1D|HC<7!<*Ob0bI2}@6Is>!yqb-N2ld4=_x zw!IPI^H!ADc@#7OtZsi0qb4wOc2tm}4p0y*Y9v?qC-{n*b839ADrRX$LLyu&<| z+V>H9n9Op{9n00-7iqNZS4GM*+rwQ-#Iggjn+u79@Cd@z;w^Fm(CNKAh^Qq=?F~(H zCpp8z(G(=ivRAXYW`nT?vu$~U^dwdmSO)f6of3_d`Y*?E3X;Gja+@bUP1kJRMgr(W z$@SYry`hK2H1c!~i$Doh6%b`U_46TJK*Xmz3`Ul~8Hj1M* zsC{Q2EpNPD|0+GLmL%?}9tL24aqI^3Ki?p>TzDl$RCL0>xbUls4SCo2bzQ_yo^BOU zs=7wJ;WamcaC$;WbQ&%!;s*~j-1bB~>=Jh_>bwKh?tp5c1y*5@CIAMJvt{Ply|q9P zyz?iJc_zm<_yp0A-m2`jmk)*DR5cet@<#n?fZ+>01@$n8Q*eD4at|AMWF}_z%kdQi z5{rvHCjZ$DH{UBDm-qpv@HrQt8obL`dvX!?SJVts1Ybm+Bbmjy5$T^>MFsH^HE}Tf z{lwqw*W#o5ggz*i^ygt8P|;eCxAotDw0IYBEX)T_i;y1MJ%ta#+7k(L#O;z@_TY6C z=03tB5fA2Q_T~t|7JOe3J}v!@5du#!I+W~2Q6s>m7DVq-CBC^JW8)n&g3hDUA?95b z4Cn$+s6aQG-sS613>V8m4uLM?ZS4O_j?I+V(v}040=g;q0(dTHB-7| zlpZMx+iTOh*RZ)f?hxx(!0B23pyVn^kio&HQ&JJt!p8g1Wv-i@c2P~yKhUv9Rf0N zD(ja3h8^?@;o)5u+;hD&j^dHa2%Im#zrW=d<;mB`pF^eo$C1JPzx$T|%bSs{rmKvt zis6fvaADd30g^BBAtVWjs8N~H0%$>tFKhjRK!MtPM#d@0M%IzuC~bb_GJJaCV%BQk zd9P;I8;{v_9?U;>%bSUSp~1qEzRG*ddwqPLbAR#rp3DCQazjT&rPr4g1&=yWdD4%I z>81+8SZW9uxmQnuH%@g$Op0f5`=T)njLIui366Z;BbR3v=GEvSX2EUt6q2C_!R)3NzUzFw<}g32YSBcrr{0Z8V?P^q z%y@+rD`J0o_Kh-an=S2eacQaf%0!Y9%yR2zQG5fg`fq!>v-PVruR%phW9v{}`5^?SYkUWyhOvlS2_?A1*l5|6FOGL^sV;arwd0uI=KsAI4 z?oDUVtc4u?7e##(*V~kMT;_$v+*29$dNxZ$)3L;EDuOh`Ckefs4Q|3(UZ5{;>d%n~ z1f}Pnj-XKkqBxoO7V841S-fNDe>`8QOx<%gtQ3D}9I@{5uncisRD}UWA@9+D%VIa$ z9%1rtNmawFhuRF)MG@^YNnyz(k#1bIjy3X;z`R@#S)P7h1uBmfHZl2RJvdXJ>M$>` z>~9JuirVV*@n3B@>b}AX$ zt~u%qAT`BByfZBof6kT9j^4gO=1-2$4`lEiEI%zD^puak5ZB}}W`@Flmhi4uX2p}MnPpBO4!Q$<7V$rz$163h$P`d&Fpja=Innz3D&KQ2 z-6DbcLv_b#{fDdkIxG8+@bQ<|0Q>Zi#b34Xb+0`y`6G8^#rB*qee}<8>F_PR!qxW& zvKnCq2Z&R4yH^*_2xu4yT7d|=83`+@_)JC5&|9=EGFV4~Pk{6$|4(A)OBp#*F`~^- z2ohm&h$|eTq@+UsV~GzqPkaGMs%k}dG91;MLO+HNhY1q%eInX}|FZva|M z9wB&656W_pWZ;LXAn<{{T*UB%&e(%b@UV{nJx1KT)A219A|d!oks7jsd|{YxRM@Yx z!!O+KkzbYVs_klk%QKOXFh&VyY5g3|IwM|bL*N>NIBE>Bv>SvuJ<=0jh-1!fmGe@- z(g)PCTUYy(O70=xctYEApEg-M(S%^ZJg{-!4nh^FReLDpBJmXxJGlMljFM!OB|6V!lFEyBJ;)S}(#UenA5QD!7u5r0Av9ZIuPP#;d`Nv-P`z zPeP!Nzn8zl`3Xh^s+$Cwotc~aeKkG1i=Um}57>OaIhv{kcj0ERpBdbQ=g&=lzjTNe zSNvb!%>4b>X7)o)`8|iTzckNHFKFaU(Joge`-9x$chHDY?n{x$NCs3!E>oyIDD4Bk zo}H5AM5u&?awJIS>4g8Z0X4E3mp$yo|I&CaM#?o)_n!gA6FDe?`HJU)zEO-{k7bWHxPP={86Tq&8z}#6INT6O1&^X(@Jg2FdGmXF>Xr1E-Sx9 zJ88GP5kf;Z|4F3cNaj?48;K&USdt6>d?00u<}K3 z+dse#6FECR+CLDIyq|<<(f^~*|9@ji{_C)-PSUoUXFwVGmZP_jZkNVHeul-Eab>9W z${bTQ2~!2dQ-k#fNyu!kEM>zCSFe`$M&ScQl2DQ0xdD7p=#|vc!fOdl;7stb&b`0? z&f<7|J%5J>INz~IYsGbbg>eanQKBH>`@myEt|Yr+7_?b-z*w@Z`7<))U$>sHZu{q) zi_gx==a*ZOGmD>?X)sT5b@F)dQtXj zhT}oxfUU5n%k0UFRL#*^K_fK}>V$Zt!=@Uau;KWuUT)u7$v~%+_)B-u;Yf4J$g`;a zi>;r6J$5c-Wv*hKvgR6a7^)Y zm}g=Gj5%%}@ju0CY{FtIEf1f`b6o!0;)om*%?y|8Sr99~UNCffosZ>dmpQ0pS?oYW zy&R!LE5F8zxU5CZ)PzrByiQi{%Asmr=l(KUy%&(vWciyAMn?tHn95W!@rmqB1)^Cubj?TOLJ z;fw)JZV!lV@vX!my~|V+^(#wF6XG3e|GxeQ-vEI46E0C>Xc0t___o8**!pH_k7Qgn ziX#YQm2SzV=nT6&5)oBT^ke}g%3jB$mIOg#uQB_4XNH-! zWPs|Q%sJUPqGErc`(9faNm*g(3PbWtNv2CTKwDraO! zAU<R4akt}%uH&z%{T!#O^v;KCvmD@=2>wt7 z_&{)G5NJxo#E%51T_&7;1FE3QG_>13gn(8?31;^2R!$Je`42~Fh(CM6M0_|xpnUxU z;vTKhp|Q7L>*^l3LGruvgd2g=H#eF&+*1o(GMgg{kR^O0 z3z8*QW@q;@KK|w4X>UZz@Jx>g1N=J9<9=EAJwD-~;vzg+0m_6;`}GK>HzqkB5n;6v zFBxGYpeT+79U!xE?cUMQ{|u?q!*Ea&feh06CG6&k&R~i z9E9V=-_oju1ss&v4j|W7R!gys6geqJMv~2Sa?@szO`Wss_cAI-s>%k?b)!1PX-G1n<^Ap^E38+8Z2NbOcMxD0Bv?n^3aW3t=H%YW{P8HmhSji^K~*aFw~+1Jv0i_ zskCoD8}jcuxHZepSe7`%Dm+=1wwY1Y6WFi}h9I?jQ$CsqrY$2UZu-a*D6MiuZLAb0soMS&+AW0PrIeZ|<2M(a9XKy2B(#@nwKL*o9h)_S1YNU~o;_D8LI!}_7xz#we#5tP! zme|s;ioB1J-LT^z@3-l^ow4ndzzf0qNx=(~H_+}Pz2h3-B9>X`8Krcu{nyv|gU@rqrCmUc*qkTD#)4Sy_x#d%68@V^hipX-+mCYAN!A@-%Kj0*Rw57ixv) z210K^Rtj@d0a>c^IR#rpxgt~*|GKw!7gZwrDNImq|G zk$l5aNj}0t@f(A3cS@0bLsCgQ19GKbKz%89)nA%}ws-y@=?z_zbcSq8zX0ENO?mqn zck?rDFVY-vU8Ev_5BVA$F-2QsFp*g$O{eVP(r7yB3Z+XW6pTqEW>Uz$nI~qMOOeKq zJQ#(S$k49zr*zWn!9v;@D)jTgK(%@geU(sUE7tnGFwjD+WW<{B=DB#UzFY}xcZt)2 znpj;yJ7mA|w=9M_UG0%*XBzpx;dGQitYGR5!H(Uqa%vM)>>HCV)_^*B`x0vlIr7w` z9SyfEsR4?s=LaN$z3Q7|g06w`w0eTxSr4gI*mA#DzJKr3>hYU)=+3G~u8!w5SERoq z)fApgb~V_5enJoF@&e|N_q7}^W4;%@jwS1+Y|(nWMzGJL%AvVX7dlEcPC(m7!jHQZ zi`_qv4go&9@`@`rnAYqR26$G^73Isz(i5Omn))db>cm3I3yfB++{d zTwq}`QdG7Qb%>FpL`u~fwo#MRZ%mllLL48NnE$PJuw1)MHm38{)o}UPtLCch=C;~y zvY=FXq28w)AP{a<+$glnuq+7g_Wu(YfDQ^_UkHpK8V$uutQtdjoF3X}XG5r|N z64ag2SQZ0efzni@$Pt*p%cAX^p)sxyj1@p7fX=8dgV0NcLKr~6HgB1dy z8>3}YRnW7h6pbvfr*8<}p89Oh?$0B6HIaNFOY|MO0%PbHIq#sMm&-(`(osH)J9u4Y zE3|bbZ&C`U3ht;mTEjAHgM0sQh0BXB&C1#pSrdSpNRBP2w2St;NQ$kv)0x<3W~p}m zr9-Z5v{P9(pY|Wgxyuy~XYSwUHvF)=d68=dBZvfIS^*Xd#@rXC_;DwI;qLTXX24ze z?5zTqSAa=zo+cIxd^y3+rPG~A^a6apg|EJJYt92Z{d}-oR$Vux*RSr&kslTyg-SFG zZWm6t?1i9zQXQA%>^H6;SU{!-d1Bx4Q#4sFAVjc$EUK&^X7)VE*g2$nOu$05UOo#F zSa4wqodhwTUfSik*_6)t&ub5!d5^&ZE|)uomxqh zqG>If*g%+k@dQ|-;p0>B#3=Fdn|zY`KT$GnG3feWv`#y!kV`2Aa|@iM<^iV?+MGCK za!JX2k~hN49I$=THU#yF-S$OsMmX0c5xIlq+~v4-b1;>m@=@Xjy%?knQ0ssVgG^s= zJWqIcKtz^Vrtd+# z%-~WJ+?c@it?+j%oo{LtCEamh-2+8>PN4%#<%3PxZ$ZlR#zu`Hi5C#<3+E&aw^qGB z0E4o$)RJ`VzJ%Dmk{gcgK)&2^vt4rHxE#676d0)-g35#nSSvtcTFWwlL~&$SW8OpQ zzal$d=V224JF+`$cJSpQmMLe|CJa$ZkUgE5+ic2h z>d$clzn{-1+zuWd*=(RBy0WD6ueFGEwT=2cTO?+Qj!}}?=&DFfbSD^H`Hx<9c}%YP zbX+j<(ujn7`fKn8dxg#9x8jxRI8%mN9>rC}wLixtbBtcTqjeed7Txq%L@J~MpPqqM zn#%chNwznhln0rQ!&YtDD32~ZM1Ptp-bKroM=gHj_9$XnpRU9#4Py$@$H{a~ipX0z z2RRjLst97XRjPt2hijT(^_l3b`-!f!^IJ*o9Dp7sY1Y_j26+!|Fd-MOuMEys#WI8u ze^#K>txCf9Q~ejZpT$28au}O+hEn}45Ld9=;{mrhTAD}A?07Nf?HT2dZCvuYC>~)7 zOH<4Z^cO^-D0NJC&<`^Df!rfJ9T|g3-(B%Hh8&@&HB2+%eL4Fv7P54RWXmpr1lr{zR>rsNWLghwr zyf)zsJSy#@b&gx`G1OgjJYGXH*P?~V%7O%4Y3rd6l1!Q8s-@;%b~{?l2k$9`TaG|e z*Iz(cZVZs`$4&C!X*TW&UCw(=%xlQ2#C7tsF8F_IBsimd6UtWrfH8_T`%q!xlRg@(vv4V5@Saryafs`@&C=5oz7BFlP(r?3%24uC6_S)yr6O>A$qsHSOWK&OEdb7J%auAiNa&?F8f@f80WGjk#>Lbqet(k)^<9@siv=V zL;Pr4yu%rXDmPS>^R>?p!kqttsR+BB9y3Dr@bA*XrQ|$f7o>-j>}8mwItJ>x{!j8} z`S0B-P6lrpBE%E_L#n9O_-?qQMKUSN&EVOX^W^-GZ^ntV zHTsDUe};o~PfHw3ea4GPi+yJrAw>bKahT?z(w_oR{XQ15KfLoz(h#5WP3E>>X%BoR zov<=dL!idn+4~OYNro$!=F)@9Uv`f4KqA@9K_efV#1a*B45^Z}ihPz6rC!hl!@(hE zj{M(yMpSI$+5kV=STcydOMl+`USJ#?C$YlAH> zHQmj z@VE#Q;N5Alq0C-mk-=_ixUmqoKCpOb-mxC_73V*@MryXoL;%YpXuxc%3ZZs4EAjj;BPU>xwBWx6MvcLeyQDBxf(@6y+EGyyipQQ|2UlOX<)x7qM-iO zOm1f15F$-kw#KQBwOwK@T3*TMZ6*v%gY9S%juTRe~rq%DL< z5~UQ18B2Ptqlm+`leAGDkZX*3uGG~Yn1iZNG|(Xa_gD+@a|W5+ta~0JUhv~s@qHny zq#y;zF?FDTd;ZV3*Z@@KyARsv^-fI`1Bn1rPF}0S5EPazpfySPkUi zf*yyajDQ%T7@=pYWax^E+E*sz8JTaOLYcqBM&Z8HMjzk8 zV{#1|1(!1b2cg6-@9Vd`)1j=btd{PW{_u@LbNcxITh^ZZPy8hu?2cUMD&J5mi#5cp ze=9X&AkU=_=A9jrN17Y+uPEd62~9=0FwyA%IXek6R3^Mgw6WkAzFcERlhQ4jrkh7Z zk@Th0pd>ZNMN-N61@v9IC;PYN>Evv+9<>%7(0An?{Y!at_pV`Jp`N`dNYJDgQN!?+ zY_MvL8*id&4B#5>gM1;ii3Trz@hI}IcRJeMWh5z)0IcuoJ^YvAV6W2`_V4_?ZdXCw z-VkW6vx66)oodC>C>O~P%#*M+-luV3e-hMWZIUB(z)JhYm``)>3JEmYX2C5v(y zRjLD%XGK{1AJHM5R&#oj4@>7_ir6@mN0&t6375l<=xWPVXS0dQN~GdTiH!?^7oDk1)JdEX%S+iV)UvQk=>1Ym6OXtFd&I!@f6vI zV(aI6Ag}g_XGqg6DQ3zyP!21Ap1gSaHk$|I>^p0=19x$`wA@`h4MHQrCTXInqDl*G z8ae26^yaWMFB;c|feDJS)u$okmif%FQoe0IWkuec!FHL65xs<)SgW!rImfZM{^9}M z%+=d0>6h^ZNX?+faBR;ZDG*lIriALK_~Yg!(`T~lscXhjzMQdi*CHKvLupRN=KA$| zBX?LvQ=WNt)#SwU5*)hivnd&vmtN5rW#ox6Rg#8TqGwB$o!J51k>vU>I~0b9IQRm**Ou4 zP{OCmxR#9A`sPQ5;7O`X6g7W0OlZ@5&T*hpKgo`B>7l2*s!{=_#^Db-p6WD`b2IAW zrN*`e8p*_)-b^znbXFIN1cB2T43~=lvd4p(j5G*W1UdpaeHGbHsh@1qfxa|KE+>BX5Te&}E6@S4wVCJ6M6Q84uV_OD0ekxJ;0mgMU)Y1?OynO5yzxqz@G} zWDrR>i9GFzEkc=mWmTrisK)VaK?0FGOj+loOx3ME^|lh!_3X4sXB|nU1_I_4GU^!8 z$11xjx+W(1@<(pWEi7=}Eh}iK`-{y$<-$PCgt$;xA1VQKe%KWqwP_U@c5!p;mrfcZ zb*t^{L8mIQ11c0l<>lBS25fxV;Re0u;_ZV6uMe2|PASMk@RHe4RUJfS9SgBFaWrN; zydsVec7wg>sxNK4D{c^=as7iQK$>f|AV@|8yljTqolY##>!B&Kzg>8#3b3#>nLgcJ`bf82`c2gu3 z<*k;|S9-nBOSF?)T4Ic34J@<3isB9>$R{Os6?oY|CBw3mKBfDq@TIgS ztHKs`5CnsIMH}e1Qis-+d6WF>{#S8p`1+lo(8K;o%e6NJ9)!r6t!_!B`>A`q07pNoA zn;{N2aHK?;MaHq01`&p9w#1&f zL0M)>P2POyR9+Y0xdHGQeUR|jWf49RfRo|%)n+^ zDYlp^G=~dQ>1|#lTf!x2M`P%GXL@|+vi&ELNMnXvEF%o90vgjMsj4am)n>SxFD?1^ zlwl`wlMiv)Hqga(0N|C;&LeO$bYMC^&rs_~t0xL9%-}?e6+0Hwz8yVo9K=fO-V#ug zDWuFHflzv7ApgrA3(>x^yr|H*xJGTdnbo+O*?4XR~IyBYv;Gw7; z>grXdbj?8HcJhq{I+dePbLE1!hoZd7(mRUsxy*jRMFC=!3Pyi$0llG#(9aFMPU=7g zl}o4kKq%HoTq{cPI&MGPXq>YfJSI|8(7#Da7V9MA!$c(#M7;;1s#>_0g}aO+%*2DfOR78il@ zDl+%^fjdXwJx{=W2+YVIxfE2ylYr^Smx7)X+AP9pa_npq5y6=isFhXY`ku40E1JwA zQmi1GZ#C(tgM*t70EU@c)`m<5{%TlY;{Q+{6DL z#f$%MKK)mLg*vF{dMB}*PIqW0qc4I*50HUm69r=(l8O+W|NO6ZtE>=Jk7iw6W zhf&NIQ)_>zwaICm=p>=@=Ym^;&=heZuGu-r_*zb%Y|qYh7ZzW7(&MS25ve#nPBeF1 zcRgQen0`)uZMT5#5Nt^A0cc6;pi^K#F(Vk)tjYH?867wF1`_pEQXH+_z*3D>Qq~(8 zJ!OU;#jS>*#l4_+WgJeqD0?!8NVO6?=}7N*x`-QZC+`ATyP{P8UW5`p5TWwP7=Y`@ z-6OAmnd9(99-fMS0o9J&Yv9yQKEa~)N*(aZ*F*P897uPej-sl&8H{XF`cxnM0kv?k zS>WOG5)m*p5y@R#Owq}bh;@rm&*H4YPtSG&e=guPW`|P1+)S6aB;jGRE^>6q*F)cC zt}T^KPhn7S;VDFzcrcM%q0YzwIu@5V&|=k|RjwnjJg;FhJDnC^9D96X0KHz%(te66 zNM(pn+-VAMGZyOa*(}F_D1w8oGHiRPN@SWrkw^*XZtY}cW-vTDQn^HAxGxJZ+|GUO zcGrE4r3iyva~J9#iBe~tnL#6kF;&W~gVA4}IbTV;No#;(Gu&wsXY^o7l<^RuyR6|k zFP?69*kF)ovGizBd~uGJ?ikG1HLxL32+v3x0!k^|HV8I=IO_<>?aE@3$T3HU++a0! z170jic8wyezTUy3XShsP;T%j8Cw6p@aZ2Q?h&`=%_{_10IHLh9GcTQmS*DCtUy|c_ zamIDU>BgayiLg$VYKtvlNrtAh&0dBsGH@KuZ06WbXuKkf#WP2E{%(a9m!?MI70Dx& zZ^{m^NuR|sFeaJ;6R|2vPG>3ZLukO@RPnA!60$6IBkwo3AeTdv|wI( zz<#~rCs1e5=0hH@&}NL-Vton-;G#kiw~8oMr(;KWsN`3Q!@2*1USQ5It-(v4%Ho9? zYw<=1XXXa-jkVw=Hi$k~dY}#4+i%N)GlGcPyGS4Lh}8qA83H5Y9}{{ zXXF9_zHXKws}Jit)E2>K?uMtzk~L5W#mXW^28*{hOZii8{VWmw{0bBs2dkzF&#|6w?3vJ^_zaBguzyRdzZ&8*x$3Y08e=GP#~2f*S)0B{E4Oan4?bAdh5L6LZPb*@ zUhNwv*8UigY~r+Li7`pZ2{AsYAa{-T6;#Mow<#Qpk!t`%rC zBDG*LtTU)RsDWCY*cc&2EL?@u7#=krXZv~bS zF1l_$WmHH*V*U*STs3m0VfI}iWaX9iwo-8!6%RO8tVpcQUG3L-b z>z=1s@D`QzVN^)=S128AchT5sXQ%{vaxDwd_a`R5LQ|Cr#1sXcebyl>ua<+`ACvps(+#DXdsm7z=FWx>6N^|d z$@P|u>ohEf$g?yYt^8hhr+D!1NoabPh7c*-hb2CNl-L$p1!T%oEuS>1x^6WZgv$Am zBpJv#w7@|EHL)IQ;qq>7O*>xgj&DE>=xeNE=-GxHawqMR*b2?zjR!&{mNt|MlLs(I ze3ZynD{*m^0U>6pb~W-K)@z&(wwX-cGYc6sy9l z`ANRnRfWYAn^-!DlkVuxhZ!A<6lS5ty?^_I#|RSXdga%rDeDRv@`N=TzU6PC*KK@33!8BM3om7pN_tHBVNqSB(wX61c*4O5 zv2h7qIl{LdWdvkSwsLblF~i0SsxlP|PsyYYjnC+q8jLe#lk1FY1!H(2g(qu+JL8to zs2CGgXI_HMm_AbGBd~Ivf^fZN`L*nv_Q;xwlA&!o`+9Oqn!kz|7mUstsTE%eUiv8a1&8ZJucphEiGX?5?qZIv7lFKxLGq|)UJZ=5jB$o z=zB;pHJ+P3Jn5|}n?BUa${2!aUuRbrF_rA9u(ERyny6Hd3H=~M{1GSp)nVGQH_k|{ zk_tOD(sPowF0~~bu%$#=Kd<70_tMiYbW=~kt`u!wVVBns`;U6=b1=~OHyQQHsks&t z`=S``MX)IyO%H$u17Bc_p&q;|DRY9ed|q9UifEGJG8C&9=h?{?;CHi3=YR8F!q=M% zYyHPJd;asZ`9E>ajwViabSnQj|34P<{}H<-D_zR`-}Xy1C@oZa?c~ac%@&0n6b^92-ZIkED}C0Jmf5K))H14 z1tE2o+Ruo=IN;17kkRf`%b(ULC)ScEr#`BRITgE98}z`y=G56Mj!|7R!npMh#oF?1 zfMG(7jCqCnx~JKU`B_CY}baRSA|pc>n9_ny6in=v1a8w7?NBmyfjV zVibRY&Lb2R(X?F_5r8sGbDF7b?{;5($E{Q1Q{)N2&FAw6!)Ks|JTm0nUy?#=c_U0z z-6U&Js3w7hE_!+JU79gg-2-;yY#4%|B11Nj1MXRP86|7q3}?oUnW|LFPX&f8tXI60 z<^VitD9zFz^N|K5Di|$b#HlPe&OXYYX!jItUf==HY6@Zb+YzSK9{u9CE!2(dz%`=u zMvZL)gV`tGTjXt#A*5i?+H45i%#x^pIie8NN{H+@886Hz92WG{K@^2Lh@?ud$k9Ej z1{^2Bhoqf2I#StlJ%<&{P*pSu5Gna~Z)0i0;NTqi_mwv##DYMtL z^_1xWkxr&;XVN*C98FGcZhybOsQfs!s6{+ z;%W$So)0iOK%AggiL`798hoF1x}teOzY9FI#{A+0=tAyhuJWY`ISD+-P_vNiH2hA6 z!C)q*^+6FqI|9fBvgZtzQ*6i%N~)1pf=8MlX%H5t;`w6@F;B+)jhHJmrGpM~lFp<4 zRiLC*s5F{vMAj*&tuLF~j$meSa>SkSZR2%%VfBP+e4`%6Lh7F)+z3||T<9yvF^FvI zZKIehR~MXu-sBdbBTY#rqlGekX=0$%JczBZWH!Y>$SzCbARj?4v*N;?>-4at!3fVZ z+TQhH;GtmXFD)gpdp6Oc>|MzOgG;f*qoK}~s@O60MZ_rZmi4^Tj3B2$HsLVn$@0Atare+Ozi^RYl`VWH|_%wNsGhb6KL+}wzAyj!Ot#21LWQlsn-RC2P{^q^3keFT~N6ZSZ~Tp2AL56FXR~V z3{XP-X%S3e6d0=dgf)czX-Xk#R^>`|D#4(d!GT2)kX@B~SrI5ZL{=U?R+KY`-l%vG z?+ADlZ)(G2ZFvWTwByRDkd|m+(!-@~RR>I3hQG_HFiX z7m*-s+y*>!EvF9@2ap%15lx@MtBhjp`q#(xxkghz1Nu#;!vMdn6e8{2Q{Dw-$y&-y zEItQioh2bRhHnvsZ#8HAb(z5~M<;qjYX@$ib|)UQ1efUsV;+U_eX%V)^au^5;4dlEqb5^s6A~tkdzh&d?ty+{s2k37 zKF|;RU20lgV7tr+t`60Avm*X)3kAv>n@s<4t(|QDbuD?8VE!*HcPmrIvlLHU`F2qD zROLWpEUeof#);j&oT}{rynPYGNSXIrKQO`Gb`7o0ZEV|pi}cPjPpyAm7)i_#U@vH1 zkpw$N^8F!ni{v-|*7w_vLz|cFPJdC*>!OVNGwYyq9h^*Mo5mE?FKjbHqVKkKpj4K~ zGlmz842YxXIxHSZSsY3?8F`b_^w>j_44B%lGf%|I8d}?^nqFh;M#eiE7@gdTuw_o$ z^bDzfL`%EgKk&@!5sPlqy4GHm%5#KQ z3{IhSv^-CVtFU@Fcm<#8Tz`wZVJB~VqE2*gW*tGd1z4&Dg1d!@c2ORcg8gU{S#t3S z0JE5`xLm{~A9pX!w&jKxP4isJYVqco>}-b`Y{WWn`c*GQU~z_JFM(yl5eWZbmlg05 zBhbntY7-o_i|(+?jyZr{d5`e0kNmg;{xgaKyAPP%C&U>o>Vy<~j`EX7|5E_*L-6NU zAxVo_5ErZX*(sz&F6vu)4vupYH+GShas3vgnbGF7Idave;f#1aec{qC;L@zCC8b^2aOACE0E(xqO7XeWtO&$q!?)9)M81EACW*#S`1*q8YS z{=X7PjJnPuS^v@*vj1s1!}PxqT=9RoNrFKYPZFvolNXnj6_aaD3b%)`xIq?4EFj_T znXkh!8m(Kql)`@F^}OZPcA23ZlQQsr=p6+5ig7p6B;4sO$S|H}ad13(|2rQaXYXAB z#JOYkfWTOq4ogHX~CRmE9f@fpfYz6Hyu^FVK%V#~2NY@!49v2T0VHI!_ykiV00yVu%!l`Tiwa zi5E%QsdV>AcW)ZH<5fFAfbA5R zB1xE*%iZUpO{}KE#`3Ud>AMnYinxnBz!I+|g_~Ool;f-icL_Sd6B{M0-PNab39=hr zbqEq0USO{sY3|{8m$tW^SBYL1AWzxhco*R;)B-o#B&k3^i!WxTEH54d`t(Ei3`2W? z?6yMpzG6zaf-YIZWwgSJ3`#K$9jmWZ(;pSU1WvMm&RGNxM>L_m(}I@JtWH_+yY%n! zrxNIo+Q6vl{jU*k6(*Or|F3v^{x`PrKgwB{|F>vFanojzAAu*a$lg#YQOB%3B`G9< zT~3so+uyC6zrx7>Z)F$P4e2&{bK&z!0v|MFzz{G}Dj6>n!zCC3N`!&At7)w1jMnRA z>nk3B)1I>22rM?5%|=_WGmS_=&`^%hCebG;PSp8+A?ye|1TP;u_L94RK* zaPcg$Kb2FGiT*imJdM2{;k=|ua1CO3&@@6O9)v{Yxk$Jyr==Fp5XIeZVh9yIQA3f7 zi9K?m0=`pY5qP2fZRq6YH%xU#KxBSSEMDC_>PuhrYl3M^*PfYWZE z-Eg`2Y2VC!xg%PHY-5AZ&v~xng~tK!e3*9iNHy(gAVo+g8kp+DW?jTf4WwZka9itW zVdmuK&zUw8STSp!QjTY6^(^=H1sRjb94LLEz081Sf94NQ3uWtu3>P+zSq>-V%u3Sh z`lkj?dg&UJPr3%K*?iKBd4~>MYL!lSVw!yL7Nls#%?~iH=!rZ)t(e06MCG6K07}bS z$;vyFs=W<21`%d@1qkQL7t?XJg(*DNY{@1X%zed1{ z_y?5a|5Ko3`L94(qJ)-`%%u~dGF0&oC~pXh$(0im3Lp`dMvc=4;uE~(_U4%tp zRGqa3or{N^Ves<}5!jO46$j(M6onG<n8W)IZP+UMAf_8EQ?p6PP(EtwY6shO4H|@n zbVuvTIsgV31p-@vSeW;3Ct3M0H3FpfDp@Z`S##%mCbQRw#L0stHd0RXW6A2_Z5KVIX1 zMR&CZq*u~%GvBL8iY+M~0uW>n%^)r*b`TF@l5zl~b#;rg`EI3)XLHX=g>`dtZO?D}F59jYDKhof#O>&IkLRq< z49}^I&d+LVE=j@o11NeoMa|I(rA>`XVS9*ZXM1}}=4D&^jKa2-~?q zZ1z%b%XpVZB17Y~Z>lL9Q;}xYfePDkxVMdcW?OdVcSc)a?9TYKs@tsg*4FeiVCmW3 z53Wtm#PsTx67|jUkoOkeQSzs|Q&=YW*1_e0fDNuggp3Zy)HGYxfj(Puxajr)!#zza zJ0b4rJhIoD_>NtYsCGse6X03|c3^JYN0cuX~#58={yMBwC^cT72mm1E(&?U?v ztc}mWv@FX#Q^;=#>CVCX=2ll>c&_CEI`S&OEz3PG(=)iVS6=wcXb^rlcD{J|I5j=7bw-or0^rg@xwv#9t#k*VsEK2t zWdq*pHwy=UA_q6lm~@RIoWmk72S(8tcj=Vtq7R2!qR^H@8TH%|y)@jZHxV-jQbb%K zvwE3$tY%D#VH@V;=?KTMTWc0RS;x7L`cR>`%=vK-hSxY!DYf&WKCmbzK;uR1ggi{E zR$?Lx$FNc@`MeQmZstYO;+8{4R{yD~nL`PwDaWxD8xIK;i+b^Ra1h zNlO_Y(nIqbDD2vmWhBd|P(6Pj9U4R^h_N+X-ZTS0=)keFk8UAfz+ubuk62Kr9k$<* zI<|^m!&-+Jeu)c*yDB>pDsvP1`{QOt#uBNwBZ!>xZH9k69bd0)SX!q=)8Ak)ppejxib%|5l_6>zk&!6aK`w zmon2OuwOY=A~EavZn_2B@?>=&Kx*)Hz=#R{7-to4@9Nj;&$Bl zbR!{kYu1h&PIV8&7AlvqURVMAi?fOO2vZ_sz-*W5 z>0U|^buBp)=DV}t(Iz}J!19vfU^jDTu!^!8HP-n`z zxRtW|c0!8$tM8f!F4TR+x=5t5pcc}WB3Pd>9;HCs2!5x<#yoW!I+ovyibP~^wDJ^5 zOc@yKQCSgmdn_s{!EI@biwWl`-T53_KwQ;lG|)^O7uEDsmJ<;pd%7CbR#imNVGq^0 zDJ<&|N;r+fNsCXa;Q|sh!BZgXD!*nM4lc1lQ`eSzC>C2s!0rTO1^i6#?hsQY8;XCsQPG;<1oxiwcO+ zve{GYhVfOhK&L6Pf8l`*-xlSK`KY7r(Yya`R zzjgl5l{%-}`if}vlE@`EvJK{H0dw+*-4TeIovM|&eJt-?*mWX!S6c6#OhP2~m#lG} zfbG~KXFGoYYENhCD=TF_n?DX-D2)`US3pM|Hqxd>T<%co69Y3AyT22sUOLx(3Z`ux z1Jh=e=ur-UjrLnI0-#tpR#~r_^s{oAu=%B4bF*2ALkoQZ83)xCro3cv$lwWY)B{tL=nW%o^ z&i3*I?E0XA_UPQvrISayQ#grzq*K}z|ENc5(X2MOaerYDg%K%S+>kjWQ3kJ0&sv3g z=_W+c)7<0k9|H^yJKjSj=? zfuvePfDU3uJeS+%ZqpRIS4!3vX)f)C@Hf;Bp&pO0XgBV_|Q-RO;(QcNj$kmh1(=&Xu0} zhhaxotT7vXlE=~-1NnjN9r(sKg+gdp7BVtxJB|;<$^H2c&{b5#}0 zBkI-Y;?NTl;-(VXkU%zXLG0|&8}l18X}tnHB3#R7_JfZ$ZUTIsAY{{?5VN0DdO52* zy_>7YMjH&k`6&|>QVK=yOrejt-~`;qh9K;8murC{Z`ow15m^x-{N)qDH>Oxs9D0B( zKFFsx&B*a(((c^x-~*z`ZDxm;5^n+$zM_t;(|g(%nk}aT>6Ps2Ir4`ZdZhA~H0iQb z-9q8S96y%X5N+;J?f2sK#JT)9=fYNjA_CVgIxKUM4yh<2 zG^qFMQ`=wp;lk)ZMnqJ zIlT%Ir`pIQrB_BZD%|`P1#GZpzmMgV;>3HAXsPS@pKPD<8>vCVh1R|}By$c)ctxQA zY}z%9ZKbM7(;=)RO3Ln&+Yv@uHzG;an6~t;A%9bjISE-rEn}pG-yU7ac*T{K6%Qi(i z3z*3}qgKDl+U%@5tmi}qOy#9cFG-sdjnv(~HwG)QlkBeH)d(c?7WD^Po(Q#eeH}&o z1KmIO!3AlLT$+8Q5?kV>NrB4pDomx{{5w$35=KWJ9KwknDUu^pxFC3NEyG{rQFiwn zUni09P$0zdF(STmv&CjIoaK~A!iLLVeJx$#m(dsE%VSrC)>UH71n`pS7c=#`IxYTR zkv~L~x8W3znYkYS%-LZ_wsE5Kzi!4qYRsl~2X0ZV5z(ksC7S*9=<{|&3LgX7y7z9& zCo~ZuZKKOZ&-aBfcT}mPW5?V$G>dDHKaneh- zR1M*dG~rLx)I^!a{Y3p87un}SzSRJ5lt zdl6Q7Z*6@Sf=$Qew1^f`#>8JG-Aj+lck?XtmE2ru!id`|v5mBAdC0~AiGL~4(?pRl z`;cu5g7p0kdG_`cvbk;Lnd#pY#JObT`6_OY>&I#892^xfj0OAtQIRUFx1$qQRVFqu{`C*fJh>q)d{_v&c(N1|!_=1_TxQb8KCY(k7(1 zSK7f>*zi_!4$PJ*|m*l57X18~>s=U}OW#q&0^DMe&4^9c>{c!Ay{bB92HZ&Yf5j$X8+d_)Xd`L|}h*Yu^gK)3RT%_KGf z@!QKMOaAfo9KPb0|M~H~Tjbfdh_Bo^38F&Oy6{6*i7z+TY3Zx>iS3Drf3frlbEDU= zCAoo~FyrW&G?i_2TX=ovuxQm)v6r^N6I}6^c0z!yF0!GkAQFtHhW{J*n%*Igh7dbB zF|$Mwce)6XIdf#e-~&h337Gyn@h8?d=2R3j%cv;QUZmg_z9=wOQK!4LE%PB(EpGe5 zlEsBaIqo5Po0K>T0HXjEW*2NMnD~8r+{m2O-U3br#0A*>DMHy2(ImDt)!bD-*c1C2=SQ$^5~G+uaoY5dYU$j$<<43Z%8 z?jZaiA$Hh{#u?z}K>X)V^&uU)Fx={4b1Ctx5n3u9@j~j95&!H3_Gq@Yh{Yi1HKuz2 z^RtK*)YGI<^92~q9BEu)Q+qOF^wV`K^pSB*bGmO@SazA=XV4cL%JU*0ZrWpU^Wwo5 z7*rL`SVc@F%{_8E7e)7C6#yvGPLqz9`K0vqox&uhMm#!YoID#jj^@661XD-8>O`xW zbl?Z@qt2VQ)DRE%z1T%3XJ+3%DOEDsLN@hs+lcH<{kEITTw34b2=#t^*QuY)ZhQ)HTXa`wt88`;TESi%=?lj%( zHOXLu?6we3mR@LyBaT}JI{+G4bhc$Yce4dKsogN{tve9!t11Z@%c#p5R!Z2`LZQiozFV9%(b8OIgH|PeOLc`{@50E-E zwE}Nf4?lG{@okFW>SJ#ZT^CgQ$GZ%v$Hqq69Q}DI+W@%VTj4vzNFX@zL@XcP2-`-Y59NoVFt*t zxqnq)M#}KY=93ML>kEl-B)4qYQ?QN!8?N>Z-VMU`4Gy&ToDL>OuMCFUBM+L|0z-;2 zmI()QEIy*}nn~JEN6aCkbTIr6#l&r#vr=feWKNe;c{in5l3S`UU${Nb8$-=J&2zd5 zTUGKg^G4P>-T+`n(@NF1hRoBe8Du6^oqg^@7 z6c#$RUFP41X+T>fIveCWQMV}nSoGTiIkfh->;(R`z^A%#|KTm_cf8phWO?o}u9Q~t zdjY)ii2LY25Lwi(D6pLqRNFD&jA8#}mhnLbyqE9r!wo$4flhG?x+xmXZzr?65dT12 z@fES}Jyh&-!dcy2oQO%`r{c9h7SgA1(Q_9=*^2_X(j1~^z}e{W zt3f0h5|ewZOq%XJBi!2ZctA`~hL?Ad#r#$-@yY&1ix%>2LL&r4A(*Bsf$~&vcP!B7VLYx!JeEx0_Nrg{-vj_bY7-08MIg_} zBzz-yw2|<8Qs_(j7|d+Fct?E+zlcOSSLgyoa1QIXn8qIS`4hQ-4}21~OuhXaeA1%# zm}p-|CWaj8kXmCQlq|rZ@_jL^HF(876HUFw;UXBlZqhXk1%a&o6bwDKqEfHiykE(P zCJ%p=LIe2)A&sb_rN0hHV(f?8XEZI*VEf50NG}3r>$?KW?b4%WmV!~!A!MKqtt1Ty zmy5!XsWnwGGQ{P$!>-Ub+UN=k-1>$3^y}ws%PI%BJAT*?j>#|&yB#)7?Cbvq z8Rz%@M!(fe2EbM;*w5vRXs3^BJ1YbcFDgn<>~JE(_gp%JDAj~S2A!Okl^ z(wYrneVU7|Xvyezx6mf&sG@UpKPShW+T*qLm%Aj)jDT(?(EsB}jN12c&BwxpE7%131l(>^s_WpmQXr0!AZoE*E4P zR6EoCdV>icxA8z>NHZ$c{^OgiHXTjA{2 z$hPY1;QD|pXa&@D0j1tcJ8?ae;I;yc9PqY3LU0-Dr<|@LHs-~J%IZFaULx_pc=clMQa=aH2zaP=kkaApkh$iwSUq5 zNQ8%3#5j(&1+h?eEM;^bFDh!nP=NcXakn?2DIk$qwef!(jMnmIRLYeH7$H%6DOia zl2821t~S3NdmYS1qCPaUdIFQGb;<6jy+0GRRC5)OA8qyUeGL6&c~HaVvS72`jVtqA z9?J>ooxbC+DVJ|2-qSRzXF*)ja`F12hL?WVItu=-ZLm%7_T1W2SGuunJvQ)|(n3g% ziW!tO*P-u?fcO=D4&~lCg8;XP(mw4ZJQT49*Pnm~R)|v|`hWuks+Q2n8*k^6abT6o zN$|^W2dP%wb(Ig@rDGLY8Rki4#tDyzV#io~&BUs}IyS|v zY(}}nxG$hS){vu#o2B&Kck@tlyc7<=j}GEG zv4G=ozRkr|!L=I4RL6%1I!_clyimNj#xi#D8zwBeEn&4Mw9Pwf(JNfQ4_%phS8U#I zD2k(1^HhCvDu={BQ*=ev$GOK;z>wiPP!4jLSmOB?)#tZd`~vv$-Zye#DPU>_8U$!* zyXunNB!0NvDI6f>Gsi~60^Wg#LUFBkFT8MB`(AIb+;=W%l;1pq`&pD03F;OJJ+MeW z<%itd^tD-em&)serREL*%M&;n1kM`a?^shpX||(ne-1SndZbS@6m-iE>b1wu zT@+;u-{6a-IB5ECSEieBJYkRpAu5c3Sxw-vnbzJD%d{-ivg|JyLkT(l2B4}6_4`ZJ zAw#^7^xqJz@y&$=X>}+r*-bqNpiM(yMIxP%OBXRJHH(%5JzuGxo#p}Ypm!5waALvC z9|8(^V%9H_4~O z$)+eIQWtJBrYlJYslhx}$qgLN<5)HgVF{S6XucxJTSGDXS;pix=umNpdmKnpp0e{O z>t-E07&|Yv#wH!%o`#k$m^x~`&IbjF<;d`2mT{6E^OqMMVDK<8-CrqPREc#lBw38> z#}FA;wE&=yY4{mUw(+guybm&d3%e*ZO)J{||L(}j=A>A=%I6&7;Iku=D`Kvr0 zpH6VplLctt9btrn_BYhyLVx@p@%KUao_qwYc~j|~&{a;CFs)iF`26vIQTC3(nTB7N zZ`iTfv2Ckk=ZS6Gwv#8e-LY-k=-9SxbWYEicdE|+ty5DoU+=H?y0EXk_WD8OKjeXA zmQ74&&CUeLL$#5MH9Zg6TLf7%7^(>XueiE~b(3>a4aO)MCaZmKyY%kpUTXtbk?)mw zh&NbJ8<<&%8H>?S!HDq{FS1 z3{;C2-gg=yszC-+VF4AzM|$zidjDL$WPKSHe)#{V>BAE&q3HIX>Eq|WK@Yb7i>CPh zcf>M9#aezr0o!i|`(habNXrT88ZgEYFE<2-br)nI`9o9?l|O@}L$RS*c0=}r@V=6a zCz|Yji_p|ZUb{6vWGrprr7P{kbNeMbH?Ozn8zg?PBAmd)NRo(lo`u{9$Gx4MR1gJ4 zNN(uY6l@#eaCSI03*SLtKp08Ktz@4u=mY$ndy82{>~*GFjvZ6vf zrC3U)vJ1UwTCKM14T*?}6sL=O#-8i@`OzC`a|w;<5*77EO*L-u@DziH$1vY4Hmc{= zEJsC(@AS6f%jBWd@pO>ZwyJH;4Y>L0uSI;|rhg-^*%E^VnXZjJzs{m>q(7NrbnDn` z!tpt_>C>BLM|qWPjUSaoYGu|B2{!ua-z>7#Oz=gl)og4UA z1~_T#OUqJIgR2U(A*6QR+v zT_>n|27!hRp7Z^EN5woRiqcUG1fp0sO88R&o#Ef;EDaT$6%A_3)7bQ*Sm@Rp?nY4&d};E7u7>zEpdefs<-sYaC0CA zb}B&Ei$7i9_jz_TMIa{mtg%T|ewN61um&(Hx`p=)u3chK$|RN1p!JJ+m%P0S&m1dh>s$dq$Leq z9$CP;1^teMlpyuc91{AV-^OFa765@z7BY;R+U}=B=c^|mwnBhV`7uQsH{XfJ%~`8> zAB}S9;jH(0bsY3Yc6fYfvPn$*h-o;Vl=c_lKUWZ{J&VpTA_$1pzd0$!|KAnlY;WUc z>cl8yn00sGWnqd3iCz9 zfn>iDF}+yFXDBwVuZvh4ErTsEP>>W<>_j2Z;h?qR86fF)g$8}g%60=I!y|(tBgc-s zov%#XIJOG>O-^{XUp}_KdeTO>J8wWi(!->omj|7NPJ{9wc1u6Metz@)5nv42J-LlS z{zUZ~F2oYKwSJ8u^urCJ@n8U9ynAscCh^IT=tb(My@e9^oI~=zAFT9ybq4v18nBYS z`vmgI4&r~Xx07)h1M(S6`F*(YjSPzafHZIo z`HH?DJ#07w;@Q&>&R|@e0rfQ5VU(|qJ%sX)2U31IyQ87d{a4^dG(WM}Ve(sS!?=h> zl#EI^TXa&D6Vo+=6zYGGmRNFLu3jxBo0Oz+NZ8+;6+&iKp|Hy;u|OMN6}u^3oFyeA zeznSzl`Tp>e=smfU}YehCA!lNooKcnCMwh964=oLhxE3_aK{uXJj5gCys z&M|D(zsw)MgQR*ks~W^XSuFb`1}}E9WJy|-6QQcLUlqLMoOINxwv;g|inZy`R_YkK zPOiahmjKuzr;z=b7Ry^sQ$fLjV^Akkl|zt}t}53iFY#`2JqD{+SfjP9t}29iLJ(_G zDbFMuUG!FBDn07R{em!qW=WmpqdQTj4|048{pc72ZiV)k=xC8voZD$ekWM`oJa-VG zr*W>-fPLvtn^`(Q_%wzwb4 z&8hx*uSmX8D@7*NO!71t*`fp}X@E_@*B&!YDj-KQAs4AHC?Hz!B5Vgs?$*dy}|)7cq7LYRGStcumA$W#?&CVmz~ zE}=OnemkSqj#{jv8EW8Uj-6@H|STq|Wqpwz5Ptg{7;17)EZ9$hRl9t9`zTyi=i$WLRIQMMfln)EETa0ObCO*3)m(s z5|FRejz@-h!b*-^%pXE8Naw?oqjTGC^*WIC5{&m;ME>jXJCuW5|_B7e0;gJ5RB}3xKz?Rptc=l=n zE(IZYxq9{34U&|mV|GcKd^WeonCpVXp3r?<5k0g(8O6w|*8i)k$$|9TV2m*cK{ zl*|U4y`A_)&K#N03Nk*z)S;9ysLFU-csDo5ou@oM!qp+PK-b~VU>LC4+#QUA<$`&C zwMhoV_343P9iR#@VC)K?k}h@RaZENwKs55QlS-hDEYKRML`t%3uVN-A#6>I zf(T|HWsHTsg^&u8r3*CPX@b2GnE05iUyGxE9AHf4gd7W?+lAGk?vwQZ5~{a!~bfC8|mVg-66Pk=v&)t4N?4Ly=o+GshN9r2 zd_|z2QFPb&N!s3#L1Bw24&AQ|HAfe zG>d99ok^>UoY)H*WEaDaS~yVZcSrqztD&e+*aJbzTK5B`f1rAj0B>@ zWEG^kn-Z8|Y#VT=PeI64F}%r-C6qc$Q^YYG%XwuqnfqMH#j1H7SuT4)-br36Ysj_o zN$JJ;vW6X-Tv@(9uRjRALuHFO;YQO$EnFZl;g;7mC7u|5Db=!_lp$i{XYTydcp65?A*_U+A;NYe zdR?Zig4*CNfj%Rk_TW4Bh&q#q=5BX+sWsQrU0Cibc9L0gj6u+D_1Z5-P@SmsmF?`7 zI%}9hCMso%U1?vurSD2@BrZE9o%u6EU+d$PYY?H;Ocn)|bZBUfByM%%E~`W48QIW% zym}34(PHl9d$TYJ$WFsD@z^FeOp5SHszkW-oJjK5n}eyth$=NpfVu2Ao-qdKLO zO@C!iAG`$ZK+ZU&8jqS{AMx?Kp_n3}e$(MF2!QnPKB4iRx})ELFyZ^m3hGP&bJ)uD)d=oY>(HO<`w=2W95imY%mXWTKl% zXUryUxBqbLV`C>AMWX$Y;sstARz}$cAVWrC8udIt1je-m^?Wz!mRk2z ze$X87Y4+ZbjByl3borbwgim3Fyvl^(P=77L*8#y_8TG~8wup}dp>gqpZ-~17ANj;ow0;3pxD+kFk4VGxORy*YYaY%=Xv@KcEJ|WQ9tzMU!)u9Pvl% zI=r5>4ChWVgJ8I_6S5lBbd$O3?L4N$dm~BfT{<3-C zI&$0ve$WhN)JTJ#Y}Q=xwtG}aPO~2L*#t`|zvayd1H6L$8cqASZ3KN6n07bI@@ugZ zu7i{CSRX=;m>z7BZi3H0_CjLz-d_45kXU^5=0g=^dpQ+)Iueq-(E#L6Q=~BR6hBwu zRkEaNY{`^S?Fy;davG-aO^&`0dG+l!-Z)-?>g^To=D0M)@w7@ccBQ3YAFKG=#kKu0 zu8f9T>JS%MW@jI%SH1LR0il}tA|`JR$xNP!EB_jpVUnas@&An7k~l5oTS)Gi;Wz1O zJ-LE%I6<`VwB{BqyAIn8a87l%AZya4Yo?mdCW8%do2kD-C13h8VlyTiqVQ64uGh6~ zN`a@kbwgcjj9W&DNV`yETZ3#o@COFaW__fy&~b@w1i?$UTuX73)bDvDaC{UkHRRtz8gMzo3govzd)ucwj_<{e?gaah&&9FVDLh{ zoGL(#GsBlH$WjS~P4rtr8D`*Kkwaw~6vCJh7>-2d=UfLqPoT_Q(~_7a;hry%7;Pi% zFy|w3=S~CICk`v`^fdH-*mbSodlcGqDIT67Wm=m$sXvLQSL`r(adVF>`C&7UTV}oXc6U?jmC&uo<-?1k6dMA@5A>)q(F#8U3a- zIJB+?IN2!0d8*tNSLv(}7;Smr#?T`(?N~FS4F{T%1Uq#|X4r5d3hhYe=_5jdmTx#^ z>5V(EiyV>E(t}sxQ---u2UM{j+Y}gGB8Kj?e`@UxZ6pMbA%_`lNP8#}z_H`ysNyl9<3I9W#T6-I9i3RCw}=hsNms zN{+tX{dds$zCm9w=fAivObQSX&i~Vj*wx9{^gk=(X$=?;?WGj{(bPw>w_&$r$V;-_ z5VF-oEJo;r8 zz^rd@svIw?X$gD|%STW0+aF(f`3B65v&V~-!-uEtmmKdI|7Gu*ypJO^dDJ;mpVldziE5&cqokF%^t zdQHDhV2{X7b^guVi>ZfRA(qJp6w9YVnV!o+Tvt=_UqB(DcX>jt(}MirOWx$M{@87r z-Fx|E*I`NT{Aumc>>tswNtVwT_}Z~s=l;7^l4~qGFIB|P9OyT1#xL-%!l}RGGT(r2 zC6RCGZ;Hq7>yq#ItM6pz@1x@Hk~Fq=LPp#CQj-sV>(jJH95Vn*-H58*`plAD$JTT# zj$6azbY|9;-7|EcIuIw^U~4++(7QV8!laQP-J?Fuw`*up#`EXpd8` zzIk>&p4pY9UtUGlE-oGhE8BD1C?y^J#v_h}q)D+OJV7IiY7}3RkFSre;yn0LBg%j$ zNQmG$6&&=aIP7s3mnrDt2a~8+fE_eBMQOClqXpf-P*}RoM!}th7nHKA^CUloggXfy zO2nLp2^Fg+TOuAidbK?h3X9Q4w28{{atY}#6v&;JVB_&vF8qKfGX0TQshRX zq~ozQh2<`&M8Nt4DIm$by_-N@z0kcgUvn+es?O6msY=2LZk8KN0Dl~Df z+=ZmQIb_0U-MA>Gnm(mo!(0=7`W4H{s>@)L4{o!q2fl#8^3 zAg-h!;#Cm4$<-)?VN!Vl_CuyR{-dY4Z#o`>Ti$f5J>0;mif&Mam4&w~nXTl9P}V^k zCq_)%N$^Fz(kA&kX4n~C=1h5dIMTC@Ihk^J(RZF=6SXpUgu^hE+0ZDj_`DPqWlQ)z z>B2l1G59L;R6toyb}_MX%&=^e@jV&kpfW6(@-81+&?;HajCYx23LLFx7X(dKFBT)WfGdwe0}IVIx9O(ou@?mX-&AUtxiePyTU65)2X+mov$--Do-7Ewf|R2 zZ%1^UK|Q#art=#q|E%kD&+BgLout?A+n&dNgJ|37GJ;F0PUg!ckuwaI4E!`s)@ECy zGD=4pOKICYCAQ!4f*T4@2wT=7VnQNK0IX}wLs(JywUv|sYb zn%U?NaKDxF=;aD=_2S$rT=+QE%c(tP*pxF9vRv`Rawk=fLb{xYjv2q&=d&3q&2qWk z)64m2(?7BH01_q<hhH@`$P=fK zdUozn0Arq2HD$BjQwYP`ke)5gS&SyDgpxUBT~BSpDZe`61&`LxRq>$bC3)b>b8`aD zLwG2HL%96r)gyF(>&idCd1k}J^BOa-IlvhQ$O4=ohq=byrjLYQ4SSyG85dEAlQ>*` zxhNgLndI)5jEkSaUqRDFc&B$Ee*(AB9f5yaJ_`v1OdT5~dOtQq;Y8@SQ5~XYJG| zr~e)}I@xM1)UNR`OG}6Z-iKIY&8r@)1vg}UC(2uuhrmgHVK}=Sj1d{uzOSu`?VMX! zA0%iiFh00Co_?;c!qUqMaaM!(In?03PxCoNW{$(r=Cj^(89k+E9yfwq^M3rUQd4_O zzMn-sGE%jHrJK_qpEtGss{^|{)6?yMD_RW)Pwt$$0>{9if5uQ?Iv|Nq-sLv5R9oDB zP;q+A?L}9RO>=(I`FBn9d80o|nv`7mqwp*O79pyuH-`F-U)h>FD3QK#H@KY^Ga?So zcyqMuF;_*L1rwdb>Ng#MI}fu_!lLBrXdokjuo>QKiXIf4w49Vcqk8IE8BI3Bl-F<@ zzjGp6$Gm|jTaudZF)}xq@;%9kvBAh6W=;L@aui9R}TF zvCz^duSm#64~8Z^2@!l(J7eJbfdA`tELzq!K(H z+k8F@=n3QCL7UV9bC#QRMrQ#Z`2c6;dB#XE8IIO2+)aG>@^+C%P_tlI>{bko!IlzJ%y0 zP^5;+J$}(KK5A3v8jeGG*U5vWAQSYLl@wg;uaPb)Cn*f=g{d z5f&vO7^m2HxJr84^!z2{3AdK@(~c;06mLYT3Q>{WOjPzS>(F0k71vvMRROu!&&9LR zT`vvCaAO@gx#+9-MPb*&ur3f?0Df{`jop0#wO98*Vo@^r34M{Ftc#`rkc}2GZAb*;w3Uoz}}K`1)t8k$a<=vPW->_PHkRAjO&sBP6)z9{r%N~Y$M z6}cD+4_x5ntOdP-O7hEt?TR<(MBNi*a%{j0)*HgJL3`imWn48Y?CHTv(WY9#W;puR z6hTU-feYfT3%Kan938>iWxG|ad%O5H{hpW(d;r>E+7Svu0zXE{V(RZMpdr znhb_snW=6aUx7c|wSx=$Gm1@fYLsicXLl!ztsxi-bmM1ZJdqBc1`K?gLfkl?91UG#dQo;q=^%!6 zO{aY9h}<+cW%appucS9Rfv6F{Gi~Cl{MFOLGa&6_m5#C?q|g6?UI&NuOd1~+Un`@F zu>QFiR1K@NBk_`{^rmNV@?)to-YxKEfQ~)8DAjo}yiadWJEK^&{VS@$g*ml{0$x+g zHlygSrlm&%Ao*fUVav;{-p04X)cWZ zrD{ML?1^BUeNxFff9*$!xkaczeB;`PaF#7B#5DH(QR9MhY7KNIz+fz&V=`LSwgm$p z0nt>9^8N>Pd17Tg1g|B`yiW95559J2rBilbAYt+vGY8^VQ#uS$s56j&x?j@0l3_IIL0_( zD5}}t&0>HAM3zmUYz>~3vZnJAysO%rAGXPbR0ZctONO^?X%y5xGM&F0+F0bt_(rO=JO90d)DAH?9Mt&g8#9%K6()T*pYv&2@n>m^g>hq)C40c*MqQ@w ze8qm1sA}b!FHHmXZ-NGh#{ls%7ixfHozReyUaGq9hsfs7JoWq3tfm$|T`}H+@0*mP z)2hBZ6bBy{g4nzQWz10oE7?QLXmjdx&R)wX8zI*H7OwhF-TEm{^Na`iWbT{aJEea# zPTVzc+CM>?q=!3vQ20F>1hLYpqu?xA5eX3Abv*TEjP&G#SJG&1-@%8Y_G12McfHf= zxlXui;?US%nk%g4(i>=*vsMpw-_{wuOKO(POaOXeOZ2nC&I;RGl0wBvZi6j&Uk=Yd zUCSPnHX0v!lHVKIE^+&bhK+#Y89z{Xy^CvVM@{l7F8Vj;zPQ${^!{)KxsAE^@pXKB z#vQY7ME?yw&AMG_wZQPj9sk7d2Lyq+NVxpm$9;F;jkK;rBmTyNnPUoDx(&|~E!QuvV)lK8v{DKEc~+_2e5 z?ZuAgqLk}FDYP!L|B8|L9U`aE10TFup?UBF>SCkOrR-cNWWdr{GtTdjsbuBgx*6wjOo-hTWuXYX{UB7witjy?t=wVv$d9hjXs{r+_bsGDDJjJ zuPl-}tV&e$wOOU8^)(%;PLJ&quCckOjV{^KFjeP#$?BlTuk2v7^({VaYf*H1kTYF! zIGhpjH&!(8QGYJKNHy+A-9m56$b{K-eRdr!hfv_%7*fSQ+fJMAq>$jso#gVHFp~ef)$IW?^QF=y^$+ys;`$flq*3Llk!3$;8-)@bI7xj z36Y3x`uUw?dh`1F%r*zt(^~sVpmGc3tTWnjI)x?0us0Y^HEkqm-rF+X(vCoo4n6PM zs+yEFj@uWIT0$68pVmg`B-;>^LF{aX_qIwGR~q~YuzV$uhp_v+*_d}g$%D1f6D%oy zxQp&B+G9m$<1=NBqJ{OFy(P_s0l<&+tW%{GSMPCSvUl~#OmK>XnRO*zTQF$|#1#C< zsduJ3*3>a|L|B15{_Fe#JB9dkX1dbIFRebiv(Ngyx$kd%a^MH`add}MwUBdl!Gkhu z?lR|coJofpL-Ru0`X^H=Kic)Wcd+ny?aD=Yv24XOhUZ#(wvoHYY9$w%dBw^af&noE z_wkeDygG*10qAxk31 zpEoOQt$o19;NiBY%5Rw~z8zJp4ec*@D4T}%^my|AY24HM`?&M)qjrIt7-y6!k@Nu7@azfeXiw2ldluNi#H5N)4DB}Dw**MA^BIwNW_(rf>Qt4Loa5H z3GFdX+%is-{1~0}zKeUyNHnRm$!xQF=M3=^D#?`^gB~oplMjR;Rit(-Mjn+^k(Vv2!*!+}XzU zMX@0@jWC>pH)M-?-QT-=9JW6K!=>KPw~T1Y#;@=+wpNkkGNeiPX6cRSpPqrD*fhzahU(SUjHK(isgU%F6UrqY+)+t;^LsH z1OQn6!-)NtStUj3eOY79sXYzcG)$Aur+5G0$A`?5Br}KK`3MvlIS(@HFR7-D%{kKZn=O!vR(o)~wWc3?ISey+)a@TiIlfBsNc}*RUTd zq_MyZ4u66Z*GjT?u0S$87VdRGTszvW!_HblJ@iZGG-r|V7`c$h(hGXPy!4S8GSebU z&}nR82Mgn?Z;W~;2=^i}X1J{p>IVe{sl+cJkL=hozG(VtIp{JUf)+&TpDO3K_~YXzGqJ_baR^oTr@; zT5g>&O)$SxU@6ZkSO=QQ>r&90-*Nv_Wl!h02#x<#*8R^>$nd{Y*}r4P()fQJGyf|z zxca}Ci*okb6Eqq^fn#FylC8;*!?;99O0oc0940b;yH;>I>dxuw`C0${PJa-z1W{Cd zSsxCo=)V{T8Mgg0pz8Y+ysYNOy#GS>rZPOgzoxZ8(ArjjZWayW<7RY_7@m*^)I<5D z*i7ZSUa(S|3QWbjB|+M-c4(;Vg^AQ@Fr>q(>N`y5z>})?4%NyFNJR`c%~i8*BEE&@ zik^cR8hO4I&9rAFBVgD3G#agPU!LKB`IkQk0 zlLq|eZ?N5)QHTG7##b1coRe{AaiBW*;iqQBhE+aNigdHhu~QukU$< z;Yosn5zHU?ws3lkXMt;@*L}Ji4p2kt23qX>Qq?1CzaNT4rh9j7X!kOcu%E;G6MRi1 zpY8`>8(5xfqi)e34D_vV^CNC3bN8L$R^H*=@Uy=*DTsEGkWP>4O-%USXOZ5<;0@~9 zSK$1%j`TdQFf0h~%-idKk*$W`68a*TGJhjFuCGZXrrmp6Y-kqc2+o4A75!@o&2mb9 zq+>p!bU(s;J^l=Sgv9X`i|v6FE=jLR1IHgQl@pBZuGyuD(-2h7#xrHYgPt*lSiwf? zw?J0IOlyW-I%YxRJA# zlVSc3Px*ECvEdF9r9m*r)!>!RZnzg4$PNDR!--;kEQ{*5g%O0iY*C#-A4i?VEl$bB zW&*|%mx+IWYa*9&5iSiX@OR2*{F+JHDKe>S4OryzsXMTQaBNl`U%RtOMYl@D%_D1r z;icuWSwYI)nw%56S}QU?o75kuh%pJ@C?do{mSSOz>Q(o1s(I`*CE9|=u?y1HZV!(I zbH-?306i5O_B)>5)MLGa45#Y|2xY2`Vf#~Z$2k2=e?=s?p>Xa7*TZ0sn85O=o*-AD z7eSjAIDYWZTYeSpH5QM1>gxftI;&==Bf&gzja%z> zZ;FuYh}}DzcqELlJv!f^rAaRDjiaYILcSxkM_M~#OL_AE3<=9)gdGV< zHD^<~8Tt%cu#9(LUkrS@!0xLq7n_EO=w~pOGumg+PTH4^kredQ4Bg)g$Rl@6ilqNTz`PZFrG<4lshzAikM^ z_7t_UqM+!DAle(jS9p=53GadNHXL8*;P8(T?hZy5)uG(PQJw<7w271+0WSJudGx?2 zGVcu=i1~v|*eWMmSmG;Ud&kyt(_I`wF+}CVl5c@q%`^^QSi=0c}I$`|~ zy-ssCG&1k}rp*JrxJ~plHuuVoLNMT6BZNr)R?b!CnZhqC8u_loak9VXy9F@Kjxb`l zSj=X|U>6)E4wL^p&>L;RKXLzY3muUfIgX>L3x#<(PeZ5*$#Me1KCZJy@^9Ie_*Uh} zA2x^Cx(zvO$EoPhWiwp}!rstjkGHgQd(hedFSIUNrKiMRvD^=o1~UUNbSJbx{-ntP z)do%2kmg8h7Y+~DVb{$7&9SVurGC2Eg-fGkU4zBze{*Rc6jxFgvx0!Ed4Yh?{U6^-{^zFL?F(a| zvb1!|{n9hu1<(^7`!PsDN)$o|p&$sAZzCi)fY}ldlw<-1o&-qGsH2XI)YjEXQ4_MQ zR-5ZU#{vs4P=UPI?pQ3&b1iqhveMP6{yf=yIi5~TL;n2meLm>^xOTc;yVkt!PP#d> zC;Z2(CT+4Mut8OBV5TbR5Nn1idSjlZmwOOQePhlcWPN2$A}oC{PSsxYAX>R(+8{j+ zZ`a8@$shI6U38iTi_@UOyfbDNNOjQ07f3x0H{FMi<5H$u8HPpjA(`2i2q1j2o7)A= zOD~8L_k;2jOkz;GAEk+dj#&D4i-?7eGPARu6B{Dc8rF&ncN)cZk9HpAu+vK;U5-NF z+Y|r0ITY9EJj89}9LuGiJz7lP!KIIdbr=rk`KhL>GnB({JWBrAmQ0v-w*T?jvq@Tm ztj^L^$ycZI8F1k@hOK*rxpKO%g*1h{;c`a`{A=u|Gy1D$W!Mdg0ev##6ko?TSbOs{ z5OSZw?k`N?opM~8=4Z6`)n3fiD?Xz*iA#)+wl`v=p&>tAzDvwFhr57_@TWWmf+ONM z$CbBFuCd3j2~q+qd51G8@x6Ek#EX4u;G=b%M<(}6v;-e*?j*{eD6I5ItY7<_`>l3& zi41zreZ~72x?K~4{-bd#oBOUvI^^54!&%WQH?DUA9Ud}R{!+9=upez1ktKDT$aV~evSORz9^22$qcUZdr(4LI0cbvIzH=nOz4Ezhj0-lQ} zpI@Qc3LoknuW3-%DBo^TwXSzDP}gYR#|+t48QC$4gyC_bG4su`;u7liio_=8wArrJLu+3>ltKR)}lfeiYB)^9?u() zVC0^cOa*kG%@sybn4JP7-Vg6O@X98II`A%2DNmik8N$4FWi>Ow{SybV3t3v}Uix?& zf~;v=x%nj2#!>9J6L$*R?uYO^6Y-|wnC-aL(kL(P(d`~j#vJb#@wjtwN1YEKbp7Ph z&|JC4=_$Q;;h2Z%OFedJxl{N}nziK~`d04QMjSdA%uOaU?p^G1hxy9(=573@47-l+ zrO8^R7mj>%m%R?b+T$;<+K=|}+C`V=MA$r;Bp6IRCSM(a41X4noOEj(CL8%Q$iVG1 z^T5B6JI{!5+ZKn4#r+^$%lXy3>O^bymBQQGw9>4xbC?7&$C<`48N^)HDkhsvP)t

>SzJ`q)wpxtz_hjCvM1?uRxC@Q+obS~a2#{1A!k9nC;TWCdxx0w3y@#u6riI(@c) zb&swHnpqBx70fUt(b&9U6mk=F!U)j;p%u)GoplY8I2OeDV5E8iP|!n>2xs5EQYoqy z76qpmF=>Qk&$ZuT=}?evk!k0>;Ot)g$3fIWv4RTEloaAyJ>st@8D2M&B4^gaOsq)N z((!l;QtD@-@UthaGbIB1BAG4;Dh_g8HHKklw9@Dj9TF<$)X=5PgrDQb<^38WY>U!W zge&=J!({WTeQkz0%^b_3I2!}~Z~dStw^t$ONa6l=ALpLbC)TcWmc?M3u_cL^yEbC>1>LtlAX-*u?Dg$_mRegC~Mj zLk%v*@P3qWB!efRHQoJ-~hd5Uw(cf5 zQE|~vD->hM9l`rZd@)#b6s-91Q-gCg*A}@>tINeSs_x<4&o zhQZVf6jgbu3We9jDVv>LWps*FSWwA>bkG^^l2b;xc)}c+e##YMxuGz);B8@)P>c=H zX+=#W)5M~*deE?jxp}wflu#RxibcQYC6*|)pH0M;rrmtE^RbJ(L)CNgcQc$92C2!)gTBuA= zE+<9lSb~zA$x7d*9(*d9?-1jt0FkpM9y>H}n9;72i(pSnIYO#sS>>yZa;Uq4nx<>^ z;J5k^+UEM$C2i;dk!DJ4IICmKDMELco)x*{C1-)FG%U0~#N!F9nXL@q2Y-yb&5d;a z!WeBBG~eaXxk+usb)vLmW(ui9@C@rhGenNT%bg9~i!s|~(qZ=SFmj)a?~QkFKiUFz zNo-q>>F{70!0xlZs#XqV?V8T-07ylF(kR@%Msiu8=6)J}3DzrXv+ zR?SK+iqP|8?7#UonfVk)bi<+LagHa!KYW~T?Dr`6{L4PBh9nvsEVs0VdCv`+4B3T_uoVPW) zlw_Wu-(fiGqIV41w)5kL(d-1f%E4n;xZ5|St7UFe28D0^F7TeIG?luzZ z4FCwe>(H~wkaWo9X#ACmW<7+u7ZJ%0_opZoZHP-STLtWHF^Kq)32+=z8lemSb94Dx zmEf};mfrvQ!5>+~TtsO1rcQBd5B%)>3?mju`er*kxrf_N`JC@txpjp#>1h8N<@p;< z+-nrwQldejPdY61RAqfJ-W4xM6=Puu{Z1k~6o{!$ISWK0ytYc){mfq!FETlSya0)A@wiIhaR4@4xOjcb^jGm?6{Q8<1G z+-p<3gy#nWp}{?hGv2U_b6QrHp^Od?WXHBlHp&cbwW)Ayif|&Z+SsROb+l561%Kza zv*&Q7fmX0*0P5g_Vd9&>=JCK(tFAkR9akK=gd-L&2&+Kdi^52>c(DcZBIe+dIxiD~u z22c5T<5K`a_A`eOSg_Uw$q0GajBScsjh)EU%Mvzy<2hDmc5~n zY8oze$305VhN;xpBmaPn=NK%$y4tid6FM|NwS3d|W@)G1b%&7t{8ZOKhq45W4(g@` zdMhhlXDUNcUl9~>)YoO`a-IhP;=kA;{|{m36r5QQuIpqb$;7s8+nLz5ZTpXH+qUgw zV%xTze`4=BwfC+%`&^uTw=TL?tyR_4_4U{NJnu1r7c;gRfmLz(u6QRU2WuEyjTDZd z1&Lmv6r4{>ESkVOYfAaKyVZ~X#JgC1ppHdn6f9a zID82F`-F(QHLDQz!qjDE3MF_0m&z7`E3RbU0k~Q7;RU=GlwmVwBfA5!ZVOkiS9iqEk~1 zT%3D=FLv1}JX?#^=bJ%HQUtpjqFDsk~q$qkiAN_(Xhe0E?5>g{Q^nNj@*r zxY&ETaJgs7elXpbt;4f-SFoH(hWoH|mi%C8rur+2#_d=ZI}(+tgtHJPw_FKli#=Su zVHwJvv!9&qKuH_kHmp=2AyC(|Wm5EZlhZwt@3yPl>q53 z-uSU{9fED@`L!(b|s$)%z zU^PqgBkt>Nk*z{MC=Z1#iFjOAxP#Jp6WlefEsIdxmFXh+bh;|v^5}PtBx&?ixN;Ur zGULXV1lO(siam62c`k2nU2>!3wa!jzG#pFweKQ1ji`#xO)pASABKnMy0=Vm9t3%d9 zgDSokD!eKMhY9!HskblyTr>s))2RMqWR8BRwUbTjAKnHvFVT{Ts^jXnnkJ|p7;l=1 z{nu-IUH@1x4SU0sHi&3@)9jdNmjX+nobV$V@8B6+`*T0kt-}qRE^F#2rMh%?DqLbT z*%KHO0C29-?n;EPRtHk0puN_w=Q($#+^YeN&Jt`PGI5R5=R#e*@}?4e@Z1fmO_Imn zKm~jyAn#M9C)9}5FgKPr*h1at?j@}iL5=ff>gp4Ewk5uomsr{VDNVL;N#whc)m?}8 zS*>@_Vv;V5f#n+~(hqbloGr|C_7zbEizE&09_!Rml`7hG3$a--CyE%ihvas#NS$(R z?b%NUo^I`g;!p$J{NCw{A_)hIeWbTbSdV6kIok0o^tu;Yvx}%PtgF;4k&Ing+V^tq zVYv2pE*hM2pW#uK&*Oo9H}o_2rTnJF}z*!sFnsXN_kx!?m}q6K^Zlb{E=09iY#D*_Tr+p1_CX02 zoHVUB;msOpy+S#9xe8?>+j|brw<<32)y}g+vNK0gSKd7(HJ5TL+SH_f_|3(rBfPAj zXn2MUW0#igceC&S4|*q#ou+^OrsQQLY~{N`0;s&|v=(sP{={1vaSv`x6oZU`F4BV{ zE{xWxoH9wOTt}&~Xkic7##9TF#7Y=@2ueHj49}4Up1K$t;vdS4Ix(p9f!&{e6zISnn_#|GDZFi_18~AkXOTLZRsM=ngiFDKOSi7?K zW!rpo#ZPj_kX64XKlbH+a7Y zND>cax{8fzGb>jitL+ zLjQ~Y$(_oYh7rO&MVvJITZd%!m&qe9*>rW^NzKqQ4CPBy&BU-%O`9jNZO$tbiQ8`- zA7ErT(i3cVC-Bq8{d4@F+#_$UB^L&g!tJzD@{J6hxIv$@(a9}Xw$g)IxhH@ZvWQ*3 zq=Zkn)aN)SE~LRgS$nOy*{$ThvDIC=@+wwjJ>SlS%&6-kN-RHmqp_SLty(dP6@`S-^fu|n+Ufxz~ zd>YX=Ae0TJki5+(z_s6`Txpx{^D-Yf14GM;QNt-#axAM$YU?Weg6Hwve{rGYJT;xk zi4Ed%Q!UeMGkV0V%KB0I`<>|)_Fd1nPA+q5IPX07z4~fkfYS!qWv=wR-+|`-txI>D z_;ZX!o-%3mRQ}?ju}pX&y;(5SHLSP9Q<$>W&NtIKAwte1B6nnrcn3mh>9sR8u%fH` zLFv#vY}aMF{uYnIWS35kQ%BD2ZUEj!R&Vo~n)N8ZDHUDB_-%)NV5*3&&91M_Pf@X& zSmV90>00@slW%M9z-<90b=;_r>JBuq=mrhxW`y^gm|vCWQq4&!SQ z+$8O+Iz7j=k==+`(cnphs_5W&8gcg3Tu&BAw8O+L z$=IJ#Q7^3C97;#K0tW|GLUx|^fV!O4a`iU^AS<1rQdeNRH$&sl&)9(URrpaS>ogo z^j358v0x}0G-k8sBeM)sJGkn~4@ppk)yj6Ju;$%cVEJm>jAjZMD^mfjuq<4(hZf5l z@8|1t=rPFG+1g9N1BPD_Zej5&{XD=C2N}~$tE4TiJ?i=&wX7=g-*uY4xklrD2wJ5$ zn$NujY1;*o$DTOaHTQ{DdOP4|MA+%56i+K{!yfLGKC)SU+y=^RZGc2gL-)dpqVI0A zgoxS=H_l8p*)LFVXXRkjIoRvQ%vILVms7VO?iipF3SW+xQeq3?z|;13aGx3z^3g#tcoVhfv_LsFmf~*1%n8~OZAH|!8i z-vw8$L8&{-(?vy}?dB#OI82CKVIIR6)8=d-uQ})^}it4+0muYPq3>;>+|uF|rE?lhb=>A$2m82ttWWuN531-|nmO z>+vGZQV0UK{`M$r!ISX_Cb>^`bx`<_{X@$EKdV7Gf{73^3pkp8Q#A`=4cYK|3iJEw zHw2tCT6S)gS|)~wyJ_zB%tg77CRNAe50;`fHrh5eLe)#IpaIBYh#c@^JfDdpS5s!` zY3##xn!*X|aEr#7YXADog`pd#a#Z2Hp+8uMeHm{J+X0o+i>)HJH#DyuaA_oXVAnv8 z-}}WUJiPn++%QEHAQr3kz&y)$9_+%1ybLLCj8a>KD>$qPU{M&w7*^U))He%g!NoeD ziVE?lv8EhgWKsf|g!(Zn_HKd{!AQC|y?$W^-$g)f_SZCki~#2HNJcS--{9L*-twA% z+R;8;`Cm>@1CA{GV%bOTPH+RGdbr*VU3`t(|P(Q)8>0+uP`#x*QSw%Z*F7T2rL)SW;X$g1dr&r zp_Orpc0I|D!4;uZe(gba%oJ@wmwei?C<7Pk*+%fNw~?i?H> zDqb_1TSMLO{ykqI_T*Q$iC?qvsAr4~FmJDt4n>`65j8BF^i&ghG4+VJ@$fSI;x9+5 zN68iR3*fjVq$N}X+~Ws)9rJ2%kQMIeSR$TU9Bz69}drBw0(%KJ$!m1x76Es+Jd#D?8 z{+HMU2DPq-4{cTGVvzl3^q!R@FWxQbEE{aBXRwD)1ym-BtrW}+F_9>I|8#0%TPz(d z)lsFJM%Oh3;|!EtGX6V}nz~Z^uY+oO*cDvm6n`xx4KUkHx8D^g{*RVYl07}I?A<=~ z0Tr^}hyX5xrWbtmCS)|$S>B+Se(l6OL_3KK38B%v&#Q5{@S#5(l zgiiSKc9q(y{pcuF_nZ4a#I6Rw^e=k&x;w7xRb3y@|8`?^`1jJ|YpWy$2+77Q*W^ifTc$Sx7=L5>ox9UKGJ}AqH;2Q|D zSB9FsEt3m8MQz&>v-@)U8^Hs#YX8~R&j-NUisBex0IIEpgzfQrqu-34?hATDxgBoK z#S#qSe_%gBWAKvl*6XVb3?7I8M6#iO4O!lmYe2?DH0|X>&hrSl+TI1Pfyqb0?AN!W z<|4cI*A0K(MFS9XQF_Bphr8|qUqJLw_4}m{tO1(dFm+?J0M(O0>qbnyw4Zx$T$nq_ z!h3XFKfVY@2Y8%_yJ@WV_&OlJNYe&?F+&neKzfsM430X%coQ>($RD%6GH5_^;AhklQ(?rXo&<0j-O(^ivMQRL4_DOyn&rnbVm)*v;t zv{+bZGpT!F-Z%f$DCdh1-GI@k{=}Eo0biR`4ertXoWINr_t8me$g}2ua$i0K*1B@e zxw6B%>H1T&(+?2U(m0k|95*xs{D-Hi|GKB7nPAmda8RtFMRoV8e3)pUncb?Wm{IOx0mN*B7`78?SBgP~> zF2z`;^Wn>8fjxfe$7F^m?K`5(HjroMPGQVm$*Ma;@1bZo%Noc5_&x5(k&{=pIycN( z3EFRh%#{V5H+AjSZXr<@lU{0+r#Hq2M>mSr+dt%R@qBagOj{tQ{AiWyRb-2aiYDYB z6v|ut;7$(IxN*yj$YuQi-WcW_ta@y7A)JaSi0XhU2X>o559;6iCOK?<%K*+LM4)RWN zV)ooBJi86kLPo6u|IeP>2Ze3t2L;_GVOROnf;SYiK*q|oo}ws373tC2Qr+V#DQBBv z-#|uo4zyuB#!k{QQuj^SncsdFzaL~{CmftTXN{iS&Mf60Sd=(&67e2zs@0R3Y>WM} zCIG*~2cml%Cf(rOWa`^W{Xabd!IPEHw$vQn_14Zgy2W_5_JfCVB!}r40A^SC;-`__S_d8 zh{K4I1XNfIO^QI)AzlKt8lc)DrU5za_-#>cTSQL>@@k2Z(+8rwO0|pbw+l14@p1+{o`mKjQ|5|R*?T)y;;@_kY9Pqz_ z^A{7{tVZ4$+Jf*GrtE`Wqk60G;1MiZ0rOk2{YqL6P&Ul0dgI^pLc?0BfK;{={59A8 z=FL7Yw67PZD&32}-uh|kp%4!0`hvdwqf}@Uh4HQU_~lA;Ec+0>f8-S}XdL`SL2Ws) zGF6BQ15!~g$puurSbJkfHZN8@Vnymjw&*oOa{5xwMG^+iDt#;|f5G^cAC!5&f)D?m zRs2{AvS2k1(fR}hQ*n@FqeIM~oRA@IgG{5EoFv@28s1C99gP}R zy>Cw?#KAFPhUhJMoBeqQ(AD%9#s?4^lOzoY#{Td&apQd#f~NzIyr8eSU#Q$8f!D z(8~Opmm=y3m5;hc_08IO82{w0j7v=loZ~0G7!JE^Be;LcK;vy@fd+0|%ir0tTFR<)64?6IiRoU>mOwh>15BuUr ziM)D^O;EJ={pn7T)7>)vue@YP#hZXOeAycuhEqI)4_MN#B(=p;Mvz{A@(<+N(Yk*L z9vr3v`h%x0aPY(523Yw0Kod=QlyFy}_?F}s?Sg%pffxd4-4~J8bYfnkOva&eV)Y?W zgcjV=psYY()g4^QY5W8QIz-AEbv|`N%D*MqEqE(B{2+^3n|aLX8~^*4j%C#+-MfZq zp{rcH`V(RMQ$IocbJ~vFLi%Ww4(jh#%3vMEWG9DsbHhSlUfNmv*sfyK$9A+Ry{CKQ z*t(P=cFgTs8PQ}7+0W zR&RuFi)mM!n8h<)S?6=s)%PFxK?2jYys$mh!lmn#Aq&+Aq_nlwXW?=oKehpyQ3Q3vkECEEF3w=s}Gs&y$cH7yYsf% zS58=!?e__1j6(blAADC-dBKbbl($00^v!H^_{xs7{hT40WwdhYX!^ki3Gc2+MU&?}iATDD1y&$d9IRQSpPrh6(NKB(Dn2-<}4*l}9pN#cDnJj(v z`mhAyZZ;JHuiohk+!9+w*%7i-jS_#VwwcpGsbm_Yh6U&_X3KK8ngQ(!LA8`otT1Vq zuK}8JK$}kULxBeS>ZltTf~u1BE>K@_qSiB@#sr3zY%<6)lHYCFuOaS=nl_8DIXXyq zKDqHLWICkxV0S8^mWL?JluW>Yq>enx<6m|O3^!qQ7ZXuUV%GtFuiJWQ ztK0D3$qdNIz*gV}_!B-Lyh+Lf`ATG)-^j~nqL?NZqm zij(I7i0xY^^ndXj)rG9FkOj1GqZ$RIG%ryZ!Jz1BQ9l_ckP+4W`4yEC{bU@0e9V6p zV(<^Jhu#q>Kww}5-~PC%+Oj8lVlm80`OFX>C5xYxcABxl_pitBK^3$Od(1Ii9cQBQ z$P`@$UY~?|5x-7aj|PPGDcri@Hm9T8#2o=@@nxc?Sv0#*pnGnZlk&h0=}$cI@4thO z8l;KfB~=p(9t1BG6H#nN7ld%l>P(OcQxibk2dYuAHh)hj2dKFGC=Llw$<)d>K?o_; z8_Xts$#9d)4A^i;Qq?F4o?FLd{}&=A)ku&K&quX`k1M&bn;F8>Tk*HkEny#!m)PaJ zuhgxbJ8e%Bf`+Q$PxzB`MPUswRId;VA_|=n1Bp|$dBBnwK5B?tgMMYuvjKDl1!teR z0m_$hCe(VE%VdIMFy}xAplw5>> zrVBN61Q#1p1=PNP>e1JZ=!aY1*)_oBp$H7L4Z9j;w~NxEw?)DX%?`sm;`nUS-ypk( z|2&WbCclILLjUZbK8HUK_cTg;C_SNc9f3IJ(V{$0as&Ng!+#x9OKq(xY~Z83AFUtw z^QvE^X%GF&n*@e?EAdkM(ZNr&iD-N&^47{6Kh6n94@!OTkm-1c45wHL^Qqer-F|`X z$XV{mHU=i%l#P+~FnopQIXXcH9Sgt6LsM=$WOmDysNRyp~JpD}hj}oa?g+RW9_Za;DSl_SFG#oRF};6YwYZ@@%lY<08QvP=!X0Asy3y z^pz<^_l~lE?H(Y(NcsPi_k5f0C!_X#FQ-y+blPamN)JGHtfY>_Fj9khMG6D)o z39U~)DfOTl$FIfLt%>PHepBbOZ7+j`@Y#91^7BFk*e8?=@l^MOEv!iKHjsR2n)H8@ShzI?lhTIXT1cY%PAhZUJl;ZY7snf-HHiAj)doo;Rq6Y z1c`kD#8G!luqb(b7CGx}i6gkFR{gYN2Cc-tDbQrivL* z6i4*ffL>Fjvq!7JT0pLv=DG8EuXv+|zVN2tU#l`NAYxKW!+4wm%%P_ycL6s|GoAGRQB5ABL2m zsr^(#!9qrgC9a{T#N?4UN%F3Eb+qS7HS+p4^eaNn( za=4&5EA9~@jrKpNOM;V1AP$RRtW40CBsr=JouZ~%*OknhOr@Z;S2k=kX{1CLhEwB* zQ>C)#C}>(A$XlbO>qQq|;xH6PDuD#G$4e>SkToSVd5h^bo~woWG#ngd(|yaA-2eK4 zl+T@<*ovDAcH?Pv-FB7FDIVLyZ{<>dzJDj=H*#o-ys6~??$F=IN#YD4NKEA88$p~* zh?t5XA;yg`>7@<2ufUT`?aNDV7b|RYugWkTAqv>Q

;fxnTp9OwYEDU<4u!ahYb*Xj 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

!)z>rjC?5l1C47 zsN?Nrh(tn2ErJya#7{Uj#|d@li#1a4hRVaJJpvHS1M@@YL>i>6|91B?oc+_s!ytS( zBTL+c#qyBk#?qW0F4n6K7ARE@nDF&5kM*d=)Icqc-uQd*$60`0vdvz)NkXj9+wr>{ zM{ndktSe}MZ}~y6porJ#HS?0|?8B9`Ch=eSU+-uU+L_v##r)^svso9*s z=XO`ggXvURj)ti#4yO!R27~7(3icNO2bMEynQHiY@`}X?zT7myLhhEn;_B5;wi=wZ zCPmVFaqHx|g~uydmh)rT){2o?kAN`Ky%ik(X!jjgTaY56z{$C4lbu&w)5fIYpOwbKzSvxI&OPK~ z7Y&QuSyq-5C-YPa=@Gq~*&Au*58_wjUaGUtQVW}}11NJB_o%&3rM<-|Db+=YB^qCM z<`HQWhUp=fyXH?Xu}@~Ok{-zxtasAFv2I?ZGQ!5YEgllF5cEILcG3FFxh!)AyDP59 z_sT=K5Csl)CCfyIoX=T@NDnAk#u__@OY1KRlWm`9*B+P?4G#D$_Vyd;r?%w9fs32m zspidWNp4B2+*)_}p4&CK41);i^$5-fWpGWS#dZ#KQ7tC>+}d{gP|YkCzuo46EZ_oT zXwkk7atpxX0KNS*D0V}%Izd`y`hKkSrTMc?)4pXgGU%PreztXE{if^%IKE#) zbqMc(J|>{n`|K~=R;68WTxKBmHg%kz-9B<)iy?fGL5FQ9Mzw-fBHds=I~SW3?eL7n z+(n}{=x-e0(|CXG1-?dqv;D*a@M*bE^)55C1oau~hrJ$<1N9m4uSXAF4*R7|f9?@F0DjRp_6V} z!IPO`Tjs^!SoYqY^yS_W9bU)4GHg3GrsLo^?Du5JaimpKDx=b7=ELZ2GlZ;(*@~(S zRvC%P;rcWr^?3Rt6XwFv)xOK&a@DwQeDMO8&GN4jguThUEmJlZveP(GSAkD7(G^8>K0}`(ATr=J|qsSQfznG)pPhk-lj>o)H3n8$@!YM z%KMcxA%j#EO#&_gq&AUhXgGOEx4;_NNb*$ud>_CdDB2=%(ZRXweJ;B&T=uZ;MuyF7 zscY`~KT5k2xR~DVKO|DLP$*k_NkyAPmiB$2Lb6RY?akConD_ zD50VfLLreo|8v{?p6T8@)BC@l_sYln>wEU|oaa2tU7&2|60zsen%Oy96YtnOT5Du$ zAX%96!Lj7fp zlee}m_wIP9r`co0FTHYU%{c0I=gC?1mmNDZT{|o7p4R8P?!MlbH@YxPG-;>vTUWt1 z84FkQ+blX=Q}PsFIo=e=SC+B!6E!Uoj2thdg@c)10lU zi3_T>KFG-s(&DeFve=a1k@Un^CBp8^u9{}M&iV>+1jJW4Cx5?{O@%TS1 zja?-(4}}_b8vYJGuqR^A5}_-RRswIT_h|_@tsA27^_KnlmjZ^-0@X(hjD>%sh6L_4 zSg~qy>B&)5XGdH(r=`5%-&(L$j#D?Vrti< zOKEQ6GbH%l8T)O#pY!a{mDHb}3kyG$t9-fvle_sN29da{+8Gyk(ys9dJ!7 z-9S{bWLM6UMRo=0R|Gp=5($;?`^M%;6x>+s?4lYN0g0A5po?X+#stFEgcfLezACi zQ`E}qIp$AHjKbQ)RM)Md{BqqfwEE|%|EaGPBXQJQ2`kowRuWKB8 ze1v^cGi}h}$;B#hTV_T^>W`{!440W?_9=Cv=5Uvbs-HfHnpH~`E;}|qGsX1GOV#5^ z*2z^nqji?V6s~z3GxTV&#P2iw?|1EAe2vEZ;2BqY_w(6J8v;^ZwTW82v`8y{)D%9Z znyLK!u*xZ$s#OQii~9TM(f8-RucVz_Q5QA7%71#*#Af?Y*_;niIl@^EbqVy~2}R-J z7b;&qIhGNXmErdDL&w&d`lnM*Zh9sc;50(dN4VW@y#D0bo6EK+jcNFi@W9GCYg>4W zLasv^d+wJ)%be46f8EUcB-ptkZZSVCrZ`6I zdey12=wB`}db1KuH&Bnht`1e6Bvm2>CNnx&C@7K{r&E9M>G_$?CsJ-iblzAZbN`#d zhXdR7OkcQtX+F;!xpl6~Cb{G=E$Gd21(-`^#t!fzo9^u<99 zJIf}w!xcWyz8inv!7qGt?AF56L8^iscN;6V3ts!6GUHJtzewiB;D~_APqEYLb2IPd zA6;cXe8tBTjQOP>!xWmYCa1*wR!aZ-jpM9ME$b3>0c;);g6$3Z|8wEjUH0vD^0ymp zAR1Y;ZPFau`SY)iH6Bzb{z_0F^N`qrA*w!C$Ne!*dq3E0^K545&5ne)5|PdcHbW8> zJ1Og+N8+;7%QvgwZOez2^7iubd-QdGIy*wdEU&+;Ur`(>-Pu?iPEm z|31cwfArd_v9(jw&Q5;zzE;rtz=M06-)tJ8#y_q`>y4k8sCmor)@KcCH$IAc>0)$Z zTxR|X)9D4d{)_d?=qHB%RanU~f0WUo`r%^ZWwmM(ns#kL+|jig-mGBEE{kvD|Hjv# zHBRXGRJdz>7+ZQz-k0+XdYit;#jh0wq3s^@8jYzJhaO?OU)_|a{lQ$q$jES`lt|cz zl%tDjsSZ0!Z;O<}<&_Eoe**7~nth=49DAdlAl)cN>y=NT(#FFHbrv(MRw%xYrJeE} z)^tI-tk&oq&H3v)wY@HB0#Vl-Rc@Z#In%pD$2G1=K;v?1Xt9mhvqign92ZVhFWIbK zQssKH>}OiaEvw;9qDkgbe0yj5?>CAMner^V*>s+fnO>sgi#Mw!6WChK4?o?wsy}9g zYU7lNt#>|8m_S>fZRxv2GeGjbw!Y_1eMzahu@c9N>qfT!c$RkZdhv*Dhbt)~{sf29 zHcMS^Zy#~@c-V#dp)#RrDs@$^(Uspaqcv|I%l2qK^3hEAkrHF{dA>LA*K1ijF8fsQ zhN0|oUhj2oKuGqVtm_Gy_v;cJj3<8I6dMrt{Pd#mZ&G4g<{0J2`bq1Ah~K)`Xgqc+K3Go3vA4%}uhXq=d}=J`Zw^At_5ZQm$EhyN8kmZ`lW=Y>xE>68n3XY)dC zT${UNy_@Ba6@#Ssqh+PDntb%krtY2hILP*K&}PS3>kc>68o#=@LUqCN*PU+nbhov~ z9u66;_c+Sy`{Y_~kX>iQaoQMOj&woR9B zNKBLp8rmj*#_m+utk`@_as6UG8&jQ)&NrL`qk`X#N*!eyreEr2bbV(cYdX!ZWTuc+ z)I?*ISkLHyr~sN@w33V()ljOaE-7 zg$)~0T0D|(Fk5)`0inv05mp~9lSSU!UYX(d&|2B!mJVw^Ys92CN_@``8O#bPNwsyi z-cz}3_FI$0xI5+^wTa@+bfrgf=RfKRQ@wzn=-_f zXbpQ@d(-mPVx^NAje*8?ZxCT@sz` zOs~mL^}WeI{Qi`%Nz?3aj44y)pVpXpwZ!H1^TYg~*+J@QW`lhbrp!vWRn%Kut)$~B zb0ECv-JAT~R(Ug=u33fcx;b@QjQ$#l6H~(WnrJ<@|D^bQVSsq@l(6w*hg9Yms-OHb zGyjwhT-x2To)8#aZU#+Sx-zRfo`OBye)jtlcZ+g0Eg4rH% zflc>s#P6*yTcT;U!N{uZ*k~`|9V;?6rsgd>T`<;v->H+|Lw2bL9{h0rnZS$ufVZ~C zKV|HF?=WsmfMV$v$F@DkjI6Xw+Ltv?4sL1xJ#^2Tn=Pu&w6XE0%kN59AD=6vsw2K> z_Kx}aVjpcI@(SJrR=j`hl&9{WK0!asY`c$vZPD1A+kG;wI zANHwbB_I4FpZDeUu|GDmmXuX!5018Rb_|+fcOZ3A+&*6c!Qb(ReN)N;Mo(>Cm&1~( zihguRvOIG}0aGy8#zA1iq6M35kLG#^`j+M|si`u28GLXl{re;hXUj>&9_I4XvIHk@ zowu)|^kB>@tuKwN^pdf2i{{)glyIDIH7n@w4)eLOMlo4i7KvmP-7kQ>|9$NlB1PIdD{rQ$Ru;`)yGqdIigAs0kp#tm-=G4yVTaTUwi*lFueF*u zca-dU=i1P$xzop|rPwvvR5pelEuP$beINfg_p|k0b~46uHi&+0GIF%KI?i;x$K-E1 zwN`Ch}8iJImX6WA-=ZiI;^< zrL}F7pEhmUw`uF1YhAYJ3=0dhj{N=|7lz9i=r?)H&2V?`HiE7mMYJbuSCP`=Q$@m}rj9}8HLGV%&aQx#mq+Q*wMbW?T9 zIv#1M8<-t)`OPN>vE$X&`qHU#DzWkx)GOmpjS&4RXf%bL>v|~0ZaP0(Z%X+JJ2CZ{ ztK`3aP%QfpD?K$;>|AnI!B_hOizKg=)Fzm`nq-g|kr?{!lut^uGvD~VSrVfz(e`*( z>F-zB^ep*-FwN3Vb>>s=wNqP7-&DmHJj&SGc{(ZTj(xFD%gM!Bj!8jYivmv+Sr|Pm zk##?FrOf%TX4tEm_W4D=4hPQVxaCe-q57;rZpnF%<%9RU-}&=vhUZGGv?;f4%-J34%)}Ej_1d_BzLCg4^|hjX)C|?f?Z^^I3#K7#ih4A zXSDieH>I^5X~>n_Y;-Ls&3(<^nx*%qEpHxFzd2@N%>Exr6KIO&lL9Rs3zUha2#M`q zd@_AR*oaRT)6`{jHY{fQhdZ!U<33G4u$$dHHzt0;HOZkebF~ip7FOQZbbO}v+%fHW zY2-dXXJP(lOP0*qXZEF(uWC*B+n17=#?rqei=_0e)*{}EKoTi1{8uO*Y+(e3_ zhdiA3V)CmL_3G9QnHRQZ3HVR0it{M@@<92bY0|5U?C$DUsu6}iGO?>MD>h;zBva{9R4T*Uab9;o7*9QmpRg}a{ z>yzIf%u63qHvSH)>A-)Rgmg_oZIXPu0~}&3a@~`Aw#1?r{Cb>ATY2sO(}GKN;QF zY+0S~uxjy2K52c08I)^_Y0=kh8;||c(H5m$JQdP*+ka*LarUpj0=2%`m+jIGRww1Z z(7HG7Oovl$#iIukGKMfme)}f)&Ec2$q{j5u0iI93*O&Zt6fmeixo5#XotIC(QZ1yn z7RAzkF28S-|M}CPTT-;ait9H=e)%lu^2bDX@qMM3BXY(QJ@XE-TIiD1)yqaUk5OYT z^VG@pq}%Tb)>`;y$L}$9c@q{CXuNG{@z{2Mzo&=%x{2*F={4sIbN3G)|4Cx=CDi6{c149-fGZbaXz?| z2A+c(y>+_&((}h~3S_~qN0icPfc?eB#L+;_!q#+JXDQ`BzbZhofb-i_dJrk+lD*`+IA`G?xOp?( zg8itd0yxExKwu8z!7%6^1K^~N0K(7P4Hbx!lQ9S<;)DAulomqcqLj%9hB+aIJ0q0t z$Dq0+a&a;QAN%WhFdJDHc`|bUzr@H9V}aAR67B>gq=hgqr;)0T7c; z^&{nHLN7aA-lG9=!+Few2K;ov_-m3PjYW`ragaQ`{QznJAp3DZ{NP3_7P$kBLpZ6z z0r95>xp{G6MG8R?f@H?289LRU#tNXiksAutixCb^0F}w&!VC%$h6BQ+VT-h+%0+$e z7y$^&8@^V#niNPHQO#>|Ah0^Qf>1Ph=yh-^8k4PuEtW@604Z;1n=HYF>q>5D_;L=rsGBC^z_5a-LBZsr zq51y?4oDD#;YW^v>iRn&1{Lz-YHq=Yj?p^9`sCwT}6AvNCo7{WQq_!IeB80|d zc{AvwZi9+afrEmbYW!EQbk}Bg4Fn5CAj*|tuZUuw<54Kt?7^^r!0C7fuB;#?)h);X z3P}(6+1-xh#8m#Ha9a^dgbsNB4X_xd6Vzh;FiEj~DeYWt0cpM&?EEjAU|471bOaHW zg*!fHCo6vGWrLI@@X8|6&V^E$5RLA^z{k^;-Z0!7q+A1Iv^;_*JBk?3j_K{`O~*%^ zGdft%0rJOqkWLvvybC*dh&WtG3-QJrgh=k&YEkORz~cq5v^s+70qKDg)d;FVZ_i*R zH3%T(7Xh-Xx1V>=YJ85{w!gmg0Ic%>y4Z3EwgFTiq}cd?t-@QMoCBbdpjZV2&;juA z0I|B$2IAeb_vj0!N2>3B+2RIT4Hw~rv;(toLK@RNsKI_*oZRTLbU`eLoe7f!J%r1z z&>kXyG^PbW0Z5~}t?rGWe_xTtSBBVQ?Fs=1ZBcCsMFSyIIh_YG+~D;q3d71k&y^5j za}fBcCWP>umvzf`|AU3QO?T~uFNuqNO44QUHZ>!75mF1xcqWApEi>`wg2N!eNJwJX zl(P59W-q03f$ohQeBcfrs_=eL4;8>s?c2}@f$f7`{k&OT-gHmng$ujq4Lv8aINefz zd8E|@fNzIavzKZ3na$Ss#DgEG^8~S1O{fLz9}xB`2>u~2GJI}c6TjU@q7!f<0T)eD z0Bf$J9M}bUyAT4}9N^tsPy$pbg`YG&k5I#_MNIB4gg20bh_^9=6XN>o6 zrBLoO2T>rf`krj|s!&{1e3<(IgU7CiU)~EZI$Y}t4eFQ4K<@^jR3;4{%Wj5otQ92M z$uQ7M177cw&2GoXg0UtDrlI&~;*7tS5&&&Kpvm__!Ov{=8ZlhXY#Ht}c_XTyAJIVY z`ejSl2QUPdxzUKQ7)y+35&{DZjD^P3ASynmr#mctLIC$77#PJ}Cq<0gn>Vom7a!Mp z|6^5ej9F|35-AioUE23#v)@f7#KdPWMo@mnJpizW zWPlo|W@&#Y>#q5|15}VfG*5zRV#SojcFut22129Ey?4Pu^me1sSp>dlcK@fY0(g&0 zKVMw8yg!tUaqp0fFKXea#^(7@(5#VFAdGa7t5C`Fl8LZ-hi4+p`Q<+y&Vt0Vz-7Rt`<`re%hrv`aB zQdz$EkmJ*q+P(#6JqykXm2%&c%@#jG07(xr4EFYOcZ7KpVTm7p_7$ZKgbsmv9IZ)= z3kYGcp@I~(u$b{P1)_BjL@S!tBQ6r6+R#`mn2T8W2lx?{D7ot`GtPmTmIKEqw+>f$ z!NphY{P5*`PXTcqOcl`*dtos?DmI$;%)jls7l;V*^4)Tih&t$XT!bHMqhiP%oMl(i;eYyWGLrn?+DJY#Ax*(+r{I2c8S_roJbe?fiut(>B=O z6~3xqOA93rGl#quqcot<0KS1vsJBAbgEN4!xByLeaos~DDcM4?nb zo$|tlLpO&AaAN4!HmJJ z`uv7fFa(D|Hy71xf*f~zd}}SJtWEj?fp!^il@Ok%sgq$sPcz7#;g1j6_FUs&I)FWb z7iH8-ixAY9=I0HlM9S^_Akgp!It1&W3yoc?*!yI&&9%8=_F!|H(Qgp0Xvl&H`vk?3 zd@lj`na$ocmm3XyOF(qixQZeoy%d5k z0$O@#p<}a>5Y~dQlgnq+F-Q;KieV^14fooE1P<0b{QU6cE_|uS=7%`82gRakoJuD| z#KyGlGLImF4@Acg(*jLihB*jYIUZ#ZqS`Z9K|MtzafXa5u3p6eM>__N_TLQ`+3YEi z#K_&fF8SUff(2O}TT{kYNwxf{Z|0CRl^_byaryl^t|WSj_g+f)6vV3=#cx9eXaY3~ zYQ_!G+$i89zI_n>TO1Y#D#3Q*2Ci-?AtbTe{w}msSTPhjBoJoO2#2rg2;mk{2|BWpV={+g18^k-E*iA#CVVt| zs+%tq`!>{o0O-{97a7}el473{zaB#C67Y%6qKCY}M}>;f&)ZcUR_r)?l1DO{cKHF; z9pKUck@sqIf2_X!LA@(?Mm-yb{;foi_hXL!Q8e2MNclQ9W%qXl41 zwEil>mYNm*<^*mBk>Ww|x`f?Zjkn8MO z5zFieka!3>n~RW%{6s>=gvn$u`zwx|){5;-LmfeH<3MlFnd*D8*{45~(CV%R21@Lw z#k2@ZAT|_;&FLeBRX1*5Nr)|`GU)>$g@w!mLs=aUAdv|#I>8e7jzbFDzvd0cDB!1> zd-w94nwuBagyRSy4EwcUdwnC|?gCNJ;_^H~dyI7=W$@*O!K$y-zlK+HZ1DPBbhbbd;#xg2oL6n`EJN?<)eduHA=y zc@7l8by?W(VxZ7oEJ&g7)9PgxerB^s$$(*;hF&7XUlqMTMvt z%!g~dE&|<+at;ba(;CO{TeBEo$4CfDb3}+Lz5&yKE(NxD&|72?*UP@gJ61e~;p{1t z-)Jd!c<4Z>;wS6FPxH%t!2vQrHdyNJd$QRNN0LymWpL;XAKm?}{XrQpI|Irkl>Y<~ z67+>MPg+<2PZScQioOK{|APG-xN{5%1xWX>*wjmb%cz-O_xF_*;O_!Upi1TG1P-7k*ydw=fAKqz7WfI+eGS@1=Uo*_+z`9j zCW_zf!Ea}#f`+lVB8n`i!Xq-l@^$>HK^Ol5>Sxe`N?-h7>Fu>DZ^-z%Xq19$XaKJY zUUc+O(;~qoH<@Ted}9^>*1#(VZ|{@M9<5CTO6p)1PhSKpfnK+OgQ2~&Z-jt-d&Z4> zHjk5d#H%WWS=YcDas)VwA-XOR!+rQBbobsI%LA!JT7mQ*;C%By6m%GgpUst&EsfSk zi$t6q$_JWLfyO8h39XH*=WwNA58HU5EZ`yvR(mzp2{UuSDx)D|q4nz3d0fdj1W}oN z+p>5dX17iu2Afnk0Wq{*EjA<~#_ZYY4;JcO#_L-vBv2nF*WuGyT^p(1f%?!=BHx5} zQX~Y<&G20p1+q{;7IY$Z-;5i9fe6x~G;3l#_`y>U1RZwsEP13uBE_TJP<3oj^a6C$ z{MFXn(7UWZ5K-R7-`wc|#M(h^Xh$p0b|Az^CtdBk9QuG*@#CizmxLdUl zhvPoPY23iOqF{osvtHisY{hj2V4_~t6iSTQv-0e?IsjW_B;16OCOqyG8yMXSuN=a#WH=!>5g?}O#J3f3 zmx0qMP}HJJ5;fcaiChzd)d{lofo)F|TgV6s2%q(lgnZgE$T+R_nN|hcf+*zxiP~!I zdJ@PWGR(}u7UstRGXOMzvN=DB5YvuH26^uA2XTFX6bDGO!Ko3`9}*fh|2dBO-z11> zQSjD>!IFT}0RtU6lICsbkJWQ#tar-6ZHpO3pgn5UPcSpZ5Uh_TsnKzS1dJH|P~lMF z{1h)FG&M`t(71czL_^_WtnZ4wxvOx|e6c-YE+7 z;wdu`kK3F4ztF)C?klqI(zn4pA_lS(s<5anT&VP};c*ircLNkG5=Xg{G7Xpsn z{xoj-isRdNIU3;ifzHr;dmK(yat;~yW19x_)r6-AFpp21S^0D-2#uXgv_%|c z+-+i1lQ1}}WXJ68-t;U{_K=ZB{y$RMAD`^1Fa_G>KpUMRohbdEXydEDJTf-*GAIrk zOVQ;6>$_aY;E6^m(zmfJ8Q7RW*#;t^2OK=^4~Q1NC|9rk;J*v-6_7pj5o@(SAci;d zW4Llig8dVzAe+y73+Vx+BoG9hwn)J#Va|Z??>QvgpHhE0ux7N})^$^N0srUVMTg7- z)x_we43}gq-?|(uoC>J`g3J-n#9q)jy1pz|O9I@r(U{~24;FmZ zpWAA%kcQqhN8?BG1u?WOgHREeZdHB>y-@?u*YKkKub=hAps0WJw;IOo%H>hBzXB>B z_{4m~`vMz@k#Unm_dgQKfl;G-86G(VdQS(vqy45EO#`FWUm8qLKKldZ3IKmG)J14M zz4)d-{=Wn4HVZ9`7Y6$gtj6!SpuFt}=!OsUgjNtm(8}P98x+-%Nu{$q7)*#JSl7j9 z;MFM@?^#Jt1vH`D8U*_uOc6_*dH+99v0-|`#T z{cVETJcR$593R+219lCe!?5yqG8(pUy?_IDy#P@lV*;ef=m-phNQ(vnXod*u4n+ zsmb8^6M$bdqZJD91WWAx!IwKzPk@gIf%~HiD9Law1hM<~siH3i@RlMl7s-6c|L_O6 zy`dt7Vu`qZ%833HV2*(uS?`_B5VR3`|8KH(!j^;A1NcE{*c1fqleA6zAL-&-XXyQA z1$j^(wwjKX(st5>gzyFHPXN>4lTp&TxsX)DVTTVY$qktS5`Z)g>qbn1J?_KJE{5iT z6z{;#P)UlF`V)edH+CxrXB(evf0m1cMY}Atl-y-GH@RF=AtZn;1@@iB?rDFL5n201 zQ};LoVFm;tnl`lc2#NGI)5(BiT3$F@14Cn{mr&rTbGQOS^A;|Lz&G#^JBe{iAxqzu z;LM^ru;RfPggtt<^A5kJ*gY_|Fh`G~gU9FKR6a!FfWaW=ZZg zfu*(2a4Jj%iR^J!B*V8>SrDse_TRfHWYGJJU(RiCRCF4 z9ouf((<_jA)WCz$B&wW12H7{}VWH7O#m$e}UkyWqhPw|3&1OTER!1~D6K1h^9^7-k zkRg@j?S>^#Y(sqiWP!PG6@7TtO2EDbwJI7NNjpfft*POwiJ`GPw0kSl$OqI6n;ST? zr|uq7Xm0w5Y+1bf7M7AhALx?WyL29bjTix|;rN#)6ArGCuhQoTxX*=y(iCiG78>Ki z`?(M!)4OibZZkM(K(U8n1&wjP13bZ!)zJ!<-=suv=V6Q9E8 znB%AXz%tlPPN-!BZu3fk%rZ+p$X#6niTWml1)4W*l#%1Z&1$_f5C@hQq*WShl^{>r z+Vz&>&OpvE27%D+-Fqv!5?e^~X9Uq4+yY2;!(o2lzVTzM0{Fp6$RcPk<~`<01mNYd zfWhDLh{1oKKIq4{(Xc}Xiaq6CAA_IS?1@i#fyXzqVALFQXJ9&mpL20#X)AYBmRHvi zO?eYK%xZ|@Bk4afMMaS;8gQNf4xWD|Z#vg`Z$}gzE zVNTNbWU~*#m5wBe@53kKUg6j5AguiY_b6~|(n^~`ijLi*2%9z+(_G!DAx3`Quy@lG zmU-ZYOQJyd?r`@96rq$;;6-RB;kU~FNDAMdZ0FY+?gx2bd6eUjPW`k25Mt2jw62S1 zdba2i$yJ_Fzt#nE$bJ|AP5R7(Wu_Mz{~vN)Sp{FhR1J3X9`Lzj2u5`D*sJ~jAc;@x zTSb9aFvzC{@}bM=+vo6349o6N<%W2>w6G}bMLdXCpm6y){0~MS;I3|nc%3#xUkVUDVEIBLx2P#_lQQ;SBzaOs1pnQcSgUYf4 z?#3la%iVXza%xN)pGsS+s8l@2qTElGd+z@O6&-vka<`|fyaqdmnv6K73CBGLP6eOF z>cLyG;rty1yHOV{*^4*wPJ=8qMlm#(-GqjZ4+I7}jpc`Pjr}dsbM0<#G2PSLC75wE zuDTkn3n4v5k+XyzyNgF~tnookWQRiFqch-7Y)I{Bot|}w2O|Hb1KpzG8{(R0aq<{2 z1m?JC0z7e)j0h~4dC|;+f&!ps>6$kaXzJ^`@gwsAA3JV~PWUBGkl^?Ahv1@j+)E^| z&~{yt_#RG@Q?OM(6kGf>&)5WM!(ne)=5V{L%GszO`>9DSneT%UC{Y^3p>!!39rf&p26{b(9Lq>pdipT){jA5MOc>v z+Qztt=dQCc_qV>vg523;H1$+=y%58lT^nX=nuR-y3KG)#szL(%Dk6`FP zXEAT>N#VP^gd>5$L?#Sp85uw47YopNra5KS_A7vTPbJ)YyQX~`b}Hi9~o|t!oHe8 zv_Ap^w4bolMi&Zl6DUVe6*0!Vna8w)t+^PTd!z~B#f(PCdZrax}?mpS^rs`2jv z8H1h=ZQy6UHB)j<&jsckfqC={=J*Xn(o~!7p0^*t->pFjs2z)Q@nO5B zh5xvf$0nde(TXwdBcIiL1UluFu%3W2KI9Nj6!0DJg!fxfZ0|t-zFWsBeAxfo2I&A@ zae^%mfp`5sWr0GP;YEwg<%RgTm;$=n?L7u0s$U&v=6snB<83u)11)&0ig<-KGjX(_ z!~QNf5JRI9G*rvIbmwC^EF5f#o-%lJo>w~m5sKgfDa^Jp#u^1wFv2PrG|;0NiWmP^ zN}6H#26t0@^g|FrD-kq^(t3I2f2E~GKr19C;cq$ks~i+CXbod=okv>uLP%~NIvqRA zX9JOp4qYp%@PT1P#~?V!iw4)2x?#ud@Nth#+3AN(FtFXmXx_Q<1RwW55e$DNp7%>0 z6*Yek$oYUQ4^GwlWV0KdaYM%Eb>;Ggy{TYCu@RiZl5ib2L}PE*aNYGmJA7<$iN%FG z!AZpX<=>VDZrH?|VKGP6>R&Mic+eH&mIOnHMKxF5$gIEWydZ7P|yu?*nD03Mw~IDOy+-o%gQ53Yx=?8mqG z&%oYk%4*1GXsY!8#0$6$)s2bsAt_ATErJuGu}^Sih;vSCtG@6I4YvT`Gu~QIpH~WA z0{u9S4FFc1Jfkn9xiOeH-_^p{7x1sw#Xf!32t^*c6yY&wSikBhxXW4oYgIc}A6V%8 zcU&G{48A{)TXJE3UI!^ksW&d+XEs}II1g0tL0^QXNfk9Kqf& zOeyYX#4h9jd#&)IzPNre56I*@!&FRM#$m}%3bd|>=z=Lt1WtB4G{*39X-}hOP{WLV z^){mG(I~t2ylBY&iK!b{rJ$MEuC(D0qA8gj-k-W+62%hbT{VeAewv6z54Ls zWqjycVp*d3f)q*_Y?zfpEO}3t02=Gq600HVFtuVfK9Cq$xjVenJf;$z7?8r zXi2iwf=810vXt+cd-MgU#s?xt9+Bk}TyjPvi=!9Rp9I-&+phg`cR(|nU@wF$f+z-s zA}(T&!}aG7oA2M88}j)K;QWFYjcqAkay;yl6Zn{vd-8kXfHcJtq@IHCDB(wd`Ok4N zf9ns6h4N2>TG2EJWor>mR^1Vr1yOjRSYr6DlkL2~$Gdo%VV&s|$ZqI@tYkbfeD~T5FZhBM*A@4G z)0M-EW+dw*V*Dk@SVm_!IvhV~pK75-OR_>?w^ z&Q0@%Y>eo8ve`lE_^_~f6HYq1a~?}PC7twF t5q@1BUYP#(J=tt2Edh#u*OET6g1`@644=#%v}Vwfjc@@o{6`eZ{{hS9Xm|hs literal 0 HcmV?d00001 diff --git a/common-build/project.properties b/common-build/project.properties new file mode 100644 index 00000000..d76f6920 --- /dev/null +++ b/common-build/project.properties @@ -0,0 +1,135 @@ +# values in here are overriden by build.properties and project.properties in +# individual projects, and build.properties in this dir, in that order + +# default wildcard for finding JUnit tests +# the convention is that our JUnit test classes have XXXTests-style names +test.includes=**/*Test.class,**/*Tests.class + +# wildcards to exclude among JUnit tests +test.excludes=**/Abstract* + +# we define standard directory locations here +# these should not normally never have to be overriden +# we define them here instead of in the XML so that Ant nested property +# replacement can work for properties overrides by other properties files + +# root of any bin files needed during build +bin.dir=${basedir}/bin + +# libs needed for build process. ivy pulls down jars into various dirs under here +lib.dir=${basedir}/lib + +# any static libs that need to be checked in instead of being pulled down by ivy +# should be placed somehwere under here. The standard build doesn't touch this though +static.lib.dir=${basedir}/static-lib + +# root of sources hierarchy +src.dir=${basedir}/src + +# main sources +src.java.main.dir=${src.dir}/main/java + +# test sources +src.java.test.dir=${src.dir}/test/java + +# root of web-apps sources +src.web.dir=${basedir}/src/main/webapp + +# root of source doc files +src.doc.dir=${basedir}/src/doc + +# root of etc hierarchy, typically used for templated sources and config files +src.etc.dir=${basedir}/src/etc + +# resources get copied into target classes dir with filtering +src.resources.dir=${src.dir}/main/resources +src.dtd.dir=${src.etc.dir}/dtd +src.tld.dir=${src.etc.dir}/tld + +# test resources get copied into target test classes dir with filtering +src.test.resources.dir=${src.etc.dir}/test-resources + +# root of build hierarchy +target.dir=${basedir}/target + +# any generated java sources go here +target.gen.java.dir=${target.dir}/gen-java-src +target.gen.java.test.dir=${target.dir}/gen-java-test-src + +# where built source class files and resources go +target.classes.dir=${target.dir}/classes + +# where built test class files and resources go +target.testclasses.dir=${target.dir}/test-classes + +# where test results end up +target.testresults.dir=${target.dir}/test-reports + +# where JavaDoc generate files go +target.javadocs.dir=${target.dir}/javadocs + +# where J2SE/J2EE modules (.jar, .war, .ear) go +target.artifacts.dir=${target.dir}/artifacts + +# where target lib archives (.JARs) go +target.lib.dir=${target.artifacts.dir}/lib + +# where WAR archive goes +target.artifacts.war.dir=${target.artifacts.dir}/war + +# where EAR archive goes +target.artifacts.ear.dir=${target.artifacts.dir}/ear + +# where any exploded web-app goes +target.war.expanded.dir=${target.artifacts.dir}/war-expanded + +# where any exploded EAR goes +target.ear.expanded.dir=${target.artifacts.dir}/ear-expanded + +# file used to provide token filter values during text file copies +target.filter.file=${target.dir}/filter.properties + +# where all project documentation resides +docs.dir=${basedir}/docs + +# where all project reference documentation resides +docs.ref.dir=${docs.dir}/reference + +# where all project reference documentation sources reside +docs.ref.src.dir=${docs.dir}/reference/src + +# where all DocBook libraries reside +docs.ref.lib.dir=${docs.dir}/reference/lib + +# where the project reference documentation is built +docs.ref.target.dir=${docs.dir}/reference/target + +# where the dist target is saved +dist.dir=${target.dir}/dist + +# sample: set proper packages here, for javadocs +packages=stub.* + +# override default ivy retrieve pattern to include configuration name in path, and no +# revision number The main advantage of no revision number in the name is that when pulling +# down subsequent snapshots of the same jar, a newer one will just overwrite a previous +# version. This means we are not forced to clean the lib dir between retrieves. +ivy.retrieve.pattern=${lib.dir}/[conf]/[artifact].[ext] + +# To add the revision, comment out the previous, and add next 2 to build.properties +# clear.libs.before.retrieve=anything +# ivy.retrieve.pattern=${lib.dir}/[conf]/[artifact]-[revision].[ext] + +# now define patterns for special retrieve used to build repo for release +release.repo.ivy.retrieve.pattern=[organisation]/[module]/[revision]/[artifact]-[revision].[ext] +release.repo.ivy.retrieve.ivy.pattern=[organisation]/[module]/ivy-[revision].xml + +# override default ivy distrib dir to go under targets +ivy.distrib.dir=${target.dir}/dist +# override where ivy.xml files are placed, so they are hierarchical and are safe +# to merge from multiple projects +ivy.srcivypattern=${ivy.distrib.dir}/ivys/[organisation]/[module]/ivy-[revision].xml + +# Location where temporary data goes. Only used for Oracle-specific create-user script +# needs to be customized for the user if location is not appropriate, or always for unix +data.dir=c:\\temp \ No newline at end of file diff --git a/common-build/readme.txt b/common-build/readme.txt new file mode 100644 index 00000000..d94b2b73 --- /dev/null +++ b/common-build/readme.txt @@ -0,0 +1,37 @@ +Contained in this directory is the Spring Jumpstart common build system used +to build all Spring projects. + +This generic build system is ant 1.6 based and also requires Ivy 1.3 or > for dependency management. + +Projects are expected to import master build files contained within +this directory as needed for the build targets they require. + +Build targets are organized into logical files: +- common-targets.xml : core targets applicable to all projects +- clover-targets.xml : for working with clover +- tomcat-targets.xml : for deploying webapps to the tomcat servlet container +etc... + +As an example, here is Spring Web Flow's project build.xml: + + + + + + + + + + + + + + + + + + +This build.xml imports the "common-targets.xml" fragment containing +core targets for compilation, distribution unit creation, and junit +testing. It also imports "clover-targets.xml" to facilitate the +generation of test coverage reports with clover. \ No newline at end of file diff --git a/common-build/spring-targets.xml b/common-build/spring-targets.xml new file mode 100644 index 00000000..286cc37d --- /dev/null +++ b/common-build/spring-targets.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/db/data.xml b/common-build/templates/db/data.xml new file mode 100644 index 00000000..bae3fc3d --- /dev/null +++ b/common-build/templates/db/data.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/common-build/templates/jsp/includeBottom.jsp b/common-build/templates/jsp/includeBottom.jsp new file mode 100644 index 00000000..4686f911 --- /dev/null +++ b/common-build/templates/jsp/includeBottom.jsp @@ -0,0 +1,5 @@ +

+ + \ No newline at end of file diff --git a/common-build/templates/jsp/includeTop.jsp b/common-build/templates/jsp/includeTop.jsp new file mode 100644 index 00000000..5911a810 --- /dev/null +++ b/common-build/templates/jsp/includeTop.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html" %> +<%@ page session="false" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + +@TITLE@ + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/jsp/pageshell.jsp b/common-build/templates/jsp/pageshell.jsp new file mode 100644 index 00000000..c60d2bb5 --- /dev/null +++ b/common-build/templates/jsp/pageshell.jsp @@ -0,0 +1,7 @@ +<%@ include file="includeTop.jsp" %> + +
+ +
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/common-build/templates/log4j/log4j.properties b/common-build/templates/log4j/log4j.properties new file mode 100644 index 00000000..5223d5b0 --- /dev/null +++ b/common-build/templates/log4j/log4j.properties @@ -0,0 +1,19 @@ +log4j.rootCategory=WARN, stdout, logfile + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${@PROJECT_NAME@.root}/@PROJECT_NAME@.log +log4j.appender.logfile.MaxFileSize=512KB + +# Keep three backup files +log4j.appender.logfile.MaxBackupIndex=3 +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout + +#Pattern to output : date priority [category] - line_separator +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n + +# Enable debug interceptor +#log4j.category.org.springframework.aop.interceptor=DEBUG \ No newline at end of file diff --git a/common-build/templates/projects/standard/.classpath b/common-build/templates/projects/standard/.classpath new file mode 100644 index 00000000..ce8eb525 --- /dev/null +++ b/common-build/templates/projects/standard/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/common-build/templates/projects/standard/.cvsignore b/common-build/templates/projects/standard/.cvsignore new file mode 100644 index 00000000..16b87eb5 --- /dev/null +++ b/common-build/templates/projects/standard/.cvsignore @@ -0,0 +1,8 @@ +target +lib +bak +build.properties +*.log +*.jpx.local* +*.iws +*.tws diff --git a/common-build/templates/projects/standard/.project b/common-build/templates/projects/standard/.project new file mode 100644 index 00000000..6f35c775 --- /dev/null +++ b/common-build/templates/projects/standard/.project @@ -0,0 +1,17 @@ + + + @PROJECT_NAME@ + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/common-build/templates/projects/standard/build.xml b/common-build/templates/projects/standard/build.xml new file mode 100644 index 00000000..c38a109a --- /dev/null +++ b/common-build/templates/projects/standard/build.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/projects/standard/ivy.xml b/common-build/templates/projects/standard/ivy.xml new file mode 100644 index 00000000..6bb7d161 --- /dev/null +++ b/common-build/templates/projects/standard/ivy.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/projects/standard/project.properties b/common-build/templates/projects/standard/project.properties new file mode 100644 index 00000000..1fecca74 --- /dev/null +++ b/common-build/templates/projects/standard/project.properties @@ -0,0 +1,5 @@ +# to override these or other properties with local user settings, +# create a unversioned build.properties file + +# The location of the common build system +common.build.dir=${basedir}/../common-build \ No newline at end of file diff --git a/common-build/templates/projects/standard/src/etc/filter.properties b/common-build/templates/projects/standard/src/etc/filter.properties new file mode 100644 index 00000000..c54e5880 --- /dev/null +++ b/common-build/templates/projects/standard/src/etc/filter.properties @@ -0,0 +1,33 @@ +# $Header$ + +# Contains filterable project settings. Setting placeholders in filterable project text +# files will be replaced with these values when the 'statics' build target is run. +# +# You may add static settings directly to this source file in the format: +# setting=value e.g MY_SETTING=myvalue +# This is appropriate usage if you know the setting value will never change. +# +# At build time this source file is copied to the ${target.dir} where additional +# dynamic settings may be appended using the task. Use this approach +# when a setting value depends on the build or the local user's environment. +# +# An example of this approach is shown below: +# +# build.xml +# +# +# +# +# +# +# +# +# This allows for dynamic replacement values that are sourced from local properties files to facilitate +# local user settings. +# +# To refer to filterable settings within project source files like config files, JSPs, or +# other text files use the standard ant placeholder format: +# @SETTING_NAME@ e.g, @MY_SETTING@ and @MY_LOCAL_SETTING@ +# +# Your settings: diff --git a/common-build/templates/projects/standard/src/etc/test-resources/log4j.properties b/common-build/templates/projects/standard/src/etc/test-resources/log4j.properties new file mode 100644 index 00000000..c6d11b4d --- /dev/null +++ b/common-build/templates/projects/standard/src/etc/test-resources/log4j.properties @@ -0,0 +1,16 @@ +log4j.rootCategory=WARN, stdout, logfile + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${@PROJECT_NAME@.root}/@PROJECT_NAME@.log +log4j.appender.logfile.MaxFileSize=512KB + +# Keep three backup files +log4j.appender.logfile.MaxBackupIndex=3 +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout + +#Pattern to output : date priority [category] - line_separator +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n diff --git a/common-build/templates/projects/standard/src/etc/test-resources/readme.txt b/common-build/templates/projects/standard/src/etc/test-resources/readme.txt new file mode 100644 index 00000000..5ae540d8 --- /dev/null +++ b/common-build/templates/projects/standard/src/etc/test-resources/readme.txt @@ -0,0 +1,5 @@ +test-resources +--------- +Test-time related configuration files (*.properties, *.xml) and other resources reside in this directory. These files are copied into the test classpath, they are not included in the project distribution unit. + +You may remove this file once you understand the project structure and the purpose of this directory: this file also serves as a "empty directory" placeholder so CVS won't prune the directory. \ No newline at end of file diff --git a/common-build/templates/projects/standard/src/main/java/readme.txt b/common-build/templates/projects/standard/src/main/java/readme.txt new file mode 100644 index 00000000..d13c5d57 --- /dev/null +++ b/common-build/templates/projects/standard/src/main/java/readme.txt @@ -0,0 +1,5 @@ +java +------ +Project source code resides in this directory. Files here are compiled into classes placed in ${project.dir}/target/classes and added to the compile classpath. + +You may remove this file once you understand the project structure and the purpose of this directory: this file also serves as a "empty directory" placeholder so CVS won't prune the directory. diff --git a/common-build/templates/projects/standard/src/main/resources/readme.txt b/common-build/templates/projects/standard/src/main/resources/readme.txt new file mode 100644 index 00000000..b354a2ba --- /dev/null +++ b/common-build/templates/projects/standard/src/main/resources/readme.txt @@ -0,0 +1,5 @@ +resources +--------- +Tweakable application configuration files (*.properties) and other resources reside in this directory. + +You may remove this file once you understand the project structure and the purpose of this directory: this file also serves as a "empty directory" placeholder so CVS won't prune the directory. \ No newline at end of file diff --git a/common-build/templates/projects/standard/src/test/java/readme.txt b/common-build/templates/projects/standard/src/test/java/readme.txt new file mode 100644 index 00000000..4a11f99e --- /dev/null +++ b/common-build/templates/projects/standard/src/test/java/readme.txt @@ -0,0 +1,5 @@ +test +------ +Project unit and integration tests reside within this directory. Files here are compiled into classes placed in ${project.dir}/target/test-classes and added to the test classpath. + +You may remove this file once you understand the project structure and the purpose of this directory: this file also serves as a "empty directory" placeholder so CVS won't prune the directory. diff --git a/common-build/templates/projects/webapp/WEB-INF/classes/log4j.properties b/common-build/templates/projects/webapp/WEB-INF/classes/log4j.properties new file mode 100644 index 00000000..5223d5b0 --- /dev/null +++ b/common-build/templates/projects/webapp/WEB-INF/classes/log4j.properties @@ -0,0 +1,19 @@ +log4j.rootCategory=WARN, stdout, logfile + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${@PROJECT_NAME@.root}/@PROJECT_NAME@.log +log4j.appender.logfile.MaxFileSize=512KB + +# Keep three backup files +log4j.appender.logfile.MaxBackupIndex=3 +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout + +#Pattern to output : date priority [category] - line_separator +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n + +# Enable debug interceptor +#log4j.category.org.springframework.aop.interceptor=DEBUG \ No newline at end of file diff --git a/common-build/templates/projects/webapp/WEB-INF/dispatcher-servlet-config.xml b/common-build/templates/projects/webapp/WEB-INF/dispatcher-servlet-config.xml new file mode 100644 index 00000000..d32bf1cd --- /dev/null +++ b/common-build/templates/projects/webapp/WEB-INF/dispatcher-servlet-config.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/common-build/templates/projects/webapp/WEB-INF/web.xml b/common-build/templates/projects/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..8c924b9e --- /dev/null +++ b/common-build/templates/projects/webapp/WEB-INF/web.xml @@ -0,0 +1,41 @@ + + + + + + + contextConfigLocation + + + + + + + + org.springframework.web.context.ContextLoaderListener + + + + @PROJECT_NAME@ + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/dispatcher-servlet-config.xml + + + + + @PROJECT_NAME@ + *.htm + + + \ No newline at end of file diff --git a/common-build/templates/projects/webapp/index.html b/common-build/templates/projects/webapp/index.html new file mode 100644 index 00000000..b37b2a3f --- /dev/null +++ b/common-build/templates/projects/webapp/index.html @@ -0,0 +1,10 @@ + + +Shell + + + + + + + diff --git a/common-build/templates/readme.txt b/common-build/templates/readme.txt new file mode 100644 index 00000000..cd23c818 --- /dev/null +++ b/common-build/templates/readme.txt @@ -0,0 +1,2 @@ +Contained in this directory are useful templates for projects, configuration files, +and Java artifacts for products such as Spring, Spring Web Flow, and log4j. \ No newline at end of file diff --git a/common-build/templates/spring-webflow/FlowExecutionTestTemplate.java b/common-build/templates/spring-webflow/FlowExecutionTestTemplate.java new file mode 100644 index 00000000..a387ed55 --- /dev/null +++ b/common-build/templates/spring-webflow/FlowExecutionTestTemplate.java @@ -0,0 +1,24 @@ +package webflow.templates; + +import java.util.Map; + +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests; +import org.springframework.webflow.test.execution.MockFlowServiceLocator; + +public class FlowExecutionTestTemplate extends AbstractXmlFlowExecutionTests { + + public void testStartFlow() { + + } + + @Override + protected FlowDefinitionResource getFlowDefinitionResource() { + return createFlowDefinitionResource("/path/to/myflow.xml"); + } + + @Override + protected void registerMockServices(MockFlowServiceLocator serviceRegistry) { + + } +} \ No newline at end of file diff --git a/common-build/templates/spring-webflow/flow-definition-1.0-form.xml b/common-build/templates/spring-webflow/flow-definition-1.0-form.xml new file mode 100644 index 00000000..6435e161 --- /dev/null +++ b/common-build/templates/spring-webflow/flow-definition-1.0-form.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/spring-webflow/flow-definition-1.0-simplest.xml b/common-build/templates/spring-webflow/flow-definition-1.0-simplest.xml new file mode 100644 index 00000000..927a309d --- /dev/null +++ b/common-build/templates/spring-webflow/flow-definition-1.0-simplest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/spring-webflow/flow-definition-1.0.xml b/common-build/templates/spring-webflow/flow-definition-1.0.xml new file mode 100644 index 00000000..aa080bea --- /dev/null +++ b/common-build/templates/spring-webflow/flow-definition-1.0.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/spring-webflow/webflow-config-1.0-spring-1.2.xml b/common-build/templates/spring-webflow/webflow-config-1.0-spring-1.2.xml new file mode 100644 index 00000000..77c48d22 --- /dev/null +++ b/common-build/templates/spring-webflow/webflow-config-1.0-spring-1.2.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/spring-webflow/webflow-config-1.0.xml b/common-build/templates/spring-webflow/webflow-config-1.0.xml new file mode 100644 index 00000000..0cb22d0e --- /dev/null +++ b/common-build/templates/spring-webflow/webflow-config-1.0.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/spring-webflow/webflow-form.jsp b/common-build/templates/spring-webflow/webflow-form.jsp new file mode 100644 index 00000000..285f09ca --- /dev/null +++ b/common-build/templates/spring-webflow/webflow-form.jsp @@ -0,0 +1,18 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ + + + +
+ + + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/common-build/templates/spring/bean-definitions-1.2.xml b/common-build/templates/spring/bean-definitions-1.2.xml new file mode 100644 index 00000000..7be11e1c --- /dev/null +++ b/common-build/templates/spring/bean-definitions-1.2.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/common-build/templates/spring/bean-definitions-2.0.xml b/common-build/templates/spring/bean-definitions-2.0.xml new file mode 100644 index 00000000..5ae46de2 --- /dev/null +++ b/common-build/templates/spring/bean-definitions-2.0.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/common-build/templates/tomcat/context.xml b/common-build/templates/tomcat/context.xml new file mode 100644 index 00000000..0aa6e718 --- /dev/null +++ b/common-build/templates/tomcat/context.xml @@ -0,0 +1,4 @@ + + + diff --git a/common-build/tomcat-targets.xml b/common-build/tomcat-targets.xml new file mode 100644 index 00000000..ea1129a0 --- /dev/null +++ b/common-build/tomcat-targets.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Set tomcat.dir in your USER_HOME/build.properties file (create if it doesn't exist) + + + \ No newline at end of file diff --git a/common-build/version.txt b/common-build/version.txt new file mode 100644 index 00000000..27a8d2a9 --- /dev/null +++ b/common-build/version.txt @@ -0,0 +1,13 @@ +version 20060409-1 + +Changelog: +2006-08-25: Keith: updated project and file templates inside "templates" +2006-04-09: Colin: upgrade Ivy to 1.3.1 +2006-03-26: Colin: upgrade Ivy to snapshot 20060322, for transitive dep fix. +2006-03-08: Colin: upgrade Ivy to 1.3RC3 +2006-02-17: Colin: Add retrieve-to-repo to common-targets.xml, user for release procoess +2006-02-13: Arjen: Standard docbook images are now also copied in doc-targets.xml +2006-02-08: Colin: add dir="${basedir} to junit task so it runs ok from other dirs +2006-01-04: Colin: add description element to "retrieve" since it's not an internal target +2005-11-27: Update Spring version in templates +2005-11-20: Arjen: add gen java source dir functionality for test sources too diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..41f85250 --- /dev/null +++ b/pom.xml @@ -0,0 +1,277 @@ + + + 4.0.0 + org.springframework.ldap + spring-ldap + pom + 1.1.1-SNAPSHOT + Spring LDAP + http://www.springframework.org/ldap + + Spring LDAP is a library to simplify LDAP programming in + Java, built on the same principles as Spring JDBC. + + The LdapTemplate class encapsulates all the plumbing work + involved in traditional LDAP programming, such as creating + contexts, looping through NamingEnumerations, handling + Exceptions and cleaning up resources. This leaves the programmer + to handle the important stuff - where to find data (DNs and + Filters) and what to do with it (map to and from domain objects, + bind, modify, unbind, etc.), in the same way that JdbcTemplate + relieves the programmer from everything but the actual SQL and + how the data maps to the domain model. + + In addition to this, LdapTemplate provides Exception translation + from NamingExceptions to DataAccessExceptions, as well as + several utilities for working with filters, LDAP paths and + Attributes. + + + + + + + + JIRA + + http://opensource.atlassian.com/projects/spring/browse/LDAP + + + + + continuum + http://www.purple.se:8787/continuum/ + + + mail + +
ulrik.sandberg@jayway.se
+
+
+ + mail + +
mattias.arthursson@jayway.se
+
+
+
+
+ + + + scm:svn:https://svn.sourceforge.net/svnroot/springframework/spring-projects/trunk/spring-ldap + + + scm:svn:https://svn.sourceforge.net/svnroot/springframework/spring-projects/trunk/spring-ldap + + + http://svn.sourceforge.net/viewcvs.cgi/springframework/spring-projects/trunk/spring-ldap + + + + 2006 + + + Spring Framework + http://www.springframework.org + + + + + ulsa + Ulrik Sandberg + ulrik.sandberg at jayway.se + Jayway AB + http://www.jayway.se + + Project Admin + Developer + + +1 + + + marthursson + Mattias Arthursson + mattias.arthursson at jayway.se + Jayway AB + http://www.jayway.se + + Project Admin + Developer + + +1 + + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + +Copyright 2006 the original author or authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. +See the License for the specific language governing permissions and +limitations under the License. + + + + + + + + + + + spring-ldap + spring-ldap-article + spring-ldap-person + + + + + + junit + junit + 3.8.1 + test + + + + + + + + + + + org.apache.maven.plugins + maven-clover-plugin + + + pre-site + + instrument + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-jxr-plugin + + true + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + true + + + + org.apache.maven.plugins + maven-javadoc-plugin + + true + + + Spring LDAP + org.springframework.ldap* + + + Spring LDAP Person Sample + org.springframework.ldap.samples.person.* + + + + + http://java.sun.com/j2se/1.4.2/docs/api/ + + http://static.springframework.org/spring/docs/2.0.x/api/ + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + org.apache.maven.plugins + maven-clover-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + + + + + + + + + + + + + true + + apache-snapshots + Apache Snapshots + http://cvs.apache.org/maven-snapshot-repository + + + safehaus-repository + Safehaus Repository + http://m2.safehaus.org + + + spring-ext + Spring External Dependencies Repository + + https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/ + + + + + + + + true + + apache.snapshots + Apache Snapshots + http://cvs.apache.org/maven-snapshot-repository/ + + + +
diff --git a/sandbox/.classpath b/sandbox/.classpath new file mode 100644 index 00000000..e1da7745 --- /dev/null +++ b/sandbox/.classpath @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/.project b/sandbox/.project new file mode 100644 index 00000000..d37ee382 --- /dev/null +++ b/sandbox/.project @@ -0,0 +1,34 @@ + + + sandbox + + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.ibm.etools.validation.validationbuilder + + + + + com.ibm.etools.ctc.serviceprojectbuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + com.ibm.etools.ctc.javaprojectnature + + diff --git a/sandbox/.settings/org.eclipse.jdt.core.prefs b/sandbox/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..a923f3d7 --- /dev/null +++ b/sandbox/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,248 @@ +#Sun Jul 02 11:21:34 EDT 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/sandbox/.settings/org.eclipse.jdt.ui.prefs b/sandbox/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000..21ae7c07 --- /dev/null +++ b/sandbox/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Fri Apr 21 13:43:14 CEST 2006 +eclipse.preferences.version=1 +formatter_settings_version=10 diff --git a/sandbox/.springBeans b/sandbox/.springBeans new file mode 100644 index 00000000..f9aa76ca --- /dev/null +++ b/sandbox/.springBeans @@ -0,0 +1,25 @@ + + + + src/iutest/conf/ldapTemplateBaseSuffixTestContext.xml + src/iutest/conf/ldapTemplateTestContext.xml + + + + iutest with base + false + false + + src/iutest/conf/ldapTemplateBaseSuffixTestContext.xml + + + + iutest + false + false + + src/iutest/conf/ldapTemplateTestContext.xml + + + + diff --git a/sandbox/build.xml b/sandbox/build.xml new file mode 100644 index 00000000..fba37e3f --- /dev/null +++ b/sandbox/build.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Unit test report has been generated. +The HTML report is ${target.testresults.html.dir}/index.html + + + + + diff --git a/sandbox/itest-openldap-targets.xml b/sandbox/itest-openldap-targets.xml new file mode 100644 index 00000000..fcee3011 --- /dev/null +++ b/sandbox/itest-openldap-targets.xml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compiling itest-openldap sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Integration test report has been generated. +The HTML report is ${target.itest.openldap.results.html.dir}/index.html + + + + + diff --git a/sandbox/itest-targets.xml b/sandbox/itest-targets.xml new file mode 100644 index 00000000..5f534a10 --- /dev/null +++ b/sandbox/itest-targets.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compiling itest sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Integration test report has been generated. +The HTML report is ${target.itestresults.html.dir}/index.html + + + + + diff --git a/sandbox/ivy.xml b/sandbox/ivy.xml new file mode 100644 index 00000000..ebb1c36d --- /dev/null +++ b/sandbox/ivy.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/project.properties b/sandbox/project.properties new file mode 100644 index 00000000..269a5449 --- /dev/null +++ b/sandbox/project.properties @@ -0,0 +1,14 @@ +# properties defined in this file are overridable by a local build.properties in this project dir + +# The location of the common build system +common.build.dir=${basedir}/../common-build + +project.base.version=1.1.2 +project.version=${project.base.version} +ivy.status=release + +javac.source=1.3 +javac.target=1.3 + +# extend common-build with source capability +main.build.configs=global,buildtime,test,source diff --git a/sandbox/project.xml b/sandbox/project.xml new file mode 100644 index 00000000..6d9b29f2 --- /dev/null +++ b/sandbox/project.xml @@ -0,0 +1,237 @@ + + + 3 + + ldaptemplate + LdapTemplate + ldaptemplate + ldaptemplate + 1.0.2 + http://jira.ddsteps.org/browse/LDT + 2006 + org.springframework.ldap + + <p> + LdapTemplate is a framework to simplify LDAP programming in + Java, built on the same principles as Spring Jdbc. + </p> + <p> + The LdapTemplate class encapsulates all the plumbing work + involved in traditional LDAP programming, such as creating, + looping through NamingEnumerations, handling Exceptions and + cleaning up resources. This leaves the programmer to handle the + important stuff - where to find data (DNs and Filters) and what + to do with it (map to and from domain objects, bind, modify, + unbind, etc.), in the same way that JdbcTemplate relieves the + programmer of all but the actual SQL and how the data maps to + the domain model. + </p> + <p> + In addition to this, LdapTemplate provides Exception translation + from NamingExceptions to DataAccessExceptions, as well as + several utilities for working with filters, LDAP paths and + Attributes. + </p> + + + Java framework for easier LDAP programming + + http://sourceforge.net/projects/ldaptemplate + + + + ldaptemplate-user + http://lists.sourceforge.net/mailman/listinfo/ldaptemplate-user + http://lists.sourceforge.net/mailman/listinfo/ldaptemplate-user + mailto:ldaptemplate-user@lists.sourceforge.net + http://sourceforge.net/mailarchive/forum.php?forum_id=47521 + + + + + Mattias Arthursson + marthursson + mattias-DOT-arthursson-AT-jayway-dot-se + Jayway AB + http://www.jayway.se + 1 + + Project Lead + SourceForge Admin + Committer + + + + Ulrik Sandberg + ulsa + ulrik_DOT_sandberg-AT-jayway_DOT_se + Jayway AB + http://www.jayway.se + 1 + + Project Lead + SourceForge Admin + Committer + + + + + + Gregor Middell + + + + Jayway AB + http://www.jayway.se + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + manual + + + + + junit + junit + 3.8.1 + jar + + + commons-logging + commons-logging + 1.0.4 + jar + + + commons-lang + commons-lang + 2.1 + jar + + + commons-collections + commons-collections + 3.1 + jar + + + easymock + easymock + 1.1 + jar + + + easymock + easymockclassextension + 1.1 + jar + + + springframework + spring-core + 1.2.6 + jar + + + springframework + spring-context + 1.2.6 + jar + + + springframework + spring-beans + 1.2.6 + jar + + + springframework + spring-dao + 1.2.6 + jar + + + cglib + cglib-full + 2.0.1 + jar + + + gsbase + gsbase + 2.0 + jar + + + acegisecurity + acegi-security + 1.0.0-RC2 + jar + + + + mattias.arthursson@jayway.se + src/java + src/test + + + **/*Test.java + + + + src/test + + **/*.dtd + **/*.xls + **/*.xml + **/*.properties + + false + + + + + + src/java + + **/*.dtd + **/*.xml + **/*.properties + **/*.xls + + false + + + src/test + + **/*.dtd + **/*.xml + **/*.properties + **/*.xls + + false + + + + + + maven-changes-plugin + + + maven-faq-plugin + + maven-javadoc-plugin + maven-jdepend-plugin + maven-jcoverage-plugin + maven-junit-report-plugin + maven-jxr-plugin + maven-license-plugin + + + + + + + \ No newline at end of file diff --git a/sandbox/readme.txt b/sandbox/readme.txt new file mode 100644 index 00000000..929d94f8 --- /dev/null +++ b/sandbox/readme.txt @@ -0,0 +1,2 @@ +Sandbox for adding and testing new functionality without disturbing +the production code. diff --git a/sandbox/src/itest-openldap/java/conf/ldap-openldap.properties b/sandbox/src/itest-openldap/java/conf/ldap-openldap.properties new file mode 100644 index 00000000..492339a0 --- /dev/null +++ b/sandbox/src/itest-openldap/java/conf/ldap-openldap.properties @@ -0,0 +1,4 @@ +urls=ldap://127.0.0.1 +userName=cn=Directory Manager +password=netscape +base=o=ikea.com diff --git a/sandbox/src/itest-openldap/java/conf/ldap.conf b/sandbox/src/itest-openldap/java/conf/ldap.conf new file mode 100644 index 00000000..aa4372ea --- /dev/null +++ b/sandbox/src/itest-openldap/java/conf/ldap.conf @@ -0,0 +1,23 @@ +# Start slapd with this file as configuration file: -f ldap.conf +# The first time, fill the database using the load script in +# src/itest/java/setup_data.ldif, like this: +# +# cd \program\openldap +# ldap_add -f ...\src\itest\java\setup_data.ldif -d cn=Manager,dc=jayway,dc=se -W +# +# The password can be seen below + +include "c:/Program/OpenLDAP/schema/core.schema" +include "c:/Program/OpenLDAP/schema/cosine.schema" +include "c:/Program/OpenLDAP/schema/inetorgperson.schema" +database bdb +suffix "dc=jayway,dc=se" +rootdn "cn=Manager,dc=jayway,dc=se" +rootpw secret +directory "c:/Program/OpenLDAP/data" + +TLSCipherSuite HIGH:MEDIUM:+SSLv2 +TLSCACertificateFile /tmp/cacert.pem +TLSCertificateFile /tmp/servercrt.pem +TLSCertificateKeyFile /tmp/serverkey.pem +TLSVerifyClient never diff --git a/sandbox/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml b/sandbox/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml new file mode 100644 index 00000000..c7c22aaa --- /dev/null +++ b/sandbox/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/src/itest-openldap/java/org/springframework/ldap/LdapTemplateVirtualListViewSearchITest.java b/sandbox/src/itest-openldap/java/org/springframework/ldap/LdapTemplateVirtualListViewSearchITest.java new file mode 100644 index 00000000..86352451 --- /dev/null +++ b/sandbox/src/itest-openldap/java/org/springframework/ldap/LdapTemplateVirtualListViewSearchITest.java @@ -0,0 +1,140 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.SearchControls; + +import org.springframework.ldap.support.control.VirtualListViewRequestControl; +import org.springframework.ldap.support.control.VirtualListViewResultsCookie; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the still experimental virtual list view search result capability of + * LdapTemplate. + * + * @author Ulrik Sandberg + */ +public class LdapTemplateVirtualListViewSearchITest extends + AbstractDependencyInjectionSpringContextTests { + + private static final String BASE_STRING = "o=ikea.com"; + + private static final String FILTER_STRING = "(&(objectclass=ikeaperson))"; + + private LdapTemplate tested; + + private CollectingNameClassPairCallbackHandler callbackHandler; + + private SearchControls searchControls; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext-openldap.xml" }; + } + + protected void onSetUp() throws Exception { + super.onSetUp(); + PersonAttributesMapper mapper = new PersonAttributesMapper(); + callbackHandler = tested.new AttributesMapperCallbackHandler(mapper); + searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + } + + protected void onTearDown() throws Exception { + super.onTearDown(); + callbackHandler = null; + tested = null; + searchControls = null; + } + + public void testSearch_VirtualListView() { + Person person; + List list; + VirtualListViewResultsCookie cookie; + VirtualListViewRequestControl requestControl; + + // Prepare for first search + requestControl = new VirtualListViewRequestControl(3); + tested.search(BASE_STRING, FILTER_STRING, searchControls, + callbackHandler, requestControl); + cookie = requestControl.getCookie(); + int listSize = requestControl.getListSize(); + // assertNotNull("Cookie should not be null yet", cookie.getCookie()); + list = callbackHandler.getList(); + assertEquals(3, list.size()); + person = (Person) list.get(0); + assertEquals("A OPER", person.getFullname()); + person = (Person) list.get(1); + assertEquals("aaaa aaaa", person.getFullname()); + person = (Person) list.get(2); + assertEquals("aaab aaab", person.getFullname()); + + // Prepare for position 6000 + requestControl = new VirtualListViewRequestControl(3, 6000, listSize, + cookie); + tested.search(BASE_STRING, FILTER_STRING, searchControls, + callbackHandler, requestControl); + cookie = requestControl.getCookie(); + // assertNull("Cookie should be null now", cookie.getCookie()); + assertEquals(6, list.size()); + person = (Person) list.get(3); + assertEquals("Jessica Santiago Moreno", person.getFullname()); + person = (Person) list.get(4); + assertEquals("Jessica stenfeldt", person.getFullname()); + person = (Person) list.get(5); + assertEquals("Jessica Svensson", person.getFullname()); + + // Prepare for position 93% + requestControl = new VirtualListViewRequestControl(3, 93, listSize, + cookie); + requestControl.setOffsetPercentage(true); + tested.search(BASE_STRING, FILTER_STRING, searchControls, + callbackHandler, requestControl); + cookie = requestControl.getCookie(); + // assertNull("Cookie should be null now", cookie.getCookie()); + assertEquals(9, list.size()); + person = (Person) list.get(6); + assertEquals("Thomas Ronnblom", person.getFullname()); + person = (Person) list.get(7); + assertEquals("Thomas Rosenthal", person.getFullname()); + person = (Person) list.get(8); + assertEquals("Thomas Rydell", person.getFullname()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } + + private class PersonAttributesMapper implements AttributesMapper { + + /** + * Maps the given attributes into a {@link Person} object. + * + * @see org.springframework.ldap.AttributesMapper#mapFromAttributes(javax.naming.directory.Attributes) + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException { + Person person = new Person(); + person.setFullname((String) attributes.get("cn").get()); + person.setLastname((String) attributes.get("sn").get()); + person.setDescription((String) attributes.get("givenName").get()); + return person; + } + } +} diff --git a/sandbox/src/itest/java/conf/apacheDsContext.xml b/sandbox/src/itest/java/conf/apacheDsContext.xml new file mode 100644 index 00000000..f5230c1e --- /dev/null +++ b/sandbox/src/itest/java/conf/apacheDsContext.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + simple + + + ${userName} + + + ${password} + + + + + + + + + + + + + + + + + + + + + objectClass: top + objectClass: domain + objectClass: extensibleObject + dc: jayway + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/src/itest/java/conf/ldap.properties b/sandbox/src/itest/java/conf/ldap.properties new file mode 100644 index 00000000..74163056 --- /dev/null +++ b/sandbox/src/itest/java/conf/ldap.properties @@ -0,0 +1,4 @@ +urls=ldap://127.0.0.1:390 +userName=uid=admin,ou=system +password=secret +base=dc=jayway,dc=se diff --git a/sandbox/src/itest/java/conf/ldapTemplateAcegiTestContext.xml b/sandbox/src/itest/java/conf/ldapTemplateAcegiTestContext.xml new file mode 100644 index 00000000..cf2af0de --- /dev/null +++ b/sandbox/src/itest/java/conf/ldapTemplateAcegiTestContext.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/src/itest/java/conf/ldapTemplateBaseSuffixTestContext.xml b/sandbox/src/itest/java/conf/ldapTemplateBaseSuffixTestContext.xml new file mode 100644 index 00000000..c716a843 --- /dev/null +++ b/sandbox/src/itest/java/conf/ldapTemplateBaseSuffixTestContext.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/src/itest/java/conf/ldapTemplateTestContext.xml b/sandbox/src/itest/java/conf/ldapTemplateTestContext.xml new file mode 100644 index 00000000..2c09f828 --- /dev/null +++ b/sandbox/src/itest/java/conf/ldapTemplateTestContext.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/src/itest/java/log4j.properties b/sandbox/src/itest/java/log4j.properties new file mode 100644 index 00000000..f57302e8 --- /dev/null +++ b/sandbox/src/itest/java/log4j.properties @@ -0,0 +1,9 @@ +log4j.rootCategory=WARN, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +#Enable debug logging +log4j.category.net.sf.ldaptemplate=INFO +log4j.category.net.sf.ldaptemplate.LdapTemplate=DEBUG diff --git a/sandbox/src/itest/java/setup_data.ldif b/sandbox/src/itest/java/setup_data.ldif new file mode 100644 index 00000000..e94d8d4d --- /dev/null +++ b/sandbox/src/itest/java/setup_data.ldif @@ -0,0 +1,71 @@ +dn: c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Sweden +description: The country of Sweden + +dn: c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Norway +description: The country of Norway + +dn: ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Sweden + +dn: ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company2 +description: Second company in Sweden + +dn: ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Norway + +dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person +sn: Person +description: Sweden, Company1, Some Person +telephoneNumber: Some Person Phone + +dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person2 +sn: Person2 +description: Sweden, Company1, Some Person2 +telephoneNumber: Some Person2 Phone + +dn: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person3 +sn: Person3 +description: Sweden, Company1, Some Person3 +telephoneNumber: Some Person3 Phone +userPassword: secretpassword + +dn: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person +sn: Person +description: Sweden, Company2, Some Person +telephoneNumber: Some Person Phone + +dn: cn=Some Person,ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person +sn: Person +description: Norway, Company1, Some Person +telephoneNumber: Some Person Phone + diff --git a/sandbox/src/main/java/org/springframework/ldap/support/ContextSourceTransactionManager.java b/sandbox/src/main/java/org/springframework/ldap/support/ContextSourceTransactionManager.java new file mode 100644 index 00000000..5d27c657 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/ContextSourceTransactionManager.java @@ -0,0 +1,88 @@ +package org.springframework.ldap.support; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.ContextSource; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionException; +import org.springframework.transaction.support.AbstractPlatformTransactionManager; +import org.springframework.transaction.support.DefaultTransactionStatus; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +public class ContextSourceTransactionManager extends + AbstractPlatformTransactionManager { + + private ContextSource contextSource; + + public void setContextSource(ContextSource contextSource) { + this.contextSource = contextSource; + } + + public ContextSource getContextSource() { + return contextSource; + } + + protected Object doGetTransaction() throws TransactionException { + DirContextHolder contextHolder = (DirContextHolder) TransactionSynchronizationManager + .getResource(this.contextSource); + ContextSourceTransactionObject txObject = new ContextSourceTransactionObject( + contextHolder); + return txObject; + } + + protected void doBegin(Object transaction, TransactionDefinition definition) + throws TransactionException { + ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) transaction; + + if (txObject.getContextHolder() == null) { + DirContext newCtx = getContextSource().getReadOnlyContext(); + DirContextHolder contextHolder = new DirContextHolder(newCtx); + + txObject.setContextHolder(contextHolder); + TransactionSynchronizationManager.bindResource(getContextSource(), + contextHolder); + } + } + + protected void doCommit(DefaultTransactionStatus status) + throws TransactionException { + // Nothing much to do here. + } + + protected void doRollback(DefaultTransactionStatus status) + throws TransactionException { + // Perform compensating transaction cleanup using information stored in + // ContextHolder. + } + + protected void doCleanupAfterCompletion(Object transaction) { + ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) transaction; + TransactionSynchronizationManager.unbindResource(contextSource); + DirContext ctx = txObject.getContextHolder().getCtx(); + + try { + ctx.close(); + } catch (NamingException e) { + e.printStackTrace(); + } + } + + static class ContextSourceTransactionObject { + private DirContextHolder contextHolder; + + public ContextSourceTransactionObject(DirContextHolder contextHolder) { + this.contextHolder = contextHolder; + } + + public DirContextHolder getContextHolder() { + return contextHolder; + } + + public void setContextHolder(DirContextHolder contextHolder) { + this.contextHolder = contextHolder; + } + + } + +} diff --git a/sandbox/src/main/java/org/springframework/ldap/support/DirContextHolder.java b/sandbox/src/main/java/org/springframework/ldap/support/DirContextHolder.java new file mode 100644 index 00000000..d54f2086 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/DirContextHolder.java @@ -0,0 +1,21 @@ +package org.springframework.ldap.support; + +import javax.naming.directory.DirContext; + +import org.springframework.transaction.support.ResourceHolderSupport; + +public class DirContextHolder extends ResourceHolderSupport { + private DirContext ctx; + + public void setCtx(DirContext ctx) { + this.ctx = ctx; + } + + public DirContextHolder(DirContext ctx) { + this.ctx = ctx; + } + + public DirContext getCtx() { + return ctx; + } +} diff --git a/sandbox/src/main/java/org/springframework/ldap/support/DirContextProxy.java b/sandbox/src/main/java/org/springframework/ldap/support/DirContextProxy.java new file mode 100644 index 00000000..a694da08 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/DirContextProxy.java @@ -0,0 +1,7 @@ +package org.springframework.ldap.support; + +import javax.naming.directory.DirContext; + +public interface DirContextProxy { + DirContext getTargetContext(); +} diff --git a/sandbox/src/main/java/org/springframework/ldap/support/TlsContextSource.java b/sandbox/src/main/java/org/springframework/ldap/support/TlsContextSource.java new file mode 100644 index 00000000..e933bf9a --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/TlsContextSource.java @@ -0,0 +1,174 @@ +package org.springframework.ldap.support; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.LdapContext; +import javax.naming.ldap.StartTlsRequest; +import javax.naming.ldap.StartTlsResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.support.LdapContextSource; + +/** + * ContextSource implementation which overrides setupAuthenticatedEnvironment to + * allow keystore authentication. + * + * @author Ben Surgison + */ +public class TlsContextSource extends LdapContextSource { + + private static final Log log = LogFactory.getLog(TlsContextSource.class); + + private static final String KEYSTORE = "javax.net.ssl.keyStore"; + + private static final String KEYSTORETYPE = "javax.net.ssl.keyStoreType"; + + private static final String KEYSTOREPASSWORD = "javax.net.ssl.keyStorePassword"; + + private static final String TRUSTSTORE = "javax.net.ssl.trustStore"; + + private static final String TRUSTSTORETYPE = "javax.net.ssl.trustStoreType"; + + private static final String TRUSTSTOREPASSWORD = "javax.net.ssl.trustStorePassword"; + + private String keyStore; + + private String keyStoreType; + + private String keyStorePassword; + + private String trustStore; + + private String trustStoreType; + + private String trustStorePassword; + + /** + * Overridden implementation to allow TLS to be started + */ + public DirContext getReadOnlyContext() { + LdapContext ctx = (LdapContext) super.getReadOnlyContext(); + + // only start tls if keyStore has been set. + if (this.keyStore == null && this.keyStore.length() > 0) { + // Start TLS + StartTlsResponse tls; + try { + tls = (StartTlsResponse) ctx + .extendedOperation(new StartTlsRequest()); + tls.negotiate(); + } catch (NamingException ne) { + log.error(ne.getLocalizedMessage(), ne); + } catch (IOException ioe) { + log.error(ioe.getLocalizedMessage(), ioe); + } + } + return ctx; + } + + /** + * Overridden implementation of setting the environment up to be + * authenticated. This allows a keyStore certificate to be used for SASL + * security. + * + * @param env + * the environment to modify. + */ + protected void setupAuthenticatedEnvironment(Hashtable env) { + + // revert to original if keyStore hasn't been set. + if (this.keyStore == null && this.keyStore.length() > 0) { + super.setupAuthenticatedEnvironment(env); + return; + } + + // Setup keyStore system properties. + System.setProperty(KEYSTORE, getMyQualifiedName(this.keyStore)); + System.setProperty(KEYSTOREPASSWORD, this.keyStorePassword); + System.setProperty(KEYSTORETYPE, getMyKeyStoreType(this.keyStoreType)); + + // Setup trustStore system properties. + System.setProperty(TRUSTSTORE, getMyQualifiedName(this.trustStore)); + System.setProperty(TRUSTSTOREPASSWORD, this.trustStorePassword); + System.setProperty(TRUSTSTORETYPE, + getMyKeyStoreType(this.trustStoreType)); + } + + private String getMyKeyStoreType(String keyStoreType) { + if (keyStoreType != null && keyStoreType.length() > 0) { + return keyStoreType; + } + return KeyStore.getDefaultType(); + } + + private String getMyQualifiedName(String filename) { + String qualifiedName = null; + if (filename.indexOf("/") > -1 || filename.indexOf("\\") > -1) { + qualifiedName = filename; // use full name as entered + } else { + try { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + qualifiedName = classLoader.getResource(filename) + .toExternalForm(); // get full name from classpath + qualifiedName = qualifiedName.substring(6); + } catch (Exception e) { + log.error("Missing file: " + filename, e); + } + } + return qualifiedName; + } + + /** + * @param keyStore + * the keyStore to set + */ + public void setKeyStore(String keyStore) { + + this.keyStore = keyStore; + } + + /** + * @param passPhrase + * the keyStore password to set + */ + public void setKeyStorePassword(String passPhrase) { + this.keyStorePassword = passPhrase; + } + + /** + * @param keyStoreType + * the keyStoreType to set + */ + public void setKeyStoreType(String keyStoreType) { + this.keyStoreType = keyStoreType; + } + + /** + * @param trustStore + * the trustStore to set + */ + public void setTrustStore(String trustStore) { + this.trustStore = trustStore; + } + + /** + * @param trustStorePassword + * the trustStorePassword to set + */ + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + /** + * @param trustStoreType + * the trustStoreType to set + */ + public void setTrustStoreType(String trustStoreType) { + this.trustStoreType = trustStoreType; + } +} diff --git a/sandbox/src/main/java/org/springframework/ldap/support/TransactionAwareContextSourceProxy.java b/sandbox/src/main/java/org/springframework/ldap/support/TransactionAwareContextSourceProxy.java new file mode 100644 index 00000000..9f0e8051 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/TransactionAwareContextSourceProxy.java @@ -0,0 +1,102 @@ +package org.springframework.ldap.support; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.dao.DataAccessException; +import org.springframework.ldap.ContextSource; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +public class TransactionAwareContextSourceProxy implements ContextSource { + + private ContextSource target; + + public TransactionAwareContextSourceProxy(ContextSource target) { + this.target = target; + } + + public DirContext getReadOnlyContext() throws DataAccessException { + DirContextHolder contextHolder = (DirContextHolder) TransactionSynchronizationManager + .getResource(target); + DirContext ctx = null; + + if (contextHolder != null) { + ctx = contextHolder.getCtx(); + } + + if (ctx == null) { + ctx = target.getReadOnlyContext(); + if (contextHolder != null) { + contextHolder.setCtx(ctx); + } + } + return getTransactionAwareDirContextProxy(ctx, target); + } + + private DirContext getTransactionAwareDirContextProxy(DirContext context, + ContextSource target) { + return (DirContext) Proxy + .newProxyInstance(DirContextProxy.class.getClassLoader(), + new Class[] { DirContextProxy.class }, + new TransactionAwareDirContextInvocationHandler( + context, target)); + + } + + public DirContext getReadWriteContext() throws DataAccessException { + throw new UnsupportedOperationException("Not implemented yet"); + } + + static class TransactionAwareDirContextInvocationHandler implements + InvocationHandler { + private DirContext target; + + private ContextSource contextSource; + + public TransactionAwareDirContextInvocationHandler(DirContext target, + ContextSource contextSource) { + this.target = target; + this.contextSource = contextSource; + } + + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + + if (method.getName().equals("getTargetContext")) { + return target; + } else if (method.getName().equals("equals")) { + // Only consider equal when proxies are identical. + return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); + } else if (method.getName().equals("hashCode")) { + // Use hashCode of Connection proxy. + return new Integer(hashCode()); + } else if (method.getName().equals("close")) { + doCloseConnection(target, contextSource); + return null; + } + + try { + return method.invoke(target, args); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + + private void doCloseConnection(DirContext context, + ContextSource contextSource) throws NamingException { + DirContextHolder transactionContextHolder = (DirContextHolder) TransactionSynchronizationManager + .getResource(contextSource); + if (transactionContextHolder == null + || transactionContextHolder.getCtx() != context) { + // This is not the transactional context or the transaction is + // no longer active - we should close it. + context.close(); + } + } + } +} diff --git a/sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewRequestControl.java b/sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewRequestControl.java new file mode 100644 index 00000000..6f06ace1 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewRequestControl.java @@ -0,0 +1,219 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import java.io.IOException; +import java.lang.reflect.Method; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import org.springframework.ldap.DirContextProcessor; +import org.springframework.ldap.UncategorizedLdapException; +import org.springframework.util.ReflectionUtils; + +import com.sun.jndi.ldap.ctl.SortControl; +import com.sun.jndi.ldap.ctl.VirtualListViewControl; +import com.sun.jndi.ldap.ctl.VirtualListViewResponseControl; + +/** + * DirContextProcessor implementation for managing a virtual list view. + * + * @author Ulrik Sandberg + */ +public class VirtualListViewRequestControl implements DirContextProcessor { + + private static final Class DEFAULT_RESPONSE_CONTROL = VirtualListViewResponseControl.class; + + private static final boolean CRITICAL_CONTROL = true; + + private int pageSize; + + private VirtualListViewResultsCookie cookie; + + private int listSize; + + private int targetOffset; + + private NamingException exception; + + private int resultCode; + + private Class responseControlClass = DEFAULT_RESPONSE_CONTROL; + + private boolean offsetPercentage; + + public VirtualListViewRequestControl(int pageSize) { + this(pageSize, 0, 0, null); + } + + public VirtualListViewRequestControl(int pageSize, int targetOffset, + int listSize, VirtualListViewResultsCookie cookie) { + this.pageSize = pageSize; + this.targetOffset = targetOffset; + this.listSize = listSize; + this.cookie = cookie; + } + + public VirtualListViewResultsCookie getCookie() { + return cookie; + } + + public int getPageSize() { + return pageSize; + } + + public int getListSize() { + return listSize; + } + + public NamingException getException() { + return exception; + } + + public int getResultCode() { + return resultCode; + } + + public int getTargetOffset() { + return targetOffset; + } + + /** + * Set the class of the expected ResponseControl for the paged results + * response. The default is {@link VirtualListViewResponseControl}. + * + * @param responseControlClass + * Class of the expected response control. + */ + public void setResponseControlClass(Class responseControlClass) { + this.responseControlClass = responseControlClass; + } + + public void setOffsetPercentage(boolean isPercentage) { + this.offsetPercentage = isPercentage; + } + + public void preProcess(DirContext ctx) throws NamingException { + LdapContext ldapContext; + if (ctx instanceof LdapContext) { + ldapContext = (LdapContext) ctx; + } else { + throw new IllegalArgumentException( + "Request Control operations require LDAPv3 - " + + "Context must be of type LdapContext"); + } + + Control[] requestControls = ldapContext.getRequestControls(); + Control newControl = createRequestControl(); + + Control[] newControls = new Control[requestControls.length + 2]; + for (int i = 0; i < requestControls.length; i++) { + newControls[i] = requestControls[i]; + } + + SortControl sortControl; + try { + sortControl = new SortControl(new String[] { "cn" }, true); + } catch (IOException e) { + throw new UncategorizedLdapException("Couldn't create SortControl", + e); + } + // Add the new Controls at the end of the array. + newControls[newControls.length - 2] = sortControl; + newControls[newControls.length - 1] = newControl; + + ldapContext.setRequestControls(newControls); + } + + /* + * @see org.springframework.ldap.support.control.AbstractRequestControlDirContextProcessor#createRequestControl() + */ + public Control createRequestControl() { + try { + VirtualListViewControl virtualListViewControl; + if (offsetPercentage) { + virtualListViewControl = new VirtualListViewControl( + targetOffset, pageSize, CRITICAL_CONTROL); + } else { + virtualListViewControl = new VirtualListViewControl( + targetOffset, listSize, 0, pageSize - 1, + CRITICAL_CONTROL); + } + if (cookie != null) { + virtualListViewControl.setContextID(cookie.getCookie()); + } + return virtualListViewControl; + } catch (IOException e) { + throw new UncategorizedLdapException( + "Error creating VirtualListViewControl", e); + } + } + + /* + * @see org.springframework.ldap.DirContextProcessor#postProcess(javax.naming.directory.DirContext) + */ + public void postProcess(DirContext ctx) throws NamingException { + LdapContext ldapContext = (LdapContext) ctx; + Control[] responseControls = ldapContext.getResponseControls(); + + // Go through response controls and get info, regardless of class + for (int i = 0; i < responseControls.length; i++) { + Control responseControl = responseControls[i]; + + // check for match + if (isVirtualListViewResponseControl(responseControl)) { + Object control = responseControl; + byte[] result = (byte[]) invokeMethod("getContextID", + responseControlClass, control); + this.cookie = new VirtualListViewResultsCookie(result); + Integer wrapper = (Integer) invokeMethod("getListSize", + responseControlClass, control); + this.listSize = wrapper.intValue(); + wrapper = (Integer) invokeMethod("getTargetOffset", + responseControlClass, control); + this.targetOffset = wrapper.intValue(); + wrapper = (Integer) invokeMethod("getResultCode", + responseControlClass, control); + this.resultCode = wrapper.intValue(); + this.exception = (NamingException) invokeMethod("getException", + responseControlClass, control); + } + } + } + + /** + * Check if the given control matches a paged results response control. + * + * @param responseControl + * the control to check for a match + * @return whether the control is a paged results response control + */ + private boolean isVirtualListViewResponseControl(Control responseControl) { + if (responseControl.getClass().isAssignableFrom(responseControlClass)) { + return true; + } + return false; + } + + private Object invokeMethod(String method, Class clazz, Object control) { + Method m = ReflectionUtils.findMethod(clazz, method, new Class[0]); + return ReflectionUtils.invokeMethod(m, control); + } +} diff --git a/sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewResultsCookie.java b/sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewResultsCookie.java new file mode 100644 index 00000000..d457721a --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ldap/support/control/VirtualListViewResultsCookie.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import com.sun.jndi.ldap.ctl.VirtualListViewControl; + +/** + * Wrapper class for the cookie returned when using the + * {@link VirtualListViewControl}. + * + * @author Ulrik Sandberg + */ +public class VirtualListViewResultsCookie { + + private byte[] cookie; + + /** + * Constructor. + * + * @param cookie + * the cookie returned by a VirtualListViewResponseControl. + */ + public VirtualListViewResultsCookie(byte[] cookie) { + this.cookie = cookie; + } + + /** + * Get the cookie. + * + * @return the cookie. + */ + public byte[] getCookie() { + return cookie; + } +} diff --git a/sandbox/src/test/java/org/springframework/ldap/support/ContextSourceTransactionManagerTest.java b/sandbox/src/test/java/org/springframework/ldap/support/ContextSourceTransactionManagerTest.java new file mode 100644 index 00000000..d59d8a55 --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ldap/support/ContextSourceTransactionManagerTest.java @@ -0,0 +1,127 @@ +package org.springframework.ldap.support; + +import javax.naming.directory.DirContext; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.support.ContextSourceTransactionManager.ContextSourceTransactionObject; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +public class ContextSourceTransactionManagerTest extends TestCase { + + private MockControl contextSourceControl; + + private ContextSource contextSourceMock; + + private MockControl contextControl; + + private DirContext contextMock; + + private ContextSourceTransactionManager tested; + + private MockControl transactionDefinitionControl; + + private TransactionDefinition transactionDefinitionMock; + + protected void setUp() throws Exception { + super.setUp(); + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.clearSynchronization(); + } + + contextSourceControl = MockControl.createControl(ContextSource.class); + contextSourceMock = (ContextSource) contextSourceControl.getMock(); + + contextControl = MockControl.createControl(DirContext.class); + contextMock = (DirContext) contextControl.getMock(); + + transactionDefinitionControl = MockControl + .createControl(TransactionDefinition.class); + transactionDefinitionMock = (TransactionDefinition) transactionDefinitionControl + .getMock(); + + tested = new ContextSourceTransactionManager(); + tested.setContextSource(contextSourceMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + contextControl = null; + contextMock = null; + + contextSourceControl = null; + contextSourceMock = null; + + transactionDefinitionControl = null; + transactionDefinitionMock = null; + + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.clearSynchronization(); + } + } + + public void testDoGetTransaction() { + Object result = tested.doGetTransaction(); + + assertNotNull(result); + assertTrue(result instanceof ContextSourceTransactionObject); + ContextSourceTransactionObject transactionObject = (ContextSourceTransactionObject) result; + assertNull(transactionObject.getContextHolder()); + } + + public void testDoGetTransactionTransactionActive() { + DirContextHolder expectedContextHolder = new DirContextHolder(null); + TransactionSynchronizationManager.bindResource(contextSourceMock, + expectedContextHolder); + Object result = tested.doGetTransaction(); + + assertSame(expectedContextHolder, + ((ContextSourceTransactionObject) result).getContextHolder()); + } + + public void testDoBegin() { + contextSourceControl.expectAndReturn(contextSourceMock + .getReadOnlyContext(), contextMock); + + contextSourceControl.replay(); + + ContextSourceTransactionObject expectedTransactionObject = new ContextSourceTransactionObject( + null); + tested.doBegin(expectedTransactionObject, transactionDefinitionMock); + + contextSourceControl.verify(); + + DirContextHolder foundContextHolder = (DirContextHolder) TransactionSynchronizationManager + .getResource(contextSourceMock); + assertSame(contextMock, foundContextHolder.getCtx()); + } + + public void testDoCommit() { + } + + public void testDoRollback() { + fail("Not yet implemented"); + } + + public void testDoCleanupAfterCompletion() throws Exception { + DirContextHolder expectedContextHolder = new DirContextHolder( + contextMock); + TransactionSynchronizationManager.bindResource(contextSourceMock, + expectedContextHolder); + + contextMock.close(); + contextControl.replay(); + + tested.doCleanupAfterCompletion(new ContextSourceTransactionObject( + expectedContextHolder)); + + contextControl.verify(); + assertNull(TransactionSynchronizationManager + .getResource(contextSourceMock)); + + } +} diff --git a/spring-ldap-article/.classpath b/spring-ldap-article/.classpath new file mode 100644 index 00000000..c373756d --- /dev/null +++ b/spring-ldap-article/.classpath @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-article/.project b/spring-ldap-article/.project new file mode 100644 index 00000000..91947d81 --- /dev/null +++ b/spring-ldap-article/.project @@ -0,0 +1,23 @@ + + + spring-ldap-article + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + + diff --git a/spring-ldap-article/.settings/org.eclipse.jdt.core.prefs b/spring-ldap-article/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..c9f85173 --- /dev/null +++ b/spring-ldap-article/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,260 @@ +#Fri Apr 21 13:43:15 CEST 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=20 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=36 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=36 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=36 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=36 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=20 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=36 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=3 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=3 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=3 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=50 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=3 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/spring-ldap-article/.settings/org.eclipse.jdt.ui.prefs b/spring-ldap-article/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000..0aeb6ebf --- /dev/null +++ b/spring-ldap-article/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,4 @@ +#Fri Apr 21 13:43:14 CEST 2006 +eclipse.preferences.version=1 +formatter_settings_version=10 +org.eclipse.jdt.ui.text.custom_code_templates=\r\n diff --git a/spring-ldap-article/.springBeans b/spring-ldap-article/.springBeans new file mode 100644 index 00000000..4919751a --- /dev/null +++ b/spring-ldap-article/.springBeans @@ -0,0 +1,16 @@ + + + + src/iutest/config/testContext.xml + + + + default + false + false + + src/iutest/config/testContext.xml + + + + diff --git a/spring-ldap-article/build.xml b/spring-ldap-article/build.xml new file mode 100644 index 00000000..5a85b7fa --- /dev/null +++ b/spring-ldap-article/build.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-article/docs/base_data.ldif b/spring-ldap-article/docs/base_data.ldif new file mode 100644 index 00000000..f06390db --- /dev/null +++ b/spring-ldap-article/docs/base_data.ldif @@ -0,0 +1,9 @@ +dn: dc=jayway,dc=se +objectclass: dcObject +objectclass: organization +o: jayway +dc: jayway + +dn: cn=Manager,dc=jayway,dc=se +objectclass:organizationalRole +cn: Manager diff --git a/spring-ldap-article/docs/ldap.conf.example b/spring-ldap-article/docs/ldap.conf.example new file mode 100644 index 00000000..3e7570c5 --- /dev/null +++ b/spring-ldap-article/docs/ldap.conf.example @@ -0,0 +1,21 @@ +# +# LDAP Defaults +# + +# See ldap.conf(5) for details +# This file should be world readable but not world writable. + +#BASE dc=example, dc=com +#URI ldap://ldap.example.com ldap://ldap-master.example.com:666 + +#SIZELIMIT 12 +#TIMELIMIT 15 +#DEREF never + +include "[open_ldap_path]/schema/core.schema" +#include "c:/Program Files/OpenLDAP/schema/inetorgperson.schema" +database bdb +suffix "dc=jayway,dc=se" +rootdn "cn=Manager,dc=jayway,dc=se" +rootpw secret +directory "[open_ldap_path]/data" diff --git a/spring-ldap-article/docs/readme.txt b/spring-ldap-article/docs/readme.txt new file mode 100644 index 00000000..651f41f3 --- /dev/null +++ b/spring-ldap-article/docs/readme.txt @@ -0,0 +1,52 @@ +LDAP server setup for samples. + +We need to semi-manually set up the server environment. I have used +OpenLDAP (http://www.openldap.org/) with a minimal amount of data set up from an +LDIF file. + +There is a Windows version of OpenLDAP available at: + + http://lucas.bergmans.us/hacks/openldap/ + +The LDIF file and sample application both expect to find the base suffix +"dc=jayway,dc=se" in the LDAP Server. + +For help in setting up the LDAP environment, three files are supplied: +1. ldap.conf.example + Modify paths in this file to suit your installation by replacing + the placeholder [open_ldap_path]. +2. base_data.ldif + Base domain and Admin data as specified in ldap.conf. +3. setup_data.ldif + The data expected by the integration test cases. + +Start the LDAP Server: +slapd -d 1 -f ldap.conf.example + +Add the LDIF files (the default password in ldap.conf.example is "secret"): +ldapadd -x -D "cn=Manager,dc=jayway,dc=se" -W -f base_data.ldif +ldapadd -x -D "cn=Manager,dc=jayway,dc=se" -W -f setup_data.ldif + +Verify the installation by running this search: + +ldapsearch -LLL -b dc=jayway,dc=se "(objectclass=*)" dn + +It should result in a list that looks like this: + +dn: dc=jayway,dc=se + +dn: cn=Manager,dc=jayway,dc=se + +dn: c=Sweden,dc=jayway,dc=se + +dn: c=Norway,dc=jayway,dc=se +... + +You should now be all set to run the integration tests. + +If you choose to run the tests on another instance, or specifically with +another suffix than the one mentioned above, you may need to modify data in +the following files: + +setup_data.ldif +/src/iutest/config/ldap.properties diff --git a/spring-ldap-article/docs/setup_data.ldif b/spring-ldap-article/docs/setup_data.ldif new file mode 100644 index 00000000..cdf07c46 --- /dev/null +++ b/spring-ldap-article/docs/setup_data.ldif @@ -0,0 +1,70 @@ +dn: c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Sweden +description: The country of Sweden + +dn: c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Norway +description: The country of Norway + +dn: ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Sweden + +dn: ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company2 +description: Second company in Sweden + +dn: ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Norway + +dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person +sn: Person +description: Sweden, Company1, Some Person +telephoneNumber: +46 555-123456 + +dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person2 +sn: Person2 +description: Sweden, Company1, Some Person2 +telephoneNumber: +46 555-654321 + +dn: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person3 +sn: Person3 +description: Sweden, Company1, Some Person3 +telephoneNumber: +46 555-123654 + +dn: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person +sn: Person +description: Sweden, Company2, Some Person +telephoneNumber: +46 555-456321 + +dn: cn=Some Person,ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: person +cn: Some Person +sn: Person +description: Norway, Company1, Some Person +telephoneNumber: +45 555-654123 + diff --git a/spring-ldap-article/docs/teardown_data.ldif b/spring-ldap-article/docs/teardown_data.ldif new file mode 100644 index 00000000..97ba7e6b --- /dev/null +++ b/spring-ldap-article/docs/teardown_data.ldif @@ -0,0 +1,3 @@ +c=Sweden,dc=jayway,dc=se + +c=Norway,dc=jayway,dc=se diff --git a/spring-ldap-article/ivy.xml b/spring-ldap-article/ivy.xml new file mode 100644 index 00000000..1426550c --- /dev/null +++ b/spring-ldap-article/ivy.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-article/pom.xml b/spring-ldap-article/pom.xml new file mode 100644 index 00000000..470bad64 --- /dev/null +++ b/spring-ldap-article/pom.xml @@ -0,0 +1,84 @@ + + + + spring-ldap + org.springframework.ldap + 1.1.1-SNAPSHOT + + 4.0.0 + org.springframework + spring-ldap-person-article + Spring LDAP Article Source Code Sample + 1.1.1-SNAPSHOT + + Example code that matches the article published on java.net + on April 18, 2006. + + + + + + commons-lang + commons-lang + 2.1 + + + commons-collections + commons-collections + 3.1 + provided + + + javax.servlet + servlet-api + 2.4 + + + + org.springframework + spring-ldap + 1.1.1-SNAPSHOT + + + org.springframework + spring-web + 2.0 + + + org.springframework + spring-webmvc + 2.0 + + + org.springframework + spring-jdbc + 2.0 + + + org.springframework + spring-remoting + 2.0 + + + org.springframework + spring-support + 2.0 + + + + org.springframework + spring-mock + 2.0 + test + + + + + src/itest/java + + + src/itest/java + + + + diff --git a/spring-ldap-article/project.properties b/spring-ldap-article/project.properties new file mode 100644 index 00000000..5e43e378 --- /dev/null +++ b/spring-ldap-article/project.properties @@ -0,0 +1,10 @@ +# properties defined in this file are overridable by a local build.properties in this project dir + +# The location of the common build system +common.build.dir=${basedir}/../common-build + +javac.source=1.3 +javac.target=1.3 + +# extend common-build with source capability +main.build.configs=global,buildtime,test,source diff --git a/spring-ldap-article/readme.txt b/spring-ldap-article/readme.txt new file mode 100644 index 00000000..93ae89cc --- /dev/null +++ b/spring-ldap-article/readme.txt @@ -0,0 +1 @@ +For setup instructions on how to run this sample project, see docs/readme.txt. \ No newline at end of file diff --git a/spring-ldap-article/src/itest/java/config/ldap.properties b/spring-ldap-article/src/itest/java/config/ldap.properties new file mode 100644 index 00000000..ddd65ea4 --- /dev/null +++ b/spring-ldap-article/src/itest/java/config/ldap.properties @@ -0,0 +1,4 @@ +urls=ldap://127.0.0.1 +userName=cn=Manager,dc=jayway,dc=se +password=secret +base=dc=jayway,dc=se diff --git a/spring-ldap-article/src/itest/java/config/testContext.xml b/spring-ldap-article/src/itest/java/config/testContext.xml new file mode 100644 index 00000000..7b54db0a --- /dev/null +++ b/spring-ldap-article/src/itest/java/config/testContext.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/AbstractPersonDaoIntegrationTest.java b/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/AbstractPersonDaoIntegrationTest.java new file mode 100644 index 00000000..35e2cdc7 --- /dev/null +++ b/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/AbstractPersonDaoIntegrationTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.dao; + +import java.util.List; + + +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.ldap.samples.article.dao.PersonDao; +import org.springframework.ldap.samples.article.domain.Person; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Abstract base class for PersonDao integration tests. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public abstract class AbstractPersonDaoIntegrationTest + extends + AbstractDependencyInjectionSpringContextTests { + + protected Person person; + + protected PersonDao personDao; + + protected String[] getConfigLocations() { + return new String[] { "config/testContext.xml" }; + } + + protected void onSetUp() throws Exception { + super.onSetUp(); + person = new Person(); + person.setCountry("Sweden"); + person.setCompany("company1"); + person.setFullName("Some Person"); + person.setLastName("Person"); + person + .setDescription("Sweden, Company1, Some Person"); + person.setPhone("+46 555-123456"); + } + + protected void onTearDown() throws Exception { + super.onTearDown(); + person = null; + personDao = null; + } + + /** + * Having a single test method test create, update and delete is not exactly + * the ideal way of testing, since they depend on each other. A better way + * would be to separate the tests and load a test fixture before each + * operation, in order to guarantee the expected state every time. See the + * ldaptemplate-person sample for the correct way to do this. + */ + public void testCreateUpdateDelete() { + try { + person.setFullName("Another Person"); + personDao.create(person); + personDao.findByPrimaryKey( + "Sweden", "company1", + "Another Person"); + // if we got here, create succeeded + + person + .setDescription("Another description"); + personDao.update(person); + Person result = personDao + .findByPrimaryKey( + "Sweden", "company1", + "Another Person"); + assertEquals( + "Another description", result + .getDescription()); + } finally { + personDao.delete(person); + try { + personDao.findByPrimaryKey( + "Sweden", "company1", + "Another Person"); + fail("DataRetrievalFailureException expected"); + } catch (DataRetrievalFailureException expected) { + // expected + } + } + } + + public void testGetAllPersonNames() { + List result = personDao.getAllPersonNames(); + assertEquals(5, result.size()); + String first = (String) result.get(0); + assertEquals("Some Person", first); + } + + public void testFindAll() { + List result = personDao.findAll(); + assertEquals(5, result.size()); + Person first = (Person) result.get(0); + assertEquals("Some Person", first + .getFullName()); + } + + public void testFindByPrimaryKey() { + Person result = personDao.findByPrimaryKey( + "Sweden", "company1", "Some Person"); + assertEquals(person, result); + } +} diff --git a/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/PersonDaoImplIntegrationTest.java b/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/PersonDaoImplIntegrationTest.java new file mode 100644 index 00000000..90a42d5e --- /dev/null +++ b/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/PersonDaoImplIntegrationTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.dao; + +import org.springframework.ldap.samples.article.dao.PersonDaoImpl; + +/** + * Integration tests for the PersonDaoImpl class. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PersonDaoImplIntegrationTest extends + AbstractPersonDaoIntegrationTest { + + public void setPersonDao( + PersonDaoImpl personDao) { + this.personDao = personDao; + } +} diff --git a/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImplIntegrationTest.java b/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImplIntegrationTest.java new file mode 100644 index 00000000..cded43b4 --- /dev/null +++ b/spring-ldap-article/src/itest/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImplIntegrationTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.dao; + +import org.springframework.ldap.samples.article.dao.TraditionalPersonDaoImpl; + +/** + * Integration tests for the TraditionalPersonDaoImpl class. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class TraditionalPersonDaoImplIntegrationTest + extends AbstractPersonDaoIntegrationTest { + + public void setPersonDao( + TraditionalPersonDaoImpl personDao) { + this.personDao = personDao; + } +} diff --git a/spring-ldap-article/src/main/java/log4j.properties b/spring-ldap-article/src/main/java/log4j.properties new file mode 100644 index 00000000..4ab57157 --- /dev/null +++ b/spring-ldap-article/src/main/java/log4j.properties @@ -0,0 +1,19 @@ +log4j.rootCategory=INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${ldaptemplate.root}/ldaptemplate.log +log4j.appender.logfile.MaxFileSize=512KB + +# Keep three backup files +log4j.appender.logfile.MaxBackupIndex=3 +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout + +#Pattern to output : date priority [category] - line_separator +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n + +#Enable debug logging +#log4j.category.net.sf.ldaptemplate=DEBUG diff --git a/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDao.java b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDao.java new file mode 100644 index 00000000..b4351d79 --- /dev/null +++ b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDao.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.dao; + +import java.util.List; + +import org.springframework.ldap.samples.article.domain.Person; + + +/** + * Data Access Object interface for the Person entity. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface PersonDao { + void create(Person person); + + void update(Person person); + + void delete(Person person); + + List getAllPersonNames(); + + List findAll(); + + Person findByPrimaryKey(String country, + String company, String fullname); +} diff --git a/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDaoImpl.java b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDaoImpl.java new file mode 100644 index 00000000..752ec260 --- /dev/null +++ b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/PersonDaoImpl.java @@ -0,0 +1,198 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.dao; + +import java.util.List; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.springframework.ldap.samples.article.domain.Person; + +import org.springframework.ldap.AttributesMapper; +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.ldap.support.filter.EqualsFilter; + +/** + * Default implementation of PersonDao. This implementation uses + * DirContextAdapter for managing attribute values. It has been specified in the + * Spring Context that the DirObjectFactory should be used when creating objects + * from contexts, which defaults to creating DirContextAdapter objects. This + * means that we can use a ContextMapper to map from the found contexts to our + * domain objects. This is especially useful since we in this case have + * properties in our domain objects that depend on parts of the DN. + * + * We could have worked with Attributes and an AttributesMapper implementation + * instead, but working with Attributes is a bore and also, working with + * AttributesMapper objects (or, indeed Attributes) does not give us access to + * the distinguished name. However, we do use it in one method that only needs a + * single attribute: {@link #getAllPersonNames()}. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PersonDaoImpl implements PersonDao { + + private LdapTemplate ldapTemplate; + + /* + * @see PersonDao#create(Person) + */ + public void create(Person person) { + Name dn = buildDn(person); + DirContextAdapter context = new DirContextAdapter( + dn); + mapToContext(person, context); + ldapTemplate.bind(dn, context, null); + } + + /* + * @see PersonDao#update(Person) + */ + public void update(Person person) { + Name dn = buildDn(person); + DirContextAdapter context = (DirContextAdapter) ldapTemplate + .lookup(dn); + mapToContext(person, context); + ldapTemplate.modifyAttributes(dn, context + .getModificationItems()); + } + + /* + * @see PersonDao#delete(Person) + */ + public void delete(Person person) { + ldapTemplate.unbind(buildDn(person)); + } + + /* + * @see PersonDao#getAllPersonNames() + */ + public List getAllPersonNames() { + EqualsFilter filter = new EqualsFilter( + "objectclass", "person"); + return ldapTemplate.search( + DistinguishedName.EMPTY_PATH, filter + .encode(), new AttributesMapper() { + public Object mapFromAttributes( + Attributes attrs) + throws NamingException { + return attrs.get("cn").get(); + } + }); + } + + /* + * @see PersonDao#findAll() + */ + public List findAll() { + EqualsFilter filter = new EqualsFilter( + "objectclass", "person"); + return ldapTemplate.search( + DistinguishedName.EMPTY_PATH, filter + .encode(), getContextMapper()); + } + + /* + * @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String, + * java.lang.String) + */ + public Person findByPrimaryKey(String country, + String company, String fullname) { + DistinguishedName dn = buildDn( + country, company, fullname); + return (Person) ldapTemplate.lookup( + dn, getContextMapper()); + } + + private ContextMapper getContextMapper() { + return new PersonContextMapper(); + } + + private DistinguishedName buildDn(Person person) { + return buildDn(person.getCountry(), person + .getCompany(), person.getFullName()); + } + + private DistinguishedName buildDn( + String country, String company, + String fullname) { + DistinguishedName dn = new DistinguishedName(); + dn.add("c", country); + dn.add("ou", company); + dn.add("cn", fullname); + return dn; + } + + private void mapToContext(Person person, + DirContextAdapter context) { + context.setAttributeValues( + "objectclass", new String[] { "top", + "person" }); + context.setAttributeValue("cn", person + .getFullName()); + context.setAttributeValue("sn", person + .getLastName()); + context.setAttributeValue( + "description", person.getDescription()); + context.setAttributeValue( + "telephoneNumber", person.getPhone()); + } + + /** + * Maps from DirContextAdapter to Person objects. A DN for a person will be + * of the form cn=[fullname],ou=[company],c=[country], so the + * values of these attributes must be extracted from the DN. For this, we use + * the DistinguishedName. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + private static class PersonContextMapper + implements ContextMapper { + + public Object mapFromContext(Object ctx) { + DirContextAdapter context = (DirContextAdapter) ctx; + DistinguishedName dn = new DistinguishedName( + context.getDn()); + Person person = new Person(); + person.setCountry(dn + .getLdapRdn(0).getComponent().getValue()); + person.setCompany(dn + .getLdapRdn(1).getComponent().getValue()); + person.setFullName(context + .getStringAttribute("cn")); + person.setLastName(context + .getStringAttribute("sn")); + person.setDescription(context + .getStringAttribute("description")); + person + .setPhone(context + .getStringAttribute("telephoneNumber")); + + return person; + } + } + + public void setLdapTemplate( + LdapTemplate ldapTemplate) { + this.ldapTemplate = ldapTemplate; + } +} diff --git a/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImpl.java b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImpl.java new file mode 100644 index 00000000..c9a3473e --- /dev/null +++ b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/dao/TraditionalPersonDaoImpl.java @@ -0,0 +1,385 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.dao; + +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; + +import javax.naming.Context; +import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + + +import org.apache.commons.lang.StringUtils; +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.ldap.samples.article.domain.Person; + +/** + * Traditional implementation of PersonDao. This implementation uses the basic + * JNDI interfaces and classes {@link DirContext}, {@link Attributes}, + * {@link Attribute}, and {@link NamingEnumeration}. The purpose is to + * contrast this implementation with that of {@link PersonDaoImpl}. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class TraditionalPersonDaoImpl implements + PersonDao { + + private String userName; + + private String password; + + private String url; + + private String base; + + /* + * @see PersonDao#create(Person) + */ + public void create(Person person) { + DirContext ctx = createAuthenticatedContext(); + String dn = buildDn(person); + try { + Attributes attrs = getAttributesToBind(person); + ctx.bind(dn, null, attrs); + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + } + + /* + * @see PersonDao#update(Person) + */ + public void update(Person person) { + DirContext ctx = createAuthenticatedContext(); + String dn = buildDn(person); + try { + ctx + .rebind( + dn, null, + getAttributesToBind(person)); + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + } + + /* + * @see PersonDao#delete(Person) + */ + public void delete(Person person) { + DirContext ctx = createAuthenticatedContext(); + String dn = buildDn(person); + try { + ctx.unbind(dn); + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + } + + /* + * @see PersonDao#getAllPersonNames() + */ + public List getAllPersonNames() { + DirContext ctx = createAnonymousContext(); + + LinkedList list = new LinkedList(); + NamingEnumeration results = null; + try { + SearchControls controls = new SearchControls(); + controls + .setSearchScope(SearchControls.SUBTREE_SCOPE); + results = ctx.search( + "", "(objectclass=person)", controls); + + while (results.hasMore()) { + SearchResult searchResult = (SearchResult) results + .next(); + Attributes attributes = searchResult + .getAttributes(); + Attribute attr = attributes.get("cn"); + String cn = (String) attr.get(); + list.add(cn); + } + } catch (NameNotFoundException e) { + // The base context was not found. + // Just clean up and exit. + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + return list; + } + + /* + * @see PersonDao#findAll() + */ + public List findAll() { + DirContext ctx = createAnonymousContext(); + + LinkedList list = new LinkedList(); + NamingEnumeration results = null; + try { + SearchControls controls = new SearchControls(); + controls + .setSearchScope(SearchControls.SUBTREE_SCOPE); + results = ctx.search( + "", "(objectclass=person)", controls); + + while (results.hasMore()) { + SearchResult searchResult = (SearchResult) results + .next(); + String dn = searchResult.getName(); + Attributes attributes = searchResult + .getAttributes(); + list.add(mapToPerson(dn, attributes)); + } + } catch (NameNotFoundException e) { + // The base context was not found, which basically means + // that the search did not return any results. Just clean up and + // exit. + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + return list; + } + + /* + * @see PersonDao#findByPrimaryKey(java.lang.String, java.lang.String, + * java.lang.String) + */ + public Person findByPrimaryKey(String country, + String company, String fullname) { + + DirContext ctx = createAnonymousContext(); + String dn = buildDn( + country, company, fullname); + try { + Attributes attributes = ctx + .getAttributes(dn); + return mapToPerson(dn, attributes); + } catch (NameNotFoundException e) { + throw new DataRetrievalFailureException( + "Did not find entry with primary key '" + + dn + "'", e); + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + } + + private String buildDn(Person person) { + return buildDn(person.getCountry(), person + .getCompany(), person.getFullName()); + } + + private String buildDn(String country, String company, + String fullname) { + StringBuffer sb = new StringBuffer(); + sb.append("cn="); + sb.append(fullname); + sb.append(", "); + sb.append("ou="); + sb.append(company); + sb.append(", "); + sb.append("c="); + sb.append(country); + String dn = sb.toString(); + return dn; + } + + private DirContext createContext(Hashtable env) { + env.put( + Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + String tempUrl = createUrl(); + env.put(Context.PROVIDER_URL, tempUrl); + DirContext ctx; + try { + ctx = new InitialDirContext(env); + } catch (NamingException e) { + throw new RuntimeException(e); + } + return ctx; + } + + private DirContext createAnonymousContext() { + Hashtable env = new Hashtable(); + return createContext(env); + } + + private DirContext createAuthenticatedContext() { + Hashtable env = new Hashtable(); + env.put( + Context.SECURITY_AUTHENTICATION, + "simple"); + env.put( + Context.SECURITY_PRINCIPAL, userName); + env.put( + Context.SECURITY_CREDENTIALS, password); + return createContext(env); + } + + private Attributes getAttributesToBind( + Person person) { + Attributes attrs = new BasicAttributes(); + BasicAttribute ocattr = new BasicAttribute( + "objectclass"); + ocattr.add("top"); + ocattr.add("person"); + attrs.put(ocattr); + attrs.put("cn", person.getFullName()); + attrs.put("sn", person.getLastName()); + attrs.put("description", person + .getDescription()); + attrs.put("telephoneNumber", person + .getPhone()); + return attrs; + } + + private Person mapToPerson(String dn, + Attributes attributes) + throws NamingException { + Person person = new Person(); + person.setFullName((String) attributes.get( + "cn").get()); + person.setLastName((String) attributes.get( + "sn").get()); + person.setDescription((String) attributes + .get("description").get()); + person.setPhone((String) attributes.get( + "telephoneNumber").get()); + + // Remove any trailing spaces after comma + String cleanedDn = dn + .replaceAll(", *", ","); + + String countryMarker = ",c="; + int countryIndex = cleanedDn + .lastIndexOf(countryMarker); + + String companyMarker = ",ou="; + int companyIndex = cleanedDn + .lastIndexOf(companyMarker); + + String country = cleanedDn + .substring(countryIndex + + countryMarker.length()); + person.setCountry(country); + String company = cleanedDn.substring( + companyIndex + companyMarker.length(), + countryIndex); + person.setCompany(company); + return person; + } + + private String createUrl() { + String tempUrl = url; + if (!tempUrl.endsWith("/")) { + tempUrl += "/"; + } + if (StringUtils.isNotEmpty(base)) { + tempUrl += base; + } + return tempUrl; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setBase(String base) { + this.base = base; + } + + public void setPassword(String credentials) { + this.password = credentials; + } + + public void setUserName(String principal) { + this.userName = principal; + } +} diff --git a/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/domain/Person.java b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/domain/Person.java new file mode 100644 index 00000000..e6e8b8f2 --- /dev/null +++ b/spring-ldap-article/src/main/java/org/springframework/ldap/samples/article/domain/Person.java @@ -0,0 +1,104 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.article.domain; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +/** + * Simple class representing a single person. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class Person { + private String fullName; + + private String lastName; + + private String description; + + private String country; + + private String company; + + private String phone; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getCompany() { + return company; + } + + public void setCompany(String company) { + this.company = company; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals( + this, obj); + } + + public int hashCode() { + return HashCodeBuilder + .reflectionHashCode(this); + } + + public String toString() { + return ToStringBuilder.reflectionToString( + this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/spring-ldap-article/src/main/java/overview.html b/spring-ldap-article/src/main/java/overview.html new file mode 100644 index 00000000..309641cf --- /dev/null +++ b/spring-ldap-article/src/main/java/overview.html @@ -0,0 +1,3 @@ + +This document is the API specification for the Spring LDAP Article sample. + \ No newline at end of file diff --git a/spring-ldap-article/src/test/java/.dummy b/spring-ldap-article/src/test/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/spring-ldap-person/.classpath b/spring-ldap-person/.classpath new file mode 100644 index 00000000..b4a42621 --- /dev/null +++ b/spring-ldap-person/.classpath @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-person/.project b/spring-ldap-person/.project new file mode 100644 index 00000000..0361d9a0 --- /dev/null +++ b/spring-ldap-person/.project @@ -0,0 +1,23 @@ + + + spring-ldap-person + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + + diff --git a/spring-ldap-person/.settings/org.eclipse.jdt.core.prefs b/spring-ldap-person/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..5c094199 --- /dev/null +++ b/spring-ldap-person/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,260 @@ +#Fri Apr 21 13:43:15 CEST 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/spring-ldap-person/.settings/org.eclipse.jdt.ui.prefs b/spring-ldap-person/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000..fc573119 --- /dev/null +++ b/spring-ldap-person/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,4 @@ +#Fri Apr 21 13:43:15 CEST 2006 +eclipse.preferences.version=1 +formatter_settings_version=10 +org.eclipse.jdt.ui.text.custom_code_templates=\r\n diff --git a/spring-ldap-person/.springBeans b/spring-ldap-person/.springBeans new file mode 100644 index 00000000..01fd81fa --- /dev/null +++ b/spring-ldap-person/.springBeans @@ -0,0 +1,35 @@ + + + + xml + + + src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml + src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml + src/main/webapp/WEB-INF/flows/search-flow-beans.xml + src/webapp/WEB-INF/apacheDsContext.xml + src/webapp/WEB-INF/applicationContext-acegi-security.xml + src/webapp/WEB-INF/applicationContext.xml + src/webapp/WEB-INF/ldaptemplate-servlet.xml + src/main/webapp/WEB-INF/flows/detail-flow-beans.xml + src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml + + + + default + false + false + + src/webapp/WEB-INF/apacheDsContext.xml + src/webapp/WEB-INF/applicationContext.xml + src/webapp/WEB-INF/applicationContext-acegi-security.xml + src/webapp/WEB-INF/ldaptemplate-servlet.xml + src/main/webapp/WEB-INF/flows/detail-flow-beans.xml + src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml + src/main/webapp/WEB-INF/flows/search-flow-beans.xml + src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml + src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml + + + + diff --git a/spring-ldap-person/build.xml b/spring-ldap-person/build.xml new file mode 100644 index 00000000..9a8300da --- /dev/null +++ b/spring-ldap-person/build.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-person/deps.txt b/spring-ldap-person/deps.txt new file mode 100644 index 00000000..0609f36e --- /dev/null +++ b/spring-ldap-person/deps.txt @@ -0,0 +1,677 @@ +Apache Ant version 1.6.5 compiled on June 2 2005 +Buildfile: build.xml +Detected Java version: 1.5 in: c:\dev\jdk1.5.0\jre +Detected OS: Windows XP +parsing buildfile D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml with URI = file:///D:/src/open/spring-colin/spring-projects/spring-ldap/spring-ldap-person/build.xml +Project base dir set to: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person + [property] Loading D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.properties + [property] Unable to find property file: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.properties + [property] Loading D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\project.properties + [property] Loading D:\src\open\spring-colin\spring-projects\common-build\build.properties + [property] Unable to find property file: D:\src\open\spring-colin\spring-projects\common-build\build.properties + [property] Loading D:\src\open\spring-colin\spring-projects\common-build\project.properties + [property] Loading C:\Documents and Settings\colin\build.properties + [property] Unable to find property file: C:\Documents and Settings\colin\build.properties +Importing file D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person/../../common-build/common-targets.xml from D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml +parsing buildfile D:\src\open\spring-colin\spring-projects\common-build\common-targets.xml with URI = file:///D:/src/open/spring-colin/spring-projects/common-build/common-targets.xml +parsing buildfile jar:file:/D:/src/open/spring-colin/spring-projects/common-build/lib/ivy-1.3.1.jar!/fr/jayasoft/ivy/ant/antlib.xml with URI = jar:file:/D:/src/open/spring-colin/spring-projects/common-build/lib/ivy-1.3.1.jar!/fr/jayasoft/ivy/ant/antlib.xml +Importing file D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person/../../common-build/tomcat-targets.xml from D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml +parsing buildfile D:\src\open\spring-colin\spring-projects\common-build\tomcat-targets.xml with URI = file:///D:/src/open/spring-colin/spring-projects/common-build/tomcat-targets.xml +Importing file common-targets.xml from D:\src\open\spring-colin\spring-projects\common-build\tomcat-targets.xml +Skipped already imported file: + D:\src\open\spring-colin\spring-projects\common-build\common-targets.xml + +Build sequence for target(s) `retrieve' is [force.env.load, init.cl.external.props, init.env.external.props, init.pre, eclipse.configure, init.post, init.post2, init, check.for.optional.packages, build.prepare, ivy.configure, resolve.pre, resolve.main, resolve.post, resolve, retrieve.pre, retrieve.main, retrieve.post, retrieve] +Complete build sequence is [force.env.load, init.cl.external.props, init.env.external.props, init.pre, eclipse.configure, init.post, init.post2, init, check.for.optional.packages, build.prepare, ivy.configure, resolve.pre, resolve.main, resolve.post, resolve, retrieve.pre, retrieve.main, retrieve.post, retrieve, guard.tomcatdir, tomcat.init, tomcat-clean-war, statics.pre, statics.main, statics.test, statics.web, statics.post, statics, gen.pre, gen.main, gen.post, gen, compile.pre, compile.main, compile.source, compile.tests, compile.post, compile, jar.pre, jar.main, jar.post, jar, source-zip, web.pre, web.main, web.post, web, war.pre, war.main, war.post, war, tomcat-copy-war, tomcat-refresh-war, tomcat-launch, targets, ear.stage.post, ear.stage.pre, ear.stage.main, ear-stage, ear.pre, ear.main, ear.post, ear, publish.setup, publish.do.publish, publish, dist.pre, dist.main, dist.post, dist, guard.testclass, resolve.conf, tests.prepare, tests-local, tests, tests-dist, build.prepare.make.config.dirs, resources, guard.runclass, retrieve-to-repo, clean, clean-all, tomcat-context-error, tomcat-reload, copy.test.resources, tomcat-list, resolve.all, retrieve.all, tomcat-start, copy.resources, tomcat-undeploy, tomcat-content, test-resources, run-with-arguments, test, tomcat-deploy, tomcat-redeploy, classicvm, web.copy.classes, clear.lib.dir.before.retrieve, javadoc, tomcat-stop, web.copy.libs, run, tomcat-context, ] + +force.env.load: + [property] Loading Environment myenv. + +init.cl.external.props: +Skipped because property 'build.prop.file' not set. + +init.env.external.props: +Skipped because property 'myenv.STUB.BUILD.PROP.FILE' not set. + +init.pre: +Override ignored for property DSTAMP +Override ignored for property TSTAMP +Override ignored for property TODAY +Override ignored for property project.webapp.name + [property] Loading Environment myenv. +Override ignored for property myenv.ANT_CMD_LINE_ARGS +Override ignored for property myenv.ANT_HOME +Override ignored for property myenv.JDK_HOME +Override ignored for property myenv.COMPUTERNAME +Override ignored for property myenv.PROCESSOR_ARCHITECTURE +Override ignored for property myenv.SystemDrive +Override ignored for property myenv.PATHEXT +Override ignored for property myenv.PROMPT +Override ignored for property myenv.ALLUSERSPROFILE +Override ignored for property myenv.ComSpec +Override ignored for property myenv.PROCESSOR_IDENTIFIER +Override ignored for property myenv.LOGONSERVER +Override ignored for property myenv.TEMP +Override ignored for property myenv.NUMBER_OF_PROCESSORS +Override ignored for property myenv.PERL5LIB +Override ignored for property myenv.APPDATA +Override ignored for property myenv.CLIENTNAME +Override ignored for property myenv.ProgramFiles +Override ignored for property myenv.OS +Override ignored for property myenv.Path +Override ignored for property myenv.HummPATH +Override ignored for property myenv.SESSIONNAME +Override ignored for property myenv.BitRock +Override ignored for property myenv.WF_RESOURCES +Override ignored for property myenv.USERPROFILE +Override ignored for property myenv.windir +Override ignored for property myenv.USERNAME +Override ignored for property myenv._USE_CLASSPATH +Override ignored for property myenv.HOMEDRIVE +Override ignored for property myenv.PROCESSOR_REVISION +Override ignored for property myenv._JAVACMD +Override ignored for property myenv.CommonProgramFiles +Override ignored for property myenv.MAVEN_HOME +Override ignored for property myenv.HOMEPATH +Override ignored for property myenv.USERDOMAIN +Override ignored for property myenv.RUBYOPT +Override ignored for property myenv.TMP +Override ignored for property myenv.PROCESSOR_LEVEL +Override ignored for property myenv.SystemRoot +Override ignored for property myenv.APR_ICONV_PATH +Override ignored for property myenv.FP_NO_HOST_CHECK +Override ignored for property myenv.JAVA_HOME +Override ignored for property javac.source +Override ignored for property javac.target + [echo] org.name = "springframework.org" + [echo] org.package.prefix = "org.springframework" + [echo] project.name = "spring-ldap-person-sample" + [echo] project.webapp.name = "ldap-person" + [echo] project.title = "spring-ldap-person-sample" + [echo] project.base.version = "1.0-dev" + [echo] project.version = "1.0-dev-20060702095831" + [echo] ant.file = "D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml" + [echo] basedir = "D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person" + [echo] user.dir = "D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person" + [echo] ant.java.version = "1.5" + [echo] debug = "true" + [echo] optimize = "false" + [echo] javac.source = "1.3" + [echo] javac.target = "1.3" +Property ${target.appserver} has not been set + [echo] target.appserver = "${target.appserver}" + [echo] unit test vm: vm arg="-DzzzDummyVal" + +eclipse.configure: +Skipped because property 'eclipse.running' not set. + +init.post: +Overriding previous definition of reference to image.files +Overriding previous definition of reference to html.files +Overriding previous definition of reference to scriptlet.files +Overriding previous definition of reference to web.config.files +Override ignored for property target.lib.dir + [delete] Deleting: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\properties.tmp + +init.post2: + +init: +Skipped because property 'init.done' set. + +check.for.optional.packages: +[available] Unable to load class org.apache.xalan.xslt.XSLTProcessorFactory to set property xalan.present + +build.prepare: +Override ignored for property DSTAMP +Override ignored for property TSTAMP +Override ignored for property TODAY +Project base dir set to: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person + [antcall] calling target(s) [build.prepare.make.config.dirs] in build file D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml +parsing buildfile D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml with URI = file:///D:/src/open/spring-colin/spring-projects/spring-ldap/spring-ldap-person/build.xml +Project base dir set to: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person + [property] Loading D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.properties + [property] Unable to find property file: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.properties + [property] Loading D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\project.properties +Override ignored for property common.build.dir +Override ignored for property javac.source +Override ignored for property javac.target + [property] Loading D:\src\open\spring-colin\spring-projects\common-build\build.properties + [property] Unable to find property file: D:\src\open\spring-colin\spring-projects\common-build\build.properties + [property] Loading D:\src\open\spring-colin\spring-projects\common-build\project.properties +Override ignored for property target.testclasses.dir +Override ignored for property src.web.dir +Override ignored for property target.artifacts.dir +Override ignored for property bin.dir +Override ignored for property src.tld.dir +Override ignored for property static.lib.dir +Override ignored for property data.dir +Override ignored for property src.test.resources.dir +Override ignored for property docs.ref.src.dir +Override ignored for property src.dtd.dir +Override ignored for property target.classes.dir +Override ignored for property target.gen.java.test.dir +Override ignored for property src.resources.dir +Override ignored for property target.ear.expanded.dir +Override ignored for property target.lib.dir +Override ignored for property ivy.retrieve.pattern +Override ignored for property lib.dir +Override ignored for property release.repo.ivy.retrieve.pattern +Override ignored for property src.etc.dir +Override ignored for property packages +Override ignored for property dist.dir +Override ignored for property docs.dir +Override ignored for property release.repo.ivy.retrieve.ivy.pattern +Override ignored for property test.excludes +Override ignored for property target.gen.java.dir +Override ignored for property ivy.srcivypattern +Override ignored for property target.testresults.dir +Override ignored for property target.war.expanded.dir +Override ignored for property target.javadocs.dir +Override ignored for property docs.ref.target.dir +Override ignored for property target.dir +Override ignored for property target.artifacts.ear.dir +Override ignored for property docs.ref.dir +Override ignored for property src.java.main.dir +Override ignored for property target.artifacts.war.dir +Override ignored for property docs.ref.lib.dir +Override ignored for property src.dir +Override ignored for property src.java.test.dir +Override ignored for property ivy.distrib.dir +Override ignored for property test.includes +Override ignored for property target.filter.file +Override ignored for property src.doc.dir + [property] Loading C:\Documents and Settings\colin\build.properties + [property] Unable to find property file: C:\Documents and Settings\colin\build.properties +Override ignored for property build.web +Override ignored for property project.webapp.name +Importing file D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person/../../common-build/common-targets.xml from D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml +parsing buildfile D:\src\open\spring-colin\spring-projects\common-build\common-targets.xml with URI = file:///D:/src/open/spring-colin/spring-projects/common-build/common-targets.xml +parsing buildfile jar:file:/D:/src/open/spring-colin/spring-projects/common-build/lib/ivy-1.3.1.jar!/fr/jayasoft/ivy/ant/antlib.xml with URI = jar:file:/D:/src/open/spring-colin/spring-projects/common-build/lib/ivy-1.3.1.jar!/fr/jayasoft/ivy/ant/antlib.xml +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:configure +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:resolve +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:retrieve +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:deliver +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:publish +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:extract +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:cachepath +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:cachefileset +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:report +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:var +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:check +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:artifactproperty +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:buildlist +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:install +Trying to override old definition of task antlib:fr.jayasoft.ivy.ant:convertpom +Trying to override old definition of task resolve.conf +Trying to override old definition of task resolve.all +Trying to override old definition of task retrieve.conf +Trying to override old definition of task retrieve.all +Override ignored for property test.arguments +Importing file D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person/../../common-build/tomcat-targets.xml from D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml +parsing buildfile D:\src\open\spring-colin\spring-projects\common-build\tomcat-targets.xml with URI = file:///D:/src/open/spring-colin/spring-projects/common-build/tomcat-targets.xml +Importing file common-targets.xml from D:\src\open\spring-colin\spring-projects\common-build\tomcat-targets.xml +Skipped already imported file: + D:\src\open\spring-colin\spring-projects\common-build\common-targets.xml + +Build sequence for target(s) `build.prepare.make.config.dirs' is [build.prepare.make.config.dirs] +Complete build sequence is [build.prepare.make.config.dirs, force.env.load, init.cl.external.props, init.env.external.props, init.pre, eclipse.configure, init.post, init.post2, init, guard.tomcatdir, tomcat.init, tomcat-clean-war, check.for.optional.packages, build.prepare, ivy.configure, resolve.pre, resolve.main, resolve.post, resolve, retrieve.pre, retrieve.main, retrieve.post, retrieve, statics.pre, statics.main, statics.test, statics.web, statics.post, statics, gen.pre, gen.main, gen.post, gen, compile.pre, compile.main, compile.source, compile.tests, compile.post, compile, jar.pre, jar.main, jar.post, jar, source-zip, web.pre, web.main, web.post, web, war.pre, war.main, war.post, war, tomcat-copy-war, tomcat-refresh-war, tomcat-launch, targets, ear.stage.post, ear.stage.pre, ear.stage.main, ear-stage, ear.pre, ear.main, ear.post, ear, publish.setup, publish.do.publish, publish, dist.pre, dist.main, dist.post, dist, guard.testclass, resolve.conf, tests.prepare, tests-local, tests, tests-dist, resources, guard.runclass, retrieve-to-repo, clean, clean-all, tomcat-context-error, tomcat-reload, copy.test.resources, tomcat-list, resolve.all, retrieve.all, tomcat-start, copy.resources, tomcat-undeploy, tomcat-content, test-resources, run-with-arguments, test, tomcat-deploy, tomcat-redeploy, classicvm, web.copy.classes, clear.lib.dir.before.retrieve, javadoc, tomcat-stop, web.copy.libs, run, tomcat-context, ] + [antcall] Entering D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml... +Build sequence for target(s) `build.prepare.make.config.dirs' is [build.prepare.make.config.dirs] +Complete build sequence is [build.prepare.make.config.dirs, force.env.load, init.cl.external.props, init.env.external.props, init.pre, eclipse.configure, init.post, init.post2, init, guard.tomcatdir, tomcat.init, tomcat-clean-war, check.for.optional.packages, build.prepare, ivy.configure, resolve.pre, resolve.main, resolve.post, resolve, retrieve.pre, retrieve.main, retrieve.post, retrieve, statics.pre, statics.main, statics.test, statics.web, statics.post, statics, gen.pre, gen.main, gen.post, gen, compile.pre, compile.main, compile.source, compile.tests, compile.post, compile, jar.pre, jar.main, jar.post, jar, source-zip, web.pre, web.main, web.post, web, war.pre, war.main, war.post, war, tomcat-copy-war, tomcat-refresh-war, tomcat-launch, targets, ear.stage.post, ear.stage.pre, ear.stage.main, ear-stage, ear.pre, ear.main, ear.post, ear, publish.setup, publish.do.publish, publish, dist.pre, dist.main, dist.post, dist, guard.testclass, resolve.conf, tests.prepare, tests-local, tests, tests-dist, resources, guard.runclass, retrieve-to-repo, clean, clean-all, tomcat-context-error, tomcat-reload, copy.test.resources, tomcat-list, resolve.all, retrieve.all, tomcat-start, copy.resources, tomcat-undeploy, tomcat-content, test-resources, run-with-arguments, test, tomcat-deploy, tomcat-redeploy, classicvm, web.copy.classes, clear.lib.dir.before.retrieve, javadoc, tomcat-stop, web.copy.libs, run, tomcat-context, ] + +build.prepare.make.config.dirs: + [antcall] Exiting D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\build.xml. + [copy] Warning: Could not find file D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\src\etc\filter.properties to copy. +[pathconvert] Set property target.testresults.dir.unix = D:/src/open/spring-colin/spring-projects/spring-ldap/spring-ldap-person/target/test-reports +Property ${database.driver} has not been set +Property ${database.url} has not been set +Property ${database.schema} has not been set +Property ${database.username} has not been set +Property ${database.password} has not been set +[propertyfile] Updating property file: D:\src\open\spring-colin\spring-projects\spring-ldap\spring-ldap-person\target\filter.properties + +ivy.configure: + [echo] reading ivy config + [null] Loading jar:file:/D:/src/open/spring-colin/spring-projects/common-build/lib/ivy-1.3.1.jar!/fr/jayasoft/ivy/ant/ivy.properties +Override ignored for property ivy.distrib.dir +Override ignored for property ivy.retrieve.pattern +:: Ivy 1.3.1 - 20060330160721 :: http://ivy.jayasoft.org/ :: +jakarta commons httpclient not found: no authentication will be done +:: configuring :: file = D:\src\open\spring-colin\spring-projects\common-build\ivyconf.xml +no default ivy user dir defined: set to C:\Documents and Settings\colin\.ivy +no default cache defined: set to C:\Documents and Settings\colin\.ivy\cache +loading properties: D:\src\open\spring-colin\spring-projects\common-build/ivyconf.properties +configuration done (109ms) + default cache: C:\Documents and Settings\colin\.ivy\cache + default resolver: third-party + -- 9 resolvers: + third-party [chain] [filesystem-repo, spring-repo-ext, dotsrc-maven2-repo, ivyrep] + spring-repo [url] + integration-repo [file] + ivyrep [ivyrep] + spring-repo-snapshots [url] + filesystem-repo [file] + spring-repo-ext [url] + spring-projects [chain] [integration-repo, filesystem-repo, spring-repo, spring-repo-snapshots] + dotsrc-maven2-repo [ibiblio] + +resolve.pre: + +resolve.main: +using ivy parser to parse file:/D:/src/open/spring-colin/spring-projects/spring-ldap/spring-ldap-person/ivy.xml +:: resolving dependencies :: [ org.springframework | spring-ldap-sample | working@oak ] + confs: [global, buildtime, test] + validate = true + filesystem-repo: revision in cache: [ apache | commons-logging | 1.0.4 ] + found [ apache | commons-logging | 1.0.4 ] in third-party + filesystem-repo: revision in cache: [ apache | log4j | 1.2.9 ] + found [ apache | log4j | 1.2.9 ] in third-party + filesystem-repo: revision in cache: [ apache | oro | 2.0.8 ] + found [ apache | oro | 2.0.8 ] in third-party + filesystem-repo: revision in cache: [ apache | taglibs | 1.1.2 ] + found [ apache | taglibs | 1.1.2 ] in third-party + filesystem-repo: revision in cache: [ java | jstl | 1.1.2 ] + found [ java | jstl | 1.1.2 ] in third-party + integration-repo: found md file for [ org.springframework | spring-ldap | latest.integration ] + => D:\src\open\spring-colin\spring-projects\common-build\..\integration-repo\artifacts\org.springframework\spring-ldap\ivy-1.0.3-dev.xml (1.0.3-dev) + integration-repo: revision in cache: [ org.springframework | spring-ldap | latest.integration ] + found [ org.springframework | spring-ldap | 1.0.3-dev ] in spring-projects + [1.0.3-dev] [ org.springframework | spring-ldap | latest.integration ] + filesystem-repo: revision in cache: [ apache | commons-lang | 2.1 ] + found [ apache | commons-lang | 2.1 ] in third-party + filesystem-repo: revision in cache: [ apache | commons-collections | 3.1 ] + found [ apache | commons-collections | 3.1 ] in third-party + integration-repo: revision in cache: [ org.springframework | spring-beans | 2.0-m5 ] + found [ org.springframework | spring-beans | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-core | 2.0-m5 ] + found [ org.springframework | spring-core | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-context | 2.0-m5 ] + found [ org.springframework | spring-context | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-dao | 2.0-m5 ] + found [ org.springframework | spring-dao | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-web | 2.0-m5 ] + found [ org.springframework | spring-web | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-webmvc | 2.0-m5 ] + found [ org.springframework | spring-webmvc | 2.0-m5 ] in spring-projects + filesystem-repo: revision in cache: [ org.acegisecurity | acegi-security | 1.0.1 ] + found [ org.acegisecurity | acegi-security | 1.0.1 ] in third-party + integration-repo: no ivy file nor artifact found for [ org.springframework | spring-remoting | 1.2.7 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-remoting/ivy-1.2.7.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + filesystem-repo: no ivy file nor artifact found for [ org.springframework | spring-remoting | 1.2.7 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-remoting/ivy-1.2.7.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo/org/springframework/spring-remoting/ivy-1.2.7.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo/org/springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + spring-repo: no ivy file nor artifact found for [ org.springframework | spring-remoting | 1.2.7 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-remoting/ivy-1.2.7.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org/springframework/spring-remoting/ivy-1.2.7.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org/springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + spring-repo-snapshots: no ivy file nor artifact found for [ org.springframework | spring-remoting | 1.2.7 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-remoting/ivy-1.2.7.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar +WARN: module not found: [ org.springframework | spring-remoting | 1.2.7 ] +WARN: integration-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-remoting/ivy-1.2.7.xml +WARN: integration-repo: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar +WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-remoting/ivy-1.2.7.xml +WARN: filesystem-repo: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar +WARN: spring-repo: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-remoting/ivy-1.2.7.xml +WARN: spring-repo: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar +WARN: spring-repo-snapshots: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-remoting/ivy-1.2.7.xml +WARN: spring-repo-snapshots: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + integration-repo: no ivy file nor artifact found for [ org.springframework | spring-jdbc | 1.2.7 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-jdbc/ivy-1.2.7.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + filesystem-repo: no ivy file nor artifact found for [ org.springframework | spring-jdbc | 1.2.7 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-jdbc/ivy-1.2.7.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo/org/springframework/spring-jdbc/ivy-1.2.7.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo/org/springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + spring-repo: no ivy file nor artifact found for [ org.springframework | spring-jdbc | 1.2.7 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-jdbc/ivy-1.2.7.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org/springframework/spring-jdbc/ivy-1.2.7.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org/springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + spring-repo-snapshots: no ivy file nor artifact found for [ org.springframework | spring-jdbc | 1.2.7 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-jdbc/ivy-1.2.7.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar +WARN: module not found: [ org.springframework | spring-jdbc | 1.2.7 ] +WARN: integration-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-jdbc/ivy-1.2.7.xml +WARN: integration-repo: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar +WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-jdbc/ivy-1.2.7.xml +WARN: filesystem-repo: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar +WARN: spring-repo: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-jdbc/ivy-1.2.7.xml +WARN: spring-repo: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar +WARN: spring-repo-snapshots: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-jdbc/ivy-1.2.7.xml +WARN: spring-repo-snapshots: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + filesystem-repo: revision in cache: [ commons-lang | commons-lang | 2.1 ] + found [ commons-lang | commons-lang | 2.1 ] in third-party + filesystem-repo: revision in cache: [ commons-logging | commons-logging | 1.0.4 ] + found [ commons-logging | commons-logging | 1.0.4 ] in third-party + filesystem-repo: revision in cache: [ commons-lang | commons-lang | 2.0 ] + found [ commons-lang | commons-lang | 2.0 ] in third-party + filesystem-repo: revision in cache: [ commons-codec | commons-codec | 1.3 ] + found [ commons-codec | commons-codec | 1.3 ] in third-party + filesystem-repo: revision in cache: [ oro | oro | 2.0.8 ] + found [ oro | oro | 2.0.8 ] in third-party + filesystem-repo: revision in cache: [ commons-collections | commons-collections | 3.1 ] + found [ commons-collections | commons-collections | 3.1 ] in third-party + integration-repo: no ivy file nor artifact found for [ org.springframework | spring-support | 1.2.7 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-support/ivy-1.2.7.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar + filesystem-repo: no ivy file nor artifact found for [ org.springframework | spring-support | 1.2.7 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-support/ivy-1.2.7.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo/org/springframework/spring-support/ivy-1.2.7.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo/org/springframework/spring-support/1.2.7/spring-support-1.2.7.jar + spring-repo: no ivy file nor artifact found for [ org.springframework | spring-support | 1.2.7 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-support/ivy-1.2.7.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org/springframework/spring-support/ivy-1.2.7.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org/springframework/spring-support/1.2.7/spring-support-1.2.7.jar + spring-repo-snapshots: no ivy file nor artifact found for [ org.springframework | spring-support | 1.2.7 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-support/ivy-1.2.7.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar +WARN: module not found: [ org.springframework | spring-support | 1.2.7 ] +WARN: integration-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-support/ivy-1.2.7.xml +WARN: integration-repo: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar +WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-support/ivy-1.2.7.xml +WARN: filesystem-repo: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar +WARN: spring-repo: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-support/ivy-1.2.7.xml +WARN: spring-repo: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar +WARN: spring-repo-snapshots: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-support/ivy-1.2.7.xml +WARN: spring-repo-snapshots: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-core | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-core | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-core-shared | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-core-shared | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-server-jndi | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-server-jndi | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-server-main | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-server-main | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-protocol-shared | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-protocol-shared | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-protocol-changepw | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-protocol-changepw | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-protocol-kerberos | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-protocol-kerberos | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-kerberos-shared | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-kerberos-shared | 1.0-RC3 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.server | apacheds-protocol-ldap | 1.0-RC3 ] + found [ org.apache.directory.server | apacheds-protocol-ldap | 1.0-RC3 ] in third-party + filesystem-repo: no ivy file nor artifact found for [ apache | directory | 0.9.5 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/ivy-0.9.5.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/0.9.5/shared-ldap-0.9.5.jar + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/0.9.5/shared-asn1-0.9.5.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/ivy-0.9.5.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-ldap-0.9.5.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-asn1-0.9.5.jar + spring-repo-ext: no ivy file nor artifact found for [ apache | directory | 0.9.5 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/ivy-0.9.5.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-ldap-0.9.5.jar + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-asn1-0.9.5.jar +CLIENT ERROR: Not Found url=http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/directory-0.9.5.pom +CLIENT ERROR: Not Found url=http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-ldap-0.9.5.jar +CLIENT ERROR: Not Found url=http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-asn1-0.9.5.jar + dotsrc-maven2-repo: no ivy file nor artifact found for [ apache | directory | 0.9.5 ] + tried http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/ivy-0.9.5.xml + tried http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-ldap-0.9.5.jar + tried http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-asn1-0.9.5.jar +CLIENT ERROR: Not Found url=http://ivyrep.jayasoft.org/apache/directory/ivy-0.9.5.xml +CLIENT ERROR: Not Found url=http://www.ibiblio.org/maven/directory/jars/shared-ldap-0.9.5.jar +CLIENT ERROR: Not Found url=http://www.ibiblio.org/maven/directory/jars/shared-asn1-0.9.5.jar + ivyrep: no ivy file nor artifact found for [ apache | directory | 0.9.5 ] + tried http://ivyrep.jayasoft.org/apache/directory/ivy-0.9.5.xml + tried http://www.ibiblio.org/maven/directory/jars/shared-ldap-0.9.5.jar + tried http://www.ibiblio.org/maven/directory/jars/shared-asn1-0.9.5.jar +WARN: module not found: [ apache | directory | 0.9.5 ] +WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/ivy-0.9.5.xml +WARN: filesystem-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/0.9.5/shared-ldap-0.9.5.jar +WARN: filesystem-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/0.9.5/shared-asn1-0.9.5.jar +WARN: spring-repo-ext: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/ivy-0.9.5.xml +WARN: spring-repo-ext: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-asn1-0.9.5.jar +WARN: spring-repo-ext: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-ldap-0.9.5.jar +WARN: dotsrc-maven2-repo: tried http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/ivy-0.9.5.xml +WARN: dotsrc-maven2-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: +WARN: http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-asn1-0.9.5.jar +WARN: dotsrc-maven2-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: +WARN: http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-ldap-0.9.5.jar +WARN: ivyrep: tried http://ivyrep.jayasoft.org/apache/directory/ivy-0.9.5.xml +WARN: ivyrep: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: +WARN: http://www.ibiblio.org/maven/directory/jars/shared-ldap-0.9.5.jar +WARN: ivyrep: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: +WARN: http://www.ibiblio.org/maven/directory/jars/shared-asn1-0.9.5.jar + filesystem-repo: revision in cache: [ antlr | antlr | 2.7.2 ] + found [ antlr | antlr | 2.7.2 ] in third-party + filesystem-repo: revision in cache: [ jdbm | jdbm | 1.0 ] + found [ jdbm | jdbm | 1.0 ] in third-party + filesystem-repo: revision in cache: [ org.slf4j | slf4j-log4j12 | 1.0 ] + found [ org.slf4j | slf4j-log4j12 | 1.0 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.mina | mina-core | 0.9.2 ] + found [ org.apache.directory.mina | mina-core | 0.9.2 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.mina | mina-filter-codec-asn1 | 0.9.2 ] + found [ org.apache.directory.mina | mina-filter-codec-asn1 | 0.9.2 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.shared | shared-asn1 | 0.9.5 ] + found [ org.apache.directory.shared | shared-asn1 | 0.9.5 ] in third-party + filesystem-repo: revision in cache: [ org.apache.directory.mina | mina-filter-ssl | 0.9.2 ] + found [ org.apache.directory.mina | mina-filter-ssl | 0.9.2 ] in third-party + integration-repo: revision in cache: [ org.springframework | spring-jdbc | 2.0-m5 ] + found [ org.springframework | spring-jdbc | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-remoting | 2.0-m5 ] + found [ org.springframework | spring-remoting | 2.0-m5 ] in spring-projects + integration-repo: revision in cache: [ org.springframework | spring-support | 2.0-m5 ] + found [ org.springframework | spring-support | 2.0-m5 ] in spring-projects + filesystem-repo: revision in cache: [ javax.servlet | servlet-api | 2.4 ] + found [ javax.servlet | servlet-api | 2.4 ] in third-party + filesystem-repo: revision in cache: [ cenqua | clover | 1.3.8 ] + found [ cenqua | clover | 1.3.8 ] in third-party + filesystem-repo: no ivy file nor artifact found for [ springframework | spring-mock | 2.0-m5 ] + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/springframework/spring-mock/ivy-2.0-m5.xml + tried D:\src\open\spring-colin\spring-projects\common-build/../repository/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/ivy-2.0-m5.xml +CLIENT ERROR: Not Found url=https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar + spring-repo-ext: no ivy file nor artifact found for [ springframework | spring-mock | 2.0-m5 ] + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/ivy-2.0-m5.xml + tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar +CLIENT ERROR: Not Found url=http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.pom +CLIENT ERROR: Not Found url=http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar + dotsrc-maven2-repo: no ivy file nor artifact found for [ springframework | spring-mock | 2.0-m5 ] + tried http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/ivy-2.0-m5.xml + tried http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar +CLIENT ERROR: Not Found url=http://ivyrep.jayasoft.org/springframework/spring-mock/ivy-2.0-m5.xml +CLIENT ERROR: Not Found url=http://www.ibiblio.org/maven/spring-mock/jars/spring-mock-2.0-m5.jar + ivyrep: no ivy file nor artifact found for [ springframework | spring-mock | 2.0-m5 ] + tried http://ivyrep.jayasoft.org/springframework/spring-mock/ivy-2.0-m5.xml + tried http://www.ibiblio.org/maven/spring-mock/jars/spring-mock-2.0-m5.jar +WARN: module not found: [ springframework | spring-mock | 2.0-m5 ] +WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/springframework/spring-mock/ivy-2.0-m5.xml +WARN: filesystem-repo: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: +WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar +WARN: spring-repo-ext: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/ivy-2.0-m5.xml +WARN: spring-repo-ext: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: +WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar +WARN: dotsrc-maven2-repo: tried http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/ivy-2.0-m5.xml +WARN: dotsrc-maven2-repo: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: +WARN: http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar +WARN: ivyrep: tried http://ivyrep.jayasoft.org/springframework/spring-mock/ivy-2.0-m5.xml +WARN: ivyrep: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: +WARN: http://www.ibiblio.org/maven/spring-mock/jars/spring-mock-2.0-m5.jar + filesystem-repo: revision in cache: [ junit | junit | 3.8.1 ] + found [ junit | junit | 3.8.1 ] in third-party + filesystem-repo: revision in cache: [ easymock | easymock | 1.1 ] + found [ easymock | easymock | 1.1 ] in third-party +:: downloading artifacts :: + [NOT REQUIRED] [ apache | taglibs | 1.1.2 ]/standard.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-web | 2.0-m5 ]/spring-web.jar[jar] + [NOT REQUIRED] [ easymock | easymock | 1.1 ]/easymock.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-ldap | 1.0.3-dev ]/spring-ldap.jar[jar] + [NOT REQUIRED] [ org.slf4j | slf4j-log4j12 | 1.0 ]/slf4j-log4j12.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-protocol-ldap | 1.0-RC3 ]/apacheds-protocol-ldap.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-protocol-kerberos | 1.0-RC3 ]/apacheds-protocol-kerberos.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-protocol-changepw | 1.0-RC3 ]/apacheds-protocol-changepw.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-protocol-shared | 1.0-RC3 ]/apacheds-protocol-shared.jar[jar] + [NOT REQUIRED] [ apache | commons-collections | 3.1 ]/commons-collections.jar[jar] + [NOT REQUIRED] [ apache | commons-lang | 2.1 ]/commons-lang.jar[jar] + [NOT REQUIRED] [ apache | commons-logging | 1.0.4 ]/commons-logging.jar[jar] + [NOT REQUIRED] [ java | jstl | 1.1.2 ]/jstl.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-core | 1.0-RC3 ]/apacheds-core.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-core | 2.0-m5 ]/spring-core.jar[jar] + [NOT REQUIRED] [ cenqua | clover | 1.3.8 ]/clover.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-support | 2.0-m5 ]/spring-support.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-dao | 2.0-m5 ]/spring-dao.jar[jar] + [NOT REQUIRED] [ antlr | antlr | 2.7.2 ]/antlr.jar[jar] + [NOT REQUIRED] [ apache | log4j | 1.2.9 ]/log4j.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-remoting | 2.0-m5 ]/spring-remoting.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-jdbc | 2.0-m5 ]/spring-jdbc.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-server-jndi | 1.0-RC3 ]/apacheds-server-jndi.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-server-main | 1.0-RC3 ]/apacheds-server-main.jar[jar] + [NOT REQUIRED] [ jdbm | jdbm | 1.0 ]/jdbm.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-context | 2.0-m5 ]/spring-context.jar[jar] + [NOT REQUIRED] [ org.acegisecurity | acegi-security | 1.0.1 ]/acegi-security.jar[jar] + [NOT REQUIRED] [ commons-collections | commons-collections | 3.1 ]/commons-collections.jar[jar] + [NOT REQUIRED] [ oro | oro | 2.0.8 ]/oro.jar[jar] + [NOT REQUIRED] [ commons-codec | commons-codec | 1.3 ]/commons-codec.jar[jar] + [NOT REQUIRED] [ junit | junit | 3.8.1 ]/junit.jar[jar] + [NOT REQUIRED] [ commons-logging | commons-logging | 1.0.4 ]/commons-logging.jar[jar] + [NOT REQUIRED] [ javax.servlet | servlet-api | 2.4 ]/servlet-api.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-beans | 2.0-m5 ]/spring-beans.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-core-shared | 1.0-RC3 ]/apacheds-core-shared.jar[jar] + [NOT REQUIRED] [ org.apache.directory.server | apacheds-kerberos-shared | 1.0-RC3 ]/apacheds-kerberos-shared.jar[jar] + [NOT REQUIRED] [ org.apache.directory.mina | mina-filter-codec-asn1 | 0.9.2 ]/mina-filter-codec-asn1.jar[jar] + [NOT REQUIRED] [ org.apache.directory.shared | shared-asn1 | 0.9.5 ]/shared-asn1.jar[jar] + [NOT REQUIRED] [ commons-lang | commons-lang | 2.0 ]/commons-lang.jar[jar] + [NOT REQUIRED] [ org.apache.directory.mina | mina-filter-ssl | 0.9.2 ]/mina-filter-ssl.jar[jar] + [NOT REQUIRED] [ org.apache.directory.mina | mina-core | 0.9.2 ]/mina-core.jar[jar] + [NOT REQUIRED] [ org.springframework | spring-webmvc | 2.0-m5 ]/spring-webmvc.jar[jar] + [NOT REQUIRED] [ apache | oro | 2.0.8 ]/oro.jar[jar] + resolved ivy file produced in C:\Documents and Settings\colin\.ivy\cache\resolved-org.springframework-spring-ldap-sample-working@oak.xml +:: resolution report :: + :: evicted modules: + [ commons-lang | commons-lang | 2.1 ] by [[ commons-lang | commons-lang | 2.0 ]] in [global] + in [ org.acegisecurity | acegi-security | 1.0.1 ] with latest-revision + --------------------------------------------------------------------- + | | modules || artifacts | + | conf | number| search|dwnlded|evicted|| number|dwnlded| + --------------------------------------------------------------------- + | global | 41 | 1 | 0 | 1 || 36 | 0 | + | buildtime | 4 | 0 | 0 | 0 || 4 | 0 | + | test | 4 | 0 | 0 | 0 || 3 | 0 | + --------------------------------------------------------------------- +WARN: :::::::::::::::::::::::::::::::::::::::::::::: +WARN: :: UNRESOLVED DEPENDENCIES :: +WARN: :::::::::::::::::::::::::::::::::::::::::::::: +WARN: :: [ org.springframework | spring-support | 1.2.7 ]: not found +WARN: :: [ org.springframework | spring-jdbc | 1.2.7 ]: not found +WARN: :: [ springframework | spring-mock | 2.0-m5 ]: not found +WARN: :: [ apache | directory | 0.9.5 ]: not found +WARN: :: [ org.springframework | spring-remoting | 1.2.7 ]: not found +WARN: :::::::::::::::::::::::::::::::::::::::::::::: + + report for [ org.springframework | spring-ldap-sample | null ] global produced in C:\Documents and Settings\colin\.ivy\cache\org.springframework-spring-ldap-sample-global.xml + report for [ org.springframework | spring-ldap-sample | null ] buildtime produced in C:\Documents and Settings\colin\.ivy\cache\org.springframework-spring-ldap-sample-buildtime.xml + report for [ org.springframework | spring-ldap-sample | null ] test produced in C:\Documents and Settings\colin\.ivy\cache\org.springframework-spring-ldap-sample-test.xml + resolve done (12156ms) + +:: problems summary :: + WARN: module not found: [ org.springframework | spring-remoting | 1.2.7 ] + WARN: integration-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-remoting/ivy-1.2.7.xml + WARN: integration-repo: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-remoting/ivy-1.2.7.xml + WARN: filesystem-repo: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + WARN: spring-repo: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-remoting/ivy-1.2.7.xml + WARN: spring-repo: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + WARN: spring-repo-snapshots: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-remoting/ivy-1.2.7.xml + WARN: spring-repo-snapshots: tried artifact [ org.springframework | spring-remoting | 1.2.7 ]/spring-remoting.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-remoting/1.2.7/spring-remoting-1.2.7.jar + WARN: module not found: [ org.springframework | spring-jdbc | 1.2.7 ] + WARN: integration-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-jdbc/ivy-1.2.7.xml + WARN: integration-repo: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-jdbc/ivy-1.2.7.xml + WARN: filesystem-repo: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + WARN: spring-repo: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-jdbc/ivy-1.2.7.xml + WARN: spring-repo: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + WARN: spring-repo-snapshots: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-jdbc/ivy-1.2.7.xml + WARN: spring-repo-snapshots: tried artifact [ org.springframework | spring-jdbc | 1.2.7 ]/spring-jdbc.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-jdbc/1.2.7/spring-jdbc-1.2.7.jar + WARN: module not found: [ org.springframework | spring-support | 1.2.7 ] + WARN: integration-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-support/ivy-1.2.7.xml + WARN: integration-repo: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../integration-repo/artifacts/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar + WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-support/ivy-1.2.7.xml + WARN: filesystem-repo: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar + WARN: spring-repo: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-support/ivy-1.2.7.xml + WARN: spring-repo: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar + WARN: spring-repo-snapshots: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-support/ivy-1.2.7.xml + WARN: spring-repo-snapshots: tried artifact [ org.springframework | spring-support | 1.2.7 ]/spring-support.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-snapshots/org.springframework/spring-support/1.2.7/spring-support-1.2.7.jar + WARN: module not found: [ apache | directory | 0.9.5 ] + WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/ivy-0.9.5.xml + WARN: filesystem-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/0.9.5/shared-ldap-0.9.5.jar + WARN: filesystem-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/apache/directory/0.9.5/shared-asn1-0.9.5.jar + WARN: spring-repo-ext: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/ivy-0.9.5.xml + WARN: spring-repo-ext: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-asn1-0.9.5.jar + WARN: spring-repo-ext: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/apache/directory/0.9.5/shared-ldap-0.9.5.jar + WARN: dotsrc-maven2-repo: tried http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/ivy-0.9.5.xml + WARN: dotsrc-maven2-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: + WARN: http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-asn1-0.9.5.jar + WARN: dotsrc-maven2-repo: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: + WARN: http://mirrors.dotsrc.org/maven2/apache/directory/0.9.5/shared-ldap-0.9.5.jar + WARN: ivyrep: tried http://ivyrep.jayasoft.org/apache/directory/ivy-0.9.5.xml + WARN: ivyrep: tried artifact [ apache | directory | 0.9.5 ]/shared-ldap.jar[jar]: + WARN: http://www.ibiblio.org/maven/directory/jars/shared-ldap-0.9.5.jar + WARN: ivyrep: tried artifact [ apache | directory | 0.9.5 ]/shared-asn1.jar[jar]: + WARN: http://www.ibiblio.org/maven/directory/jars/shared-asn1-0.9.5.jar + WARN: module not found: [ springframework | spring-mock | 2.0-m5 ] + WARN: filesystem-repo: tried D:\src\open\spring-colin\spring-projects\common-build/../repository/springframework/spring-mock/ivy-2.0-m5.xml + WARN: filesystem-repo: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: + WARN: D:\src\open\spring-colin\spring-projects\common-build/../repository/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar + WARN: spring-repo-ext: tried https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/ivy-2.0-m5.xml + WARN: spring-repo-ext: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: + WARN: https://svn.sourceforge.net/svnroot/springframework/repos/repo-ext/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar + WARN: dotsrc-maven2-repo: tried http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/ivy-2.0-m5.xml + WARN: dotsrc-maven2-repo: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: + WARN: http://mirrors.dotsrc.org/maven2/springframework/spring-mock/2.0-m5/spring-mock-2.0-m5.jar + WARN: ivyrep: tried http://ivyrep.jayasoft.org/springframework/spring-mock/ivy-2.0-m5.xml + WARN: ivyrep: tried artifact [ springframework | spring-mock | 2.0-m5 ]/spring-mock.jar[jar]: + WARN: http://www.ibiblio.org/maven/spring-mock/jars/spring-mock-2.0-m5.jar + WARN: :::::::::::::::::::::::::::::::::::::::::::::: + WARN: :: UNRESOLVED DEPENDENCIES :: + WARN: :::::::::::::::::::::::::::::::::::::::::::::: + WARN: :: [ org.springframework | spring-support | 1.2.7 ]: not found + WARN: :: [ org.springframework | spring-jdbc | 1.2.7 ]: not found + WARN: :: [ springframework | spring-mock | 2.0-m5 ]: not found + WARN: :: [ apache | directory | 0.9.5 ]: not found + WARN: :: [ org.springframework | spring-remoting | 1.2.7 ]: not found + WARN: :::::::::::::::::::::::::::::::::::::::::::::: + + + --- USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS --- diff --git a/spring-ldap-person/docs/base_data.ldif b/spring-ldap-person/docs/base_data.ldif new file mode 100644 index 00000000..f06390db --- /dev/null +++ b/spring-ldap-person/docs/base_data.ldif @@ -0,0 +1,9 @@ +dn: dc=jayway,dc=se +objectclass: dcObject +objectclass: organization +o: jayway +dc: jayway + +dn: cn=Manager,dc=jayway,dc=se +objectclass:organizationalRole +cn: Manager diff --git a/spring-ldap-person/docs/ldap.conf.example b/spring-ldap-person/docs/ldap.conf.example new file mode 100644 index 00000000..bec7489f --- /dev/null +++ b/spring-ldap-person/docs/ldap.conf.example @@ -0,0 +1,25 @@ +# +# LDAP Defaults +# + +# See ldap.conf(5) for details +# This file should be world readable but not world writable. + +#BASE dc=example, dc=com +#URI ldap://ldap.example.com ldap://ldap-master.example.com:666 + +#SIZELIMIT 12 +#TIMELIMIT 15 +#DEREF never + +include "C:/Program Files/OpenLDAP/schema/core.schema" +include "C:/Program Files/OpenLDAP/schema/cosine.schema" +include "C:/Program Files/OpenLDAP/schema/inetorgperson.schema" +database bdb +suffix "dc=jayway,dc=se" +rootdn "cn=Manager,dc=jayway,dc=se" +rootpw secret +directory "C:/Program Files/OpenLDAP/data" +access to * + by users write + by * read diff --git a/spring-ldap-person/docs/readme.txt b/spring-ldap-person/docs/readme.txt new file mode 100644 index 00000000..73d6dd15 --- /dev/null +++ b/spring-ldap-person/docs/readme.txt @@ -0,0 +1,57 @@ +LDAP server setup for samples. + +We need to semi-manually set up the server environment. I have used +OpenLDAP (http://www.openldap.org/) with a minimal amount of data set up from an +LDIF file. + +There is a Windows version of OpenLDAP available at: + + http://lucas.bergmans.us/hacks/openldap/ + +The LDIF file and sample application both expect to find the base suffix +"dc=jayway,dc=se" in the LDAP Server. + +For help in setting up the LDAP environment, three files are supplied: +1. ldap.conf.example + Modify paths in this file to suit your installation by replacing + the placeholder [open_ldap_path]. +2. base_data.ldif + Base domain and Admin data as specified in ldap.conf. +3. setup_data.ldif + The data expected by the integration test cases. + +Start the LDAP Server: +slapd -d 1 -f ldap.conf.example + +Add the LDIF files (the default password in ldap.conf.example is "secret"): +ldapadd -x -D "cn=Manager,dc=jayway,dc=se" -W -f base_data.ldif +ldapadd -x -D "cn=Manager,dc=jayway,dc=se" -W -f setup_data.ldif + +Verify the installation by running this search: + +ldapsearch -LLL -b dc=jayway,dc=se "(objectclass=*)" dn + +It should result in a list that looks like this: + +dn: dc=jayway,dc=se + +dn: cn=Manager,dc=jayway,dc=se + +dn: c=Sweden,dc=jayway,dc=se + +dn: c=Norway,dc=jayway,dc=se +... + +You should now be all set to run the examples. If you are running Trifork T4, enter this: + +C:\src\ldaptemplate\ldaptemplate-person>trifork archive deploy -inplace -appname + ldaptemplate default trifork.map + +Open a browser and go to http://localhost:8080/ldaptemplate + +If you choose to run the tests on another instance, or specifically with +another suffix than the one mentioned above, you may need to modify data in +the following files: + +setup_data.ldif +/src/webapp/WEB-INF/ldap.properties diff --git a/spring-ldap-person/docs/setup_data.ldif b/spring-ldap-person/docs/setup_data.ldif new file mode 100644 index 00000000..68d301a5 --- /dev/null +++ b/spring-ldap-person/docs/setup_data.ldif @@ -0,0 +1,90 @@ +dn: c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Sweden +description: The country of Sweden + +dn: c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Norway +description: The country of Norway + +dn: ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Sweden + +dn: ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company2 +description: Second company in Sweden + +dn: ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Norway + +dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person +userPassword: password +cn: Some Person +sn: Person +description: USER +telephoneNumber: +46 555-123456 + +dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person2 +userPassword: password +cn: Some Person2 +sn: Person2 +description: USER +description: ADMIN +telephoneNumber: +46 555-654321 + +dn: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person3 +userPassword: password +cn: Some Person3 +sn: Person3 +description: USER +telephoneNumber: +46 555-123654 + +dn: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person4 +userPassword: password +cn: Some Person +sn: Person +description: USER +telephoneNumber: +46 555-456321 + +dn: cn=Some Person,ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.norwegian +userPassword: password +cn: Some Person +sn: Person +description: USER +telephoneNumber: +45 555-456321 diff --git a/spring-ldap-person/docs/teardown_data.ldif b/spring-ldap-person/docs/teardown_data.ldif new file mode 100644 index 00000000..97ba7e6b --- /dev/null +++ b/spring-ldap-person/docs/teardown_data.ldif @@ -0,0 +1,3 @@ +c=Sweden,dc=jayway,dc=se + +c=Norway,dc=jayway,dc=se diff --git a/spring-ldap-person/ivy.xml b/spring-ldap-person/ivy.xml new file mode 100644 index 00000000..6b4d1dcd --- /dev/null +++ b/spring-ldap-person/ivy.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-person/pom.xml b/spring-ldap-person/pom.xml new file mode 100644 index 00000000..3ea94a95 --- /dev/null +++ b/spring-ldap-person/pom.xml @@ -0,0 +1,151 @@ + + + + spring-ldap + org.springframework.ldap + 1.1.1-SNAPSHOT + + 4.0.0 + org.springframework + spring-ldap-person-sample + Spring LDAP Person Sample + 1.1.1-SNAPSHOT + + Example web application that demonstrates how + Spring LDAP can be used to perform CRUD (Create,Read,Update,Delete) + operations towards an LDAP database. + + + + + + commons-lang + commons-lang + 2.1 + provided + + + javax.servlet + servlet-api + 2.4 + provided + + + + org.apache.directory.server + apacheds-core + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-core-shared + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-server-jndi + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-server-main + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-protocol-shared + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-protocol-changepw + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-protocol-kerberos + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-kerberos-shared + 1.0-RC3 + provided + + + org.apache.directory.server + apacheds-protocol-ldap + 1.0-RC3 + provided + + + org.apache.directory.shared + shared-asn1 + 0.9.5.1 + provided + + + org.apache.directory.shared + shared-ldap + 0.9.5.1 + provided + + + + org.springframework + spring-ldap + 1.1.1-SNAPSHOT + provided + + + org.springframework + spring-web + 2.0 + provided + + + org.springframework + spring-webmvc + 2.0 + provided + + + org.springframework + spring-jdbc + 2.0 + provided + + + org.springframework + spring-remoting + 2.0 + provided + + + org.springframework + spring-support + 2.0 + provided + + + + easymock + easymock + 1.2_Java1.3 + test + + + org.springframework + spring-mock + 2.0 + test + + + diff --git a/spring-ldap-person/project.properties b/spring-ldap-person/project.properties new file mode 100644 index 00000000..5e43e378 --- /dev/null +++ b/spring-ldap-person/project.properties @@ -0,0 +1,10 @@ +# properties defined in this file are overridable by a local build.properties in this project dir + +# The location of the common build system +common.build.dir=${basedir}/../common-build + +javac.source=1.3 +javac.target=1.3 + +# extend common-build with source capability +main.build.configs=global,buildtime,test,source diff --git a/spring-ldap-person/readme.txt b/spring-ldap-person/readme.txt new file mode 100644 index 00000000..92f1ac30 --- /dev/null +++ b/spring-ldap-person/readme.txt @@ -0,0 +1,3 @@ +To run this sample project, run "ant dist" and copy target/artifacts/war/ldap-person.war +to the webapps directory of your tomcat server. It runs Apache-DS directory server +setup with some initial data internally. \ No newline at end of file diff --git a/spring-ldap-person/src/itest/java/.dummy b/spring-ldap-person/src/itest/java/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/spring-ldap-person/src/main/java/log4j.properties b/spring-ldap-person/src/main/java/log4j.properties new file mode 100644 index 00000000..4ab57157 --- /dev/null +++ b/spring-ldap-person/src/main/java/log4j.properties @@ -0,0 +1,19 @@ +log4j.rootCategory=INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${ldaptemplate.root}/ldaptemplate.log +log4j.appender.logfile.MaxFileSize=512KB + +# Keep three backup files +log4j.appender.logfile.MaxBackupIndex=3 +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout + +#Pattern to output : date priority [category] - line_separator +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n + +#Enable debug logging +#log4j.category.net.sf.ldaptemplate=DEBUG diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/ConfigEnvHelper.java b/spring-ldap-person/src/main/java/org/springframework/ldap/ConfigEnvHelper.java new file mode 100644 index 00000000..3f03a19b --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/ConfigEnvHelper.java @@ -0,0 +1,58 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.io.File; +import java.util.Hashtable; + +import javax.naming.Context; + +import org.apache.directory.server.configuration.MutableServerStartupConfiguration; +import org.apache.directory.server.jndi.ServerContextFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * Helper class to simplify Spring configuration of ApacheDS. + * + * @author Mattias Arthursson + */ +public class ConfigEnvHelper implements InitializingBean { + private final MutableServerStartupConfiguration configuration; + + private final Hashtable initialEnv; + + private final File workingDir = new File(System + .getProperty("java.io.tmpdir") + + File.separator + "ldaptemplate_apacheds"); + + public ConfigEnvHelper(Hashtable initialEnv, + MutableServerStartupConfiguration configuration) { + + this.initialEnv = initialEnv; + this.configuration = configuration; + } + + public Hashtable getEnv() { + return initialEnv; + } + + public void afterPropertiesSet() throws Exception { + initialEnv.put(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName()); + configuration.setWorkingDirectory(workingDir); + initialEnv.putAll(configuration.toJndiEnvironment()); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/LdapServerManager.java b/spring-ldap-person/src/main/java/org/springframework/ldap/LdapServerManager.java new file mode 100644 index 00000000..928b42d2 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/LdapServerManager.java @@ -0,0 +1,132 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.io.File; +import java.util.Collections; +import java.util.Properties; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.ContextNotEmptyException; +import javax.naming.InitialContext; +import javax.naming.Name; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.support.DefaultDirObjectFactory; +import org.springframework.ldap.support.DistinguishedName; + +import org.apache.directory.server.core.configuration.ShutdownConfiguration; +import org.apache.directory.server.jndi.ServerContextFactory; +import org.apache.directory.server.protocol.shared.store.LdifFileLoader; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; + +/** + * Utility class to initialize the apache directory server. This means clearing + * it of all entries, and initializing it with the startup ldif data. + * + * @author Mattias Arthursson + */ +public class LdapServerManager implements InitializingBean, DisposableBean { + + private ContextSource contextSource; + + private String ldifFile; + + public void setContextSource(ContextSource contextSource) { + this.contextSource = contextSource; + } + + public void setLdifFile(String ldifFile) { + this.ldifFile = ldifFile; + } + + public void destroy() throws Exception { + Properties env = new Properties(); + env.setProperty(Context.INITIAL_CONTEXT_FACTORY, + ServerContextFactory.class.getName()); + env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); + env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); + env.setProperty(Context.SECURITY_CREDENTIALS, "secret"); + + ShutdownConfiguration configuration = new ShutdownConfiguration(); + env.putAll(configuration.toJndiEnvironment()); + + new InitialContext(env); + } + + public void afterPropertiesSet() throws Exception { + DirContext ctx = contextSource.getReadWriteContext(); + + // First of all, make sure the database is empty. + Name startingPoint = null; + + // Different test cases have different base paths. This means that the + // starting point will be different. + if (ctx.getEnvironment().get( + DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY) != null) { + startingPoint = DistinguishedName.EMPTY_PATH; + } else { + startingPoint = new DistinguishedName("dc=jayway,dc=se"); + } + + try { + clearSubContexts(ctx, startingPoint); + // Load the ldif to the recently started server + System.out.println("loading file '" + ldifFile + "'"); + LdifFileLoader loader = new LdifFileLoader(ctx, new File(ldifFile), + Collections.EMPTY_LIST, this.getClass().getClassLoader()); + loader.execute(); + } finally { + ctx.close(); + } + } + + private void clearSubContexts(DirContext ctx, Name name) + throws NamingException { + + NamingEnumeration enumeration = null; + try { + enumeration = ctx.listBindings(name); + while (enumeration.hasMore()) { + Binding element = (Binding) enumeration.next(); + DistinguishedName childName = new DistinguishedName(element + .getName()); + childName.prepend((DistinguishedName) name); + + try { + ctx.destroySubcontext(childName); + } catch (ContextNotEmptyException e) { + clearSubContexts(ctx, childName); + ctx.destroySubcontext(childName); + } + } + } catch (NamingException e) { + e.printStackTrace(); + } finally { + try { + enumeration.close(); + } catch (Exception e) { + // Never mind this + } + } + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyGroupDao.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyGroupDao.java new file mode 100644 index 00000000..b90811a6 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyGroupDao.java @@ -0,0 +1,67 @@ +package org.springframework.ldap.samples.person.dao; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.EntryNotFoundException; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +public class DummyGroupDao implements GroupDao { + private static Map GROUPS; + + static { + Group group1 = new Group(); + group1.setName("DUMMY_ADMIN"); + Group group2 = new Group(); + group2.setName("DUMMY_USER"); + GROUPS = new HashMap(); + GROUPS.put("DUMMY_ADMIN", group1); + GROUPS.put("DUMMY_USER", group2); + } + + Log log = LogFactory.getLog(DummyGroupDao.class); + + public void create(Group group) { + log.info("create"); + } + + public void delete(Group group) { + log.info("delete"); + } + + public List find(SearchCriteria criteria) { + log.info("find"); + if (GROUPS.get(criteria.getName()) != null) { + return Collections.singletonList(GROUPS.get(criteria.getName())); + } else { + return Collections.EMPTY_LIST; + } + } + + public List findAll() { + log.info("findAll"); + return new LinkedList(GROUPS.entrySet()); + } + + public Group findByPrimaryKey(String name) { + log.info("findByPrimaryKey"); + if (GROUPS.get(name) != null) { + return (Group) GROUPS.get(name); + } else { + throw new EntryNotFoundException("Could not find group with name '" + + name + "'"); + } + } + + public void update(Group group) { + log.info("update"); + Group actualGroup = findByPrimaryKey(group.getName()); + actualGroup.setMembers(group.getMembers()); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyPersonDao.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyPersonDao.java new file mode 100644 index 00000000..f2e5613c --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/DummyPersonDao.java @@ -0,0 +1,83 @@ +package org.springframework.ldap.samples.person.dao; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.EntryNotFoundException; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +public class DummyPersonDao implements PersonDao { + private static Map PERSONS; + + static { + Person person1 = new Person(); + person1.setFullName("Dummy Person1"); + person1.setCompany("Dummy Company"); + person1.setCountry("Sweden"); + person1.setDescription(new String[] { "Some dummy person" }); + person1.setLastName("Person1"); + person1.setPhone("555-12312"); + person1.setDn("cn=Dummy Person1"); + Person person2 = new Person(); + person2.setFullName("Dummy Person2"); + person2.setCompany("Dummy Company"); + person2.setCountry("Norway"); + person2.setDescription(new String[] { "Another dummy person" }); + person2.setLastName("Person2"); + person2.setPhone("555-32132"); + person2.setDn("cn=Dummy Person2"); + PERSONS = new HashMap(); + PERSONS.put("Dummy Person1", person1); + PERSONS.put("Dummy Person2", person2); + } + + Log log = LogFactory.getLog(DummyPersonDao.class); + + public void create(Person person) { + log.info("create"); + } + + public void delete(Person person) { + log.info("delete"); + } + + public List find(SearchCriteria criteria) { + log.info("find"); + if (PERSONS.get(criteria.getName()) != null) { + return Collections.singletonList(PERSONS.get(criteria.getName())); + } else { + return Collections.EMPTY_LIST; + } + } + + public List findAll() { + log.info("findAll"); + return new LinkedList(PERSONS.entrySet()); + } + + public Person findByPrimaryKey(String country, String company, + String fullname) { + log.info("findByPrimaryKey"); + if (PERSONS.get(fullname) != null) { + return (Person) PERSONS.get(fullname); + } else { + throw new EntryNotFoundException( + "Could not find person with name '" + fullname + "'"); + } + } + + public void update(Person person) { + Person actualPerson = findByPrimaryKey(null, null, person.getFullName()); + actualPerson.setCompany(person.getCompany()); + actualPerson.setCountry(person.getCountry()); + actualPerson.setDescription(person.getDescription()); + actualPerson.setDn(person.getDn()); + actualPerson.setPhone(person.getPhone()); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupContextMapper.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupContextMapper.java new file mode 100644 index 00000000..1c7438c8 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupContextMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.Arrays; +import java.util.List; +import java.util.TreeSet; + +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.support.DirContextOperations; + +/** + * Maps from DirContextOperations (DirContextAdapters, really) to Group objects. + * A DN for a group will be of the form cn=[name],ou=groups + * + * @author Ulrik Sandberg + */ +public class GroupContextMapper implements ContextMapper { + + /* + * @see org.springframework.ldap.ContextMapper#mapFromContext(java.lang.Object) + */ + public Object mapFromContext(Object ctx) { + DirContextOperations dirContext = (DirContextOperations) ctx; + Group group = new Group(); + group.setName(dirContext.getStringAttribute("cn")); + String[] membersArray = dirContext.getStringAttributes("uniqueMember"); + if (membersArray != null) { + List list = Arrays.asList(membersArray); + group.setMembers(new TreeSet(list)); + } + return group; + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDao.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDao.java new file mode 100644 index 00000000..3e39e544 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDao.java @@ -0,0 +1,40 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.List; + +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +/** + * Data Access Object interface for the Group entity. + * + * @author Ulrik Sandberg + */ +public interface GroupDao { + public void create(Group group); + + public void update(Group group); + + public void delete(Group group); + + public Group findByPrimaryKey(String name); + + public List findAll(); + + public List find(SearchCriteria criteria); +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDaoImpl.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDaoImpl.java new file mode 100644 index 00000000..8a1fca68 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/GroupDaoImpl.java @@ -0,0 +1,130 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.List; + +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapOperations; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.SearchCriteria; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DirContextOperations; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.ldap.support.filter.AndFilter; +import org.springframework.ldap.support.filter.EqualsFilter; +import org.springframework.ldap.support.filter.WhitespaceWildcardsFilter; + +/** + * Default implementation of GroupDao. This implementation uses + * DirContextOperations (DirContextAdapter really, but for mock testing purposes + * we use the interface) for managing attribute values. It has been specified in + * the Spring Context that the DirObjectFactory should be used when creating + * objects from contexts, which defaults to creating DirContextAdapter objects. + * This means that we can use a ContextMapper to map from the found contexts to + * our domain objects. + * + * @author Ulrik Sandberg + */ +public class GroupDaoImpl implements GroupDao { + + /** + * The template object that performs all data access work. + */ + LdapOperations ldapOperations; + + DistinguishedName buildDn(Group group) { + DistinguishedName dn = new DistinguishedName(); + dn.add("ou", "groups"); + dn.add("cn", group.getName()); + return dn; + } + + DirContextOperations setAttributes(DirContextOperations adapter, Group group) { + adapter.setAttributeValues("objectclass", new String[] { "top", + "groupOfUniqueNames" }); + adapter.setAttributeValue("cn", group.getName()); + if (group.getMembers() != null && group.getMembers().size() > 0) { + adapter.setAttributeValues("uniqueMember", group.getMembers() + .toArray(new String[0])); + } + return adapter; + } + + ContextMapper getContextMapper() { + return new GroupContextMapper(); + } + + /* + * @see org.springframework.ldap.samples.person.dao.GroupDao#create(org.springframework.ldap.samples.person.domain.Group) + */ + public void create(Group group) { + ldapOperations.bind(buildDn(group), setAttributes( + new DirContextAdapter(), group), null); + } + + /* + * @see org.springframework.ldap.samples.person.dao.GroupDao#delete(org.springframework.ldap.samples.person.domain.Group) + */ + public void delete(Group group) { + ldapOperations.unbind(buildDn(group)); + } + + /* + * @see org.springframework.ldap.samples.person.dao.GroupDao#find(org.springframework.ldap.samples.person.domain.SearchCriteria) + */ + public List find(SearchCriteria criteria) { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "groupOfUniqueNames")); + filter.and(new WhitespaceWildcardsFilter("cn", criteria.getName())); + return ldapOperations.search(DistinguishedName.EMPTY_PATH, filter + .encode(), getContextMapper()); + } + + /* + * @see org.springframework.ldap.samples.person.dao.GroupDao#findAll() + */ + public List findAll() { + EqualsFilter filter = new EqualsFilter("objectclass", + "groupOfUniqueNames"); + return ldapOperations.search(DistinguishedName.EMPTY_PATH, filter + .encode(), getContextMapper()); + } + + /* + * @see org.springframework.ldap.samples.person.dao.GroupDao#findByPrimaryKey(java.lang.String) + */ + public Group findByPrimaryKey(String name) { + DistinguishedName dn = new DistinguishedName("ou=groups"); + dn.add("cn", name); + return (Group) ldapOperations.lookup(dn, getContextMapper()); + } + + /* + * @see org.springframework.ldap.samples.person.dao.GroupDao#update(org.springframework.ldap.samples.person.domain.Group) + */ + public void update(Group group) { + DistinguishedName dn = buildDn(group); + DirContextOperations adapter = (DirContextOperations) ldapOperations + .lookup(dn); + adapter = setAttributes(adapter, group); + ldapOperations.modifyAttributes(dn, adapter.getModificationItems()); + } + + public void setLdapOperations(LdapOperations ldapOperations) { + this.ldapOperations = ldapOperations; + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonContextMapper.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonContextMapper.java new file mode 100644 index 00000000..cd4aa00b --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonContextMapper.java @@ -0,0 +1,68 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import javax.naming.NamingException; + +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.support.DirContextOperations; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.util.Assert; + +/** + * Maps from DirContextOperations (DirContextAdapters, really) to Person + * objects. A DN for a person will be of the form + * cn=[fullname],ou=[company],c=[country], so the values of + * these attributes must be extracted from the DN. For this, we use the + * DistinguishedName. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PersonContextMapper implements ContextMapper { + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + public Object mapFromContext(Object ctx) { + Assert.notNull(exceptionTranslator, "exceptionTranslator must be set"); + DirContextOperations dirContext = (DirContextOperations) ctx; + DistinguishedName dn = new DistinguishedName(dirContext.getDn()); + String fullDn; + try { + fullDn = dirContext.getNameInNamespace(); + } catch (NamingException e) { + throw exceptionTranslator.translate(e); + } + Person person = new Person(); + person.setDn(fullDn); + person.setCountry(dn.getLdapRdn(0).getComponent().getValue()); + person.setCompany(dn.getLdapRdn(1).getComponent().getValue()); + person.setFullName(dirContext.getStringAttribute("cn")); + person.setLastName(dirContext.getStringAttribute("sn")); + person.setDescription(dirContext.getStringAttributes("description")); + person.setPhone(dirContext.getStringAttribute("telephoneNumber")); + + return person; + } + + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDao.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDao.java new file mode 100644 index 00000000..9df1076b --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDao.java @@ -0,0 +1,42 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.List; + +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + + +/** + * Data Access Object interface for the Person entity. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface PersonDao { + public void create(Person person); + + public void update(Person person); + + public void delete(Person person); + + public Person findByPrimaryKey(String country, String company, String fullname); + + public List findAll(); + + public List find(SearchCriteria criteria); +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDaoImpl.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDaoImpl.java new file mode 100644 index 00000000..b3dd3bad --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/PersonDaoImpl.java @@ -0,0 +1,120 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.List; + +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapOperations; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DirContextOperations; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.ldap.support.filter.AndFilter; +import org.springframework.ldap.support.filter.EqualsFilter; +import org.springframework.ldap.support.filter.WhitespaceWildcardsFilter; + +/** + * Default implementation of PersonDao. This implementation uses + * DirContextOperations (DirContextAdapter really, but for mock testing purposes + * we use the interface) for managing attribute values. It has been specified in + * the Spring Context that the DirObjectFactory should be used when creating + * objects from contexts, which defaults to creating DirContextAdapter objects. + * This means that we can use a ContextMapper to map from the found contexts to + * our domain objects. This is especially useful since we in this case have + * properties in our domain objects that depend on parts of the DN. + * + * We could have worked with Attributes and an AttributesMapper implementation + * instead, but working with Attributes is a bore and also, working with + * AttributesMapper objects (or, indeed Attributes) does not give us access to + * the distinguished name. + * + * @author Mattias Arthursson + */ +public class PersonDaoImpl implements PersonDao { + + private LdapOperations ldapOperations; + + DistinguishedName buildDn(Person person) { + DistinguishedName dn = new DistinguishedName(); + dn.add("c", person.getCountry()); + dn.add("ou", person.getCompany()); + dn.add("cn", person.getFullName()); + return dn; + } + + DirContextOperations setAttributes(DirContextOperations adapter, + Person person) { + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", person.getFullName()); + adapter.setAttributeValue("sn", person.getLastName()); + adapter.setAttributeValues("description", person.getDescription()); + adapter.setAttributeValue("telephoneNumber", person.getPhone()); + return adapter; + } + + ContextMapper getContextMapper() { + PersonContextMapper personContextMapper = new PersonContextMapper(); + return personContextMapper; + } + + public void create(Person person) { + ldapOperations.bind(buildDn(person), setAttributes( + new DirContextAdapter(), person), null); + } + + public void update(Person person) { + DirContextOperations ctx = (DirContextOperations) ldapOperations + .lookup(buildDn(person)); + ldapOperations.modifyAttributes(buildDn(person), setAttributes(ctx, + person).getModificationItems()); + } + + public void delete(Person person) { + ldapOperations.unbind(buildDn(person)); + } + + public List findAll() { + EqualsFilter filter = new EqualsFilter("objectclass", "person"); + return ldapOperations.search(DistinguishedName.EMPTY_PATH, filter + .encode(), getContextMapper()); + } + + public Person findByPrimaryKey(String country, String company, + String fullname) { + + DistinguishedName dn = new DistinguishedName(); + dn.add("c", country); + dn.add("ou", company); + dn.add("cn", fullname); + + return (Person) ldapOperations.lookup(dn, getContextMapper()); + } + + public List find(SearchCriteria criteria) { + AndFilter andFilter = new AndFilter(); + andFilter.and(new EqualsFilter("objectclass", "person")); + andFilter.and(new WhitespaceWildcardsFilter("cn", criteria.getName())); + return ldapOperations.search(DistinguishedName.EMPTY_PATH, andFilter + .encode(), getContextMapper()); + } + + public void setLdapOperations(LdapOperations ldapOperations) { + this.ldapOperations = ldapOperations; + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/TraditionalPersonDaoImpl.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/TraditionalPersonDaoImpl.java new file mode 100644 index 00000000..f26fc5a0 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/dao/TraditionalPersonDaoImpl.java @@ -0,0 +1,228 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; + +import javax.naming.Context; +import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DirContextOperations; + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +/** + * Traditional implementation of PersonDao. This implementation uses the basic + * JNDI interfaces and classes {@link DirContext}, {@link Attributes}, + * {@link Attribute}, and {@link NamingEnumeration}. The purpose is to + * contrast this implementation with that of + * {@link org.springframework.ldap.samples.person.dao.PersonDaoImpl}. + * + * @author Ulrik Sandberg TODO Add search method so we can use a search page + */ +public class TraditionalPersonDaoImpl implements PersonDao { + + private String url; + + private String base; + + // TODO Rewrite using traditional tools + DirContextOperations getContextToBind(Person person) { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValue("objectclass", + new String[] { "top", "person" }); + adapter.setAttributeValue("cn", person.getFullName()); + adapter.setAttributeValue("sn", person.getLastName()); + adapter.setAttributeValue("description", person.getDescription()); + return adapter; + } + + // TODO Rewrite using traditional tools + public void create(Person person) { + // ldapOperations.bind(buildDn(person), getContextToBind(person), null); + } + + // TODO Rewrite using traditional tools + public void update(Person person) { + // ldapOperations.rebind(buildDn(person), getContextToBind(person), + // null); + } + + // TODO Rewrite using traditional tools + public void delete(Person person) { + // ldapOperations.unbind(buildDn(person)); + } + + /* + * @see org.springframework.ldap.samples.person.dao.PersonDao#findAll() + */ + public List findAll() { + DirContext ctx = createContext(); + + LinkedList list = new LinkedList(); + NamingEnumeration results = null; + try { + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + results = ctx.search("", "(objectclass=person)", controls); + + while (results.hasMore()) { + SearchResult searchResult = (SearchResult) results.next(); + String dn = searchResult.getName(); + Attributes attributes = searchResult.getAttributes(); + list.add(mapToPerson(dn, attributes)); + } + } catch (NameNotFoundException e) { + // The base context was not found, which basically means + // that the search did not return any results. Just clean up and + // exit. + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + return list; + } + + /* + * @see org.springframework.ldap.samples.person.dao.PersonDao#findByPrimaryKey(java.lang.String, + * java.lang.String, java.lang.String) + */ + public Person findByPrimaryKey(String country, String company, + String fullname) { + + DirContext ctx = createContext(); + String dn = buildDn(country, company, fullname); + try { + Attributes attributes = ctx.getAttributes(dn); + return mapToPerson(dn, attributes); + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + } + + /* + * @see org.springframework.ldap.samples.person.dao.PersonDao#find(org.springframework.ldap.samples.person.domain.SearchCriteria) + */ + public List find(SearchCriteria criteria) { + return null; + } + + private String buildDn(String country, String company, String fullname) { + StringBuffer sb = new StringBuffer(); + sb.append("cn="); + sb.append(fullname); + sb.append(","); + sb.append("ou="); + sb.append(company); + sb.append(","); + sb.append("c="); + sb.append(country); + String dn = sb.toString(); + return dn; + } + + private DirContext createContext() { + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + String tempUrl = createUrl(); + env.put(Context.PROVIDER_URL, tempUrl); + DirContext ctx; + try { + ctx = new InitialDirContext(env); + } catch (NamingException e) { + throw new RuntimeException(e); + } + return ctx; + } + + private Person mapToPerson(String dn, Attributes attributes) + throws NamingException { + Person person = new Person(); + person.setFullName((String) attributes.get("cn").get()); + person.setLastName((String) attributes.get("sn").get()); + Attribute descriptionAttribute = attributes.get("description"); + String[] description = new String[descriptionAttribute.size()]; + for (int i = 0; i < description.length; i++) { + description[i] = (String) descriptionAttribute.get(i); + } + person.setDescription(description); + person.setPhone((String) attributes.get("telephoneNumber").get()); + String countryMarker = ",c="; + String country = dn.substring(dn.lastIndexOf(countryMarker) + + countryMarker.length()); + person.setCountry(country); + String companyMarker = ",ou="; + String company = dn.substring(dn.lastIndexOf(companyMarker) + + companyMarker.length(), dn.lastIndexOf(countryMarker)); + person.setCompany(company); + return person; + } + + private String createUrl() { + String tempUrl = url; + if (!tempUrl.endsWith("/")) { + tempUrl += "/"; + } + if (StringUtils.isNotEmpty(base)) { + tempUrl += base; + } + return tempUrl; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setBase(String base) { + this.base = base; + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Group.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Group.java new file mode 100644 index 00000000..90b7de02 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Group.java @@ -0,0 +1,63 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import java.io.Serializable; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Simple class representing an access group. + * + * @author Ulrik Sandberg + */ +public class Group implements Serializable { + private static final long serialVersionUID = -360943117484570379L; + + private String name; + + private Set members = new TreeSet(); + + public Set getMembers() { + return members; + } + + public void setMembers(Set members) { + this.members = members; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean equals(Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + return EqualsBuilder.reflectionEquals(this, obj); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/GroupValidator.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/GroupValidator.java new file mode 100644 index 00000000..42f65b0e --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/GroupValidator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import org.springframework.util.StringUtils; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +/** + * Validates a Group domain object. + * + * @author Ulrik Sandberg + */ +public class GroupValidator implements Validator { + + public boolean supports(Class clazz) { + return clazz.equals(Group.class); + } + + public void validate(Object obj, Errors errors) { + Group group = (Group) obj; + if (!StringUtils.hasText(group.getName())) { + errors.reject("noName", "Please provide the group name"); + } + } +} \ No newline at end of file diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Person.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Person.java new file mode 100644 index 00000000..a3cb07c6 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/Person.java @@ -0,0 +1,121 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import java.io.Serializable; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.core.style.ToStringCreator; + +/** + * Simple class representing a single person. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class Person implements Serializable { + private static final long serialVersionUID = -8953862790009843528L; + + /** + * Needed when adding persons to groups, since groups require + * full distinguished names of their members. + */ + private String dn; + + private String fullName; + + private String lastName; + + private String[] description; + + private String country; + + private String company; + + private String phone; + + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String[] getDescription() { + return description; + } + + public void setDescription(String[] description) { + this.description = description; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getCompany() { + return company; + } + + public void setCompany(String company) { + this.company = company; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public boolean equals(Object obj) { + if (obj == null || getClass() != obj.getClass()) { + return false; + } + return EqualsBuilder.reflectionEquals(this, obj); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + public String toString() { + return new ToStringCreator(this).toString(); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/PersonValidator.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/PersonValidator.java new file mode 100644 index 00000000..d54a7c23 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/PersonValidator.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import org.springframework.util.StringUtils; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +public class PersonValidator implements Validator { + + public boolean supports(Class clazz) { + return clazz.equals(Person.class); + } + + public void validate(Object obj, Errors errors) { + Person person = (Person) obj; + if (!StringUtils.hasText(person.getFullName())) { + errors.reject("noName", "Please provide the full name"); + } + if (!StringUtils.hasText(person.getCompany())) { + errors.reject("noCompany", "Please provide the company"); + } + if (!StringUtils.hasText(person.getCountry())) { + errors.reject("noCountry", "Please provide the country"); + } + if (!StringUtils.hasText(person.getPhone())) { + errors.reject("noPhone", "Please provide the telephone number"); + } + } +} \ No newline at end of file diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteria.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteria.java new file mode 100644 index 00000000..6764d44d --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteria.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import java.io.Serializable; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.core.style.ToStringCreator; + +public class SearchCriteria implements Serializable { + + private static final long serialVersionUID = -4263208255805049113L; + + private String name = ""; + + public String getName() { + return name; + } + + public void setName(String firstName) { + this.name = firstName; + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + public boolean equals(Object obj) { + if (obj == null || getClass() != obj.getClass()) + return false; + return EqualsBuilder.reflectionEquals(this, obj); + } + + public String toString() { + return new ToStringCreator(this).append("name", name).toString(); + } +} \ No newline at end of file diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteriaValidator.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteriaValidator.java new file mode 100644 index 00000000..d297abd2 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/domain/SearchCriteriaValidator.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +/** + * Validates search chriteria. + * + * @author Ulrik Sandberg + * + */ +public class SearchCriteriaValidator implements Validator { + + /* + * (non-Javadoc) + * + * @see org.springframework.validation.Validator#supports(java.lang.Class) + */ + public boolean supports(Class clazz) { + return clazz.equals(SearchCriteria.class); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.validation.Validator#validate(java.lang.Object, + * org.springframework.validation.Errors) + */ + public void validate(Object obj, Errors errors) { + // SearchCriteria query = (SearchCriteria) obj; + // if (!StringUtils.hasText(query.getName())) { + // errors.reject("noCriteria", "Please provide some query criteria!"); + // } + } +} \ No newline at end of file diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupService.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupService.java new file mode 100644 index 00000000..42baa070 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupService.java @@ -0,0 +1,42 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.service; + +import java.util.List; +import java.util.Set; + +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +/** + * Example interface for a Group service. + * + * @author Ulrik Sandberg + */ +public interface GroupService { + + public void create(String name, Set members); + + public void update(Group group); + + public void delete(Group group); + + public Group findByPrimaryKey(String name); + + public List find(SearchCriteria criteria); + + public List findAll(); +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupServiceImpl.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupServiceImpl.java new file mode 100644 index 00000000..c11509ed --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/GroupServiceImpl.java @@ -0,0 +1,85 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.service; + +import java.util.List; +import java.util.Set; + +import org.springframework.ldap.samples.person.dao.GroupDao; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +/** + * Service implementation for managing the Group entity. + * + * @author Ulrik Sandberg + */ +public class GroupServiceImpl implements GroupService { + + private GroupDao groupDao; + + public void setGroupDao(GroupDao groupDao) { + this.groupDao = groupDao; + } + + /* + * @see org.springframework.ldap.samples.person.service.GroupService#create(java.lang.String, + * java.util.Set) + */ + public void create(String name, Set members) { + + Group group = new Group(); + group.setName(name); + group.setMembers(members); + + groupDao.create(group); + } + + /* + * @see org.springframework.ldap.samples.person.service.GroupService#update(org.springframework.ldap.samples.person.domain.Group) + */ + public void update(Group group) { + groupDao.update(group); + } + + /* + * @see org.springframework.ldap.samples.person.service.GroupService#delete(org.springframework.ldap.samples.person.domain.Group) + */ + public void delete(Group group) { + groupDao.delete(group); + } + + /* + * @see org.springframework.ldap.samples.person.service.GroupService#findByPrimaryKey(java.lang.String) + */ + public Group findByPrimaryKey(String name) { + return groupDao.findByPrimaryKey(name); + } + + /* + * @see org.springframework.ldap.samples.person.service.GroupService#findAll() + */ + public List findAll() { + return groupDao.findAll(); + } + + /* + * @see org.springframework.ldap.samples.person.service.GroupService#find(org.springframework.ldap.samples.person.domain.SearchCriteria) + */ + public List find(SearchCriteria criteria) { + return groupDao.find(criteria); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonService.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonService.java new file mode 100644 index 00000000..e5ed1f53 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonService.java @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.service; + +import java.util.List; + +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +/** + * Example interface for a Person service. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface PersonService { + + public void create(String country, String company, String fullname, + String lastname, String[] description); + + public void update(Person person); + + public void delete(Person person); + + public Person findByPrimaryKey(String country, String company, String name); + + public List find(SearchCriteria criteria); + + public List findAll(); +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonServiceImpl.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonServiceImpl.java new file mode 100644 index 00000000..67a76147 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/service/PersonServiceImpl.java @@ -0,0 +1,88 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.service; + +import java.util.List; + +import org.springframework.ldap.samples.person.dao.PersonDao; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; + +/** + * Service implementation for managing the Person entity. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PersonServiceImpl implements PersonService { + + private PersonDao personDao; + + /* + * @see org.springframework.ldap.samples.person.service.PersonService#create(java.lang.String, + * java.lang.String, java.lang.String, java.lang.String, + * java.lang.String[]) + */ + public void create(String country, String company, String fullname, + String lastname, String[] description) { + + Person person = new Person(); + person.setCountry(country); + person.setCompany(company); + person.setFullName(fullname); + person.setLastName(lastname); + person.setDescription(description); + + personDao.create(person); + } + + /* + * @see org.springframework.ldap.samples.person.service.PersonService#update(org.springframework.ldap.samples.person.domain.Person) + */ + public void update(Person person) { + personDao.update(person); + } + + public void delete(Person person) { + personDao.delete(person); + } + + /* + * @see org.springframework.ldap.samples.person.service.PersonService#findByPrimaryKey(java.lang.String, + * java.lang.String, java.lang.String) + */ + public Person findByPrimaryKey(String country, String company, String name) { + return personDao.findByPrimaryKey(country, company, name); + } + + /* + * @see org.springframework.ldap.samples.person.service.PersonService#findAll() + */ + public List findAll() { + return personDao.findAll(); + } + + /* + * @see org.springframework.ldap.samples.person.service.PersonService#find(org.springframework.ldap.samples.person.domain.SearchCriteria) + */ + public List find(SearchCriteria criteria) { + return personDao.find(criteria); + } + + public void setPersonDao(PersonDao personDao) { + this.personDao = personDao; + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditGroupFormAction.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditGroupFormAction.java new file mode 100644 index 00000000..3cf82aa5 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditGroupFormAction.java @@ -0,0 +1,103 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.web; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.commons.collections.CollectionUtils; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.service.GroupService; +import org.springframework.util.Assert; +import org.springframework.webflow.action.FormAction; +import org.springframework.webflow.execution.Event; +import org.springframework.webflow.execution.RequestContext; + +/** + * Action implementation that handles edit of a group. This action has the + * capability to add and remove members of the current Group form object. + * + * @author Ulrik Sandberg + */ +public class EditGroupFormAction extends FormAction { + + private GroupService groupService; + + public void setGroupService(GroupService groupService) { + this.groupService = groupService; + } + + /* + * @see org.springframework.webflow.action.FormAction#initAction() + */ + protected void initAction() { + super.initAction(); + Assert.notNull(groupService, "A GroupService object is required"); + } + + /* + * @see org.springframework.webflow.action.FormAction#createFormObject(org.springframework.webflow.execution.RequestContext) + */ + protected Object createFormObject(RequestContext context) throws Exception { + String name = context.getFlowScope().getRequiredString("name"); + Group group = groupService.findByPrimaryKey(name); + return group; + } + + /** + * Add the member in the member property to the form object + * members property. + * + * @param context + * RequestContext with parameters and attributes. + * @return The success event if member was added successfully + * @throws Exception + * if an unexpected error occurs + */ + public Event add(RequestContext context) throws Exception { + Group group = (Group) getFormObject(context); + Set members = group.getMembers(); + String member = (String) context.getRequestParameters().get("member"); + members.add(member); + return success(); + } + + /** + * Removes the members in the selectedMembers property from + * the form object members property. + * + * @param context + * RequestContext with parameters and attributes. + * @return The success event if members were removed + * successfully + * @throws Exception + * if an unexpected error occurs + */ + public Event remove(RequestContext context) throws Exception { + Group group = (Group) getFormObject(context); + Set members = group.getMembers(); + String[] selectedMembers = (String[]) context.getRequestParameters() + .getArray("selectedMembers"); + List membersToRemove = Arrays.asList(selectedMembers); + Collection adjustedMembers = CollectionUtils.subtract(members, + membersToRemove); + group.setMembers(new TreeSet(adjustedMembers)); + return success(); + } +} diff --git a/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditPersonFormAction.java b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditPersonFormAction.java new file mode 100644 index 00000000..027bbbf3 --- /dev/null +++ b/spring-ldap-person/src/main/java/org/springframework/ldap/samples/person/web/EditPersonFormAction.java @@ -0,0 +1,44 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.samples.person.web; + +import org.springframework.beans.PropertyEditorRegistry; +import org.springframework.beans.propertyeditors.StringArrayPropertyEditor; +import org.springframework.webflow.action.FormAction; +import org.springframework.webflow.execution.RequestContext; + +/** + * Action implementation that handles edit of a person. Registers appropriate + * property editors. + * + * @author Mattias Arthursson + * + */ +public class EditPersonFormAction extends FormAction { + + /* + * (non-Javadoc) + * + * @see org.springframework.webflow.action.FormAction#registerPropertyEditors(org.springframework.webflow.execution.RequestContext, + * org.springframework.beans.PropertyEditorRegistry) + */ + protected void registerPropertyEditors(RequestContext context, + PropertyEditorRegistry registry) { + registry.registerCustomEditor(String[].class, + new StringArrayPropertyEditor()); + } +} diff --git a/spring-ldap-person/src/main/java/overview.html b/spring-ldap-person/src/main/java/overview.html new file mode 100644 index 00000000..7d7ac9a3 --- /dev/null +++ b/spring-ldap-person/src/main/java/overview.html @@ -0,0 +1,3 @@ + +This document is the API specification for the Spring LDAP Person sample. + \ No newline at end of file diff --git a/spring-ldap-person/src/main/java/setup_data.ldif b/spring-ldap-person/src/main/java/setup_data.ldif new file mode 100644 index 00000000..08343e68 --- /dev/null +++ b/spring-ldap-person/src/main/java/setup_data.ldif @@ -0,0 +1,111 @@ +dn: ou=groups,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: cn=USER,ou=groups,dc=jayway,dc=se +objectclass: top +objectclass: groupOfUniqueNames +cn: USER +uniqueMember: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +uniqueMember: cn=Some Person,ou=company1,c=Norway,dc=jayway,dc=se +uniqueMember: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +uniqueMember: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se + +dn: cn=ADMIN,ou=groups,dc=jayway,dc=se +objectclass: top +objectclass: groupOfUniqueNames +cn: ADMIN +uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se + +dn: c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Sweden +description: The country of Sweden + +dn: c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Norway +description: The country of Norway + +dn: ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Sweden + +dn: ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company2 +description: Second company in Sweden + +dn: ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Norway + +dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person +userPassword: password +cn: Some Person +sn: Person +description: USER +telephoneNumber: +46 555-123456 + +dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person2 +userPassword: password +cn: Some Person2 +sn: Person2 +description: USER +description: ADMIN +telephoneNumber: +46 555-654321 + +dn: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person3 +userPassword: password +cn: Some Person3 +sn: Person3 +description: USER +telephoneNumber: +46 555-123654 + +dn: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person4 +userPassword: password +cn: Some Person +sn: Person +description: USER +telephoneNumber: +46 555-456321 + +dn: cn=Some Person,ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.norwegian +userPassword: password +cn: Some Person +sn: Person +description: USER +telephoneNumber: +45 555-654123 diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/apacheDsContext.xml b/spring-ldap-person/src/main/webapp/WEB-INF/apacheDsContext.xml new file mode 100644 index 00000000..17306fb2 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/apacheDsContext.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + simple + + + ${userName} + + + ${password} + + + + + + + + + + + + + + + + + + + + objectClass: top + objectClass: domain + objectClass: extensibleObject + dc: jayway + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml b/spring-ldap-person/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml new file mode 100644 index 00000000..e00e9996 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /ldaptemplate.htm*=ROLE_USER + + + + + diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/applicationContext.xml b/spring-ldap-person/src/main/webapp/WEB-INF/applicationContext.xml new file mode 100644 index 00000000..0554dc73 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/classes/log4j.properties b/spring-ldap-person/src/main/webapp/WEB-INF/classes/log4j.properties new file mode 100644 index 00000000..6724c59a --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/classes/log4j.properties @@ -0,0 +1,21 @@ +log4j.rootCategory=WARN, stdout, logfile + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${@PROJECT_WEBAPP_NAME@.root}/@PROJECT_WEBAPP_NAME@.log +log4j.appender.logfile.MaxFileSize=512KB + +# Keep three backup files +log4j.appender.logfile.MaxBackupIndex=3 +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout + +#Pattern to output : date priority [category] - line_separator +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n + +#Enable webflow debug logging +log4j.category.org.springframework.webflow=INFO +log4j.category.org.springframework.binding=INFO +log4j.category.org.springframework.ldap=INFO diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow-beans.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow-beans.xml new file mode 100644 index 00000000..1349b02c --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow-beans.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow.xml new file mode 100644 index 00000000..02ccab46 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-flow.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml new file mode 100644 index 00000000..fee7209b --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow.xml new file mode 100644 index 00000000..9e047e27 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/detail-group-flow.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/personmanager-flow.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/personmanager-flow.xml new file mode 100644 index 00000000..ab1c9d69 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/personmanager-flow.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow-beans.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow-beans.xml new file mode 100644 index 00000000..17f68c64 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow-beans.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow.xml new file mode 100644 index 00000000..32dda2c7 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-flow.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml new file mode 100644 index 00000000..e03b74ab --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow.xml b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow.xml new file mode 100644 index 00000000..eb8f83c2 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/flows/search-group-flow.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/editDetails.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/editDetails.jsp new file mode 100644 index 00000000..2da82db7 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/editDetails.jsp @@ -0,0 +1,53 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Edit Person Details

+
Please check form for invalid input
+
Name
Company
Country
Phone
Description
+ + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/editGroupDetails.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/editGroupDetails.jsp new file mode 100644 index 00000000..9747de4b --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/editGroupDetails.jsp @@ -0,0 +1,65 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Edit Group Details

+
Please check form for invalid input
+
Name
+
+ Members: +
+ +
+ + + + + + + +
+ +
+ +
+
+ + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/error.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/error.jsp new file mode 100644 index 00000000..0cb50f54 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/error.jsp @@ -0,0 +1,18 @@ +<%@ page session="false" %> + + + + + + +
Error
+
+
+

+ An error has occured! +

+
+
+
+ + diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeBottom.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeBottom.jsp new file mode 100644 index 00000000..3bb24aba --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeBottom.jsp @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeTop.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeTop.jsp new file mode 100644 index 00000000..4500d28d --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/includeTop.jsp @@ -0,0 +1,21 @@ +<%@ page contentType="text/html" %> +<%@ page session="false" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + +Search the Phonebook + + + + + + + + diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/menu.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/menu.jsp new file mode 100644 index 00000000..c3ae59fa --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/menu.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%@ include file="includeTop.jsp" %> + +
+
+ +
+ + + + + + ">Find and manage persons +
+ + + + + ">Find and manage groups +
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchForm.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchForm.jsp new file mode 100644 index 00000000..bc11a06d --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchForm.jsp @@ -0,0 +1,46 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
Person Search
+
+
+
Please provide valid search criteria
+
Name + +
+
+
+ + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupForm.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupForm.jsp new file mode 100644 index 00000000..90d61ba2 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupForm.jsp @@ -0,0 +1,46 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
Group Search
+
+
+
Please provide valid search criteria
+
Name + +
+
+
+ + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupResult.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupResult.jsp new file mode 100644 index 00000000..c4558287 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchGroupResult.jsp @@ -0,0 +1,52 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+
+ + + + + + + + + + + + + +
+ Matching Groups +
+
+
+ + + + + + + + + +
Name
+ + + + + + + ${group.name} + +
+
+ + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchResult.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchResult.jsp new file mode 100644 index 00000000..f6efc9ef --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/searchResult.jsp @@ -0,0 +1,60 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+
+ + + + + + + + + + + + + +
+ Matching Persons +
+
+
+ + + + + + + + + + + + + + + +
NameCompanyCountryPhone
+ + + + + + + + + ${person.fullName} + + ${person.company}${person.country}${person.phone}
+
+ + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showAddCandidates.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showAddCandidates.jsp new file mode 100644 index 00000000..58f6f3f3 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showAddCandidates.jsp @@ -0,0 +1,58 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+
+ + + + + + + + + + + + + +
+ Select a person to add +
+
+
+ + + + + + + + + + + + + + + +
NameCompanyCountryPhone
+ + + + + + + ${person.fullName} + + ${person.company}${person.country}${person.phone}
+
+ + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showDetails.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showDetails.jsp new file mode 100644 index 00000000..91a772ad --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showDetails.jsp @@ -0,0 +1,50 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Person Details

Name${person.fullName}
Company${person.company}
Country${person.country}
Phone${person.phone}
Description + + ${description}
+
+
+ + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showGroupDetails.jsp b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showGroupDetails.jsp new file mode 100644 index 00000000..5be81776 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/jsp/showGroupDetails.jsp @@ -0,0 +1,40 @@ +<%@ include file="includeTop.jsp" %> + +
+
+ +
+
+ + + + + + + + + + + + + + + + + +
Group Details

Name${group.name}
+
+ Members: +
+ + ${item}
+
+
+ + + +
+
+
+ +<%@ include file="includeBottom.jsp" %> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/ldap.properties b/spring-ldap-person/src/main/webapp/WEB-INF/ldap.properties new file mode 100644 index 00000000..eff9c99f --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/ldap.properties @@ -0,0 +1,4 @@ +urls=ldap://127.0.0.1 +userName=uid=admin,ou=system +password=secret +base=dc=jayway,dc=se diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-servlet.xml b/spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-servlet.xml new file mode 100644 index 00000000..6c63c297 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-servlet.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml b/spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml new file mode 100644 index 00000000..865daaf4 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/WEB-INF/web.xml b/spring-ldap-person/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..3c3ccb4d --- /dev/null +++ b/spring-ldap-person/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,50 @@ + + + + LdapTemplate Example + + contextConfigLocation + /WEB-INF/applicationContext.xml /WEB-INF/applicationContext-acegi-security.xml + + + + Acegi Filter Chain Proxy + org.acegisecurity.util.FilterToBeanProxy + + targetClass + org.acegisecurity.util.FilterChainProxy + + + + + Acegi Filter Chain Proxy + /* + + + + org.springframework.web.context.ContextLoaderListener + + + ldaptemplate + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + + /WEB-INF/ldaptemplate-servlet.xml + /WEB-INF/ldaptemplate-webflow-config.xml + + + 1 + + + ldaptemplate + *.htm + + + index.jsp + + \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/acegilogin.jsp b/spring-ldap-person/src/main/webapp/acegilogin.jsp new file mode 100644 index 00000000..e74d9848 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/acegilogin.jsp @@ -0,0 +1,52 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page import="org.acegisecurity.ui.AbstractProcessingFilter" %> +<%@ page import="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter" %> +<%@ page import="org.acegisecurity.AuthenticationException" %> + + + + Login + + + +

Login

+ +

Valid users: +

+

username some.person (USER), password password
+ username some.person2 (ADMIN), password password +

+ + <%-- this form-login-page form is also used as the + form-error-page to ask for a login again. + --%> + + + Your login attempt was not successful, try again.
+ Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %> +
+
+ +

+ + + + + + +
User: + + + + + + + + +
Password:
  +
+ +
+ + + diff --git a/spring-ldap-person/src/main/webapp/images/spring-logo.jpg b/spring-ldap-person/src/main/webapp/images/spring-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62be39835f2d980befae3ec961b6b10e7d1fca6f GIT binary patch literal 31339 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%0Dgs02_0)mtC0O8J0`s=@(mN;yyuh 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 HzQ6z3m$6-^ literal 0 HcmV?d00001 diff --git a/spring-ldap-person/src/main/webapp/images/webflow-logo.jpg b/spring-ldap-person/src/main/webapp/images/webflow-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed76bae066c665b63369a970cb47b9a038ceaee0 GIT binary patch literal 2383 zcmb7^dpy$%AIE>&%vf$i9HP0cHp^1E9jRCi8&0e>WxBgbhU-}$rtMxH_EBhNY@J`7m%0P*i{_ zLKPGhp^7k=q7qyK4p&x&YpbcNXy|JH^pmc(j*h+|3aP)v)IdkaXor#Mw(S^mj2_a$ z(gJOXLSxWBN?cbAPA7W6EFY(Fc<;? z0sj>YstATCfRr|NC5-^Lm|-r{QY4@C_puhcX?@HzH?q18) zylwd|M+c_Pdov=@TH)!V^S+evc@sV_ipx69k;u}BF5E1Gx1MqU%3eSEtT*^;(7H*z zG*s7R6Y;>`AOZJSAN_MMPtT?Np2d|T;`{aP%BEt?-GXWGHLb}Tt7$?;Hkqm7iV5Gt z$MNQjJF#%51^AZKDtfuUxnv>C+P*H=>n$U}5|$a!vHmD#?BQ%p%Dh^y;%n?1i`lot z3<7W!AUnar2%9VaB4~Tz5rnN)o*eSw>hmKZ_hl7wU`VzXgA@n1{J=DAqV&xk{$HT}TK3@jYSJ=sK&Txj$ViV$uHOH>q zp~-{d2V9-%;K$P;##v!&z;KtHRgL7oqbUO;78XE zG3zDF*Rd~J`-fVQS-n%G$*PSF!t`HxOgbPrnaetrv2P6VRV#^HPWRY95GKu*z`E_# zC$Wc^Zm_g>Zh7sRFbzle^!4$GwCCfDT*}9u#DMaNBD9O;qvnsw-Qf|miq7uTV0vUf zT>lrYsM20+QhmR+J%)s|8vWZ)RJ9mRwXoH_;M$h4_tWp*9o!LQ%ojnLVL6JCK8R#q z#WY~4A5@~!yV?yxBDDAKhqT6u$T{voeC?&nS?PY|k`X+OzU6P3b$H-m2GuvcZ*uhV z>R|Ujy0h);E;(Uw4u9V8T`24>(DQo#V0fxjsFRoBGm@1EyXDh86%_OfbZ1aesz0{t z17~)e+hKjQD%kG6z29qb4H5}x3Fe9v~!sJ+6JNxd)2StCX7Zv^M@#4;GcsG!_O~SbgEQ z9s0EE)ahBF!OQ24-}7cVCY-vCk4N3QhHpU&ID0y&ww;Dr3Yux`f&_W#{;HUF7gJU&qX*P@!j#ag(n#| ziw>AktRMR@Xo+Y_w^4PRam~m&WBWXq*Cae89D8u`v-h)ryB73Xw3NGxl-aqv6I`B;XqaWC3VL3wlROcWvV@CbaB2Ax3uhKUqzy^txo3( zEP6xYwR37&Ed?oG4gVx04A_2i;A7l{afpFKesczw_QbpNndD>Z@duS+!iU_jcBCiW z%3t+OC8NEO)>~<6bWD^1+g6EIHUv7yoFeZkQ+a$x(1!<%Fc zBuT-s#y!j^$2X)fPFY;H>cNIL&Drc5#y4I4vv*S@ui>l(FKzzyNqlDlhbWkUnoir| zY#(qYwud%bx0|&Xf2lCUvffSQh>7G3-WHK~XW%0Q|MESN@$sR()?JYKu`XXGwU3aC zx31jb%JqB!Au5xvP11*VoQ|P%t;RlkA_x3xrlJp>km)|W|1feJIvkTOVH?zi7nlBe zZ0KT>{fx(?T1V_V#<=PSt_8_IG()JP%#Y|=$vFCP^y+VODY^YPA=WdqH?Gpa#Y*L7 zU|cK}ecQ10?LnEqb|$k>x+oYKnH;8lEYoMJ+ZfR4KI#Os34L=XDCu7CBJRa*MP7P7 z%F<2UEZ$GRT-Gn`<=V9C`DarWzuPf83fP0#h-I{h)oI*0TX$0sgSa#2VN;ZEW;VN4 zZ@AB#8acGpw6CLdb!J*~t=hG0xcXbFxtpthuEigpoR1{l$Sxdn_*~^otTMj@2^Ht% zm(4e&6U=anbddIVE z)yzlkU=p#>4<6RJse#h*-=uQj0Q-nYC)Do2KiQqoN*_{^+p&{jmc+9ATIX6{h2`f= z`UE+9ntSJ32fHf&iAsgq&~B8))@1`S0#W`Ek4?r)4%yW z@N7q2#?9fBN^Hqv2Xw@yN5Y(voj!R<7hK0;EY|k6#)qV}*e7S{94)zxD55kp5J`gt z?5E2a5|7!Ma;nCJ$)t Pr%*S>8-PL?@;Cnig|{u< literal 0 HcmV?d00001 diff --git a/spring-ldap-person/src/main/webapp/index.jsp b/spring-ldap-person/src/main/webapp/index.jsp new file mode 100644 index 00000000..d8cc2b73 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/index.jsp @@ -0,0 +1,21 @@ +<%@ page session="true" %> <%-- make sure we have a session --%> + + + + + + +
PersonManager - A Spring LDAP Sample
+
+
+

+ Spring LDAP PersonManager +

+

+ This sample application illustrates the core features of Spring LDAP. +

+
+
+
+ + diff --git a/spring-ldap-person/src/main/webapp/logoff.jsp b/spring-ldap-person/src/main/webapp/logoff.jsp new file mode 100644 index 00000000..0231bcb9 --- /dev/null +++ b/spring-ldap-person/src/main/webapp/logoff.jsp @@ -0,0 +1,4 @@ +<% +session.invalidate(); +response.sendRedirect("index.jsp"); +%> \ No newline at end of file diff --git a/spring-ldap-person/src/main/webapp/style.css b/spring-ldap-person/src/main/webapp/style.css new file mode 100644 index 00000000..edc758ab --- /dev/null +++ b/spring-ldap-person/src/main/webapp/style.css @@ -0,0 +1,58 @@ +body { + width: 720px; + margin: 0px; + padding: 0px; +} + +div#logo { + width: 720px; + height: 73px; + background: #86AEA5; +} + +div#navigation { + width: 720px; + height: 15px; + background: #E2F3B8; + text-align: right; +} + +div#content { + width: 720px; + padding: 5px; +} + +div#insert { + width: 120; + float: right; + text-align: right; +} + +.buttonBar { + height: 1.5em; + text-align: right; +} + +div#copyright { + width: 720px; +} + +div#copyright p { + text-align: center; + font-family: Tahoma, sans-serif; + font-size: 75%; + color: div#336633; + margin-left: 5px; + font-weight: bold; + clear: both; +} + +.readOnly { + color: rgb(192, 192, 192); +} + +.error { + color: red; + font-weight: bold; + font-family: Arial, sans-serif; +} \ No newline at end of file diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/GroupDaoImplTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/GroupDaoImplTest.java new file mode 100644 index 00000000..b1f2dfb4 --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/GroupDaoImplTest.java @@ -0,0 +1,216 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.Collections; +import java.util.List; + +import javax.naming.directory.ModificationItem; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapOperations; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.SearchCriteria; +import org.springframework.ldap.support.DirContextOperations; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Unit tests for the GroupDaoImpl class. + * + * @author Ulrik Sandberg + */ +public class GroupDaoImplTest extends TestCase { + + private MockControl ldapOperationsControl; + + private LdapOperations ldapOperationsMock; + + private MockControl dirContextOperationsControl; + + private DirContextOperations dirContextOperationsMock; + + private MockControl contextMapperControl; + + private ContextMapper contextMapperMock; + + private GroupDaoImpl tested; + + private Group group; + + protected void setUp() throws Exception { + super.setUp(); + ldapOperationsControl = MockControl.createControl(LdapOperations.class); + ldapOperationsMock = (LdapOperations) ldapOperationsControl.getMock(); + + dirContextOperationsControl = MockControl + .createControl(DirContextOperations.class); + dirContextOperationsMock = (DirContextOperations) dirContextOperationsControl + .getMock(); + + contextMapperControl = MockControl.createControl(ContextMapper.class); + contextMapperMock = (ContextMapper) contextMapperControl.getMock(); + + group = new Group(); + + tested = new GroupDaoImpl() { + DirContextOperations setAttributes(DirContextOperations adapter, + Group p) { + assertSame(group, p); + return dirContextOperationsMock; + } + + DistinguishedName buildDn(Group p) { + assertSame(group, p); + return DistinguishedName.EMPTY_PATH; + } + + ContextMapper getContextMapper() { + return contextMapperMock; + } + }; + tested.setLdapOperations(ldapOperationsMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + ldapOperationsControl = null; + ldapOperationsMock = null; + + dirContextOperationsControl = null; + dirContextOperationsMock = null; + + contextMapperControl = null; + contextMapperMock = null; + + group = null; + tested = null; + } + + protected void replay() { + ldapOperationsControl.replay(); + dirContextOperationsControl.replay(); + contextMapperControl.replay(); + } + + protected void verify() { + ldapOperationsControl.verify(); + dirContextOperationsControl.verify(); + contextMapperControl.verify(); + } + + public void testBuildDn() { + tested = new GroupDaoImpl(); + Group group = new Group(); + group.setName("Some Group"); + + DistinguishedName dn = tested.buildDn(group); + + assertEquals("cn=Some Group, ou=groups", dn.toString()); + } + + public void testCreate() { + ldapOperationsMock.bind(DistinguishedName.EMPTY_PATH, + dirContextOperationsMock, null); + + replay(); + + tested.create(group); + + verify(); + } + + public void testUpdate() { + ldapOperationsControl + .expectAndReturn(ldapOperationsMock + .lookup(DistinguishedName.EMPTY_PATH), + dirContextOperationsMock); + ModificationItem[] modificationItems = new ModificationItem[0]; + dirContextOperationsControl.expectAndReturn(dirContextOperationsMock + .getModificationItems(), modificationItems); + ldapOperationsMock.modifyAttributes(DistinguishedName.EMPTY_PATH, + modificationItems); + + replay(); + + tested.update(group); + + verify(); + + } + + public void testDelete() { + ldapOperationsMock.unbind(DistinguishedName.EMPTY_PATH); + + replay(); + + tested.delete(group); + + verify(); + } + + public void testFindAll() { + List expectedList = Collections.singletonList(null); + ldapOperationsControl.expectAndReturn(ldapOperationsMock.search( + DistinguishedName.EMPTY_PATH, "(objectclass=groupOfUniqueNames)", + contextMapperMock), expectedList); + + replay(); + + List result = tested.findAll(); + + verify(); + + assertSame(expectedList, result); + } + + public void testFindByPrimaryKey() { + DistinguishedName dn = new DistinguishedName( + "cn=Some Group, ou=groups"); + + ldapOperationsControl.expectAndReturn(ldapOperationsMock.lookup(dn, + contextMapperMock), group); + + replay(); + + Group result = tested.findByPrimaryKey("Some Group"); + + verify(); + + assertSame(group, result); + } + + public void testFind_Name() { + List expectedList = Collections.singletonList(null); + ldapOperationsControl.expectAndReturn(ldapOperationsMock.search( + DistinguishedName.EMPTY_PATH, + "(&(objectclass=groupOfUniqueNames)(cn=*some*))", contextMapperMock), + expectedList); + + replay(); + + SearchCriteria criteria = new SearchCriteria(); + criteria.setName("some"); + List result = tested.find(criteria); + + verify(); + + assertSame(expectedList, result); + } +} diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/PersonDaoImplTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/PersonDaoImplTest.java new file mode 100644 index 00000000..07d89105 --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/dao/PersonDaoImplTest.java @@ -0,0 +1,221 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.dao; + +import java.util.Collections; +import java.util.List; + +import javax.naming.directory.ModificationItem; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapOperations; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; +import org.springframework.ldap.support.DirContextOperations; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Unit tests for the PersonDaoImpl class. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PersonDaoImplTest extends TestCase { + + private MockControl ldapOperationsControl; + + private LdapOperations ldapOperationsMock; + + private MockControl dirContextOperationsControl; + + private DirContextOperations dirContextOperationsMock; + + private MockControl contextMapperControl; + + private ContextMapper contextMapperMock; + + private PersonDaoImpl tested; + + private Person person; + + protected void setUp() throws Exception { + super.setUp(); + ldapOperationsControl = MockControl.createControl(LdapOperations.class); + ldapOperationsMock = (LdapOperations) ldapOperationsControl.getMock(); + + dirContextOperationsControl = MockControl + .createControl(DirContextOperations.class); + dirContextOperationsMock = (DirContextOperations) dirContextOperationsControl + .getMock(); + + contextMapperControl = MockControl.createControl(ContextMapper.class); + contextMapperMock = (ContextMapper) contextMapperControl.getMock(); + + person = new Person(); + + tested = new PersonDaoImpl() { + DirContextOperations setAttributes(DirContextOperations adapter, + Person p) { + assertSame(person, p); + return dirContextOperationsMock; + } + + DistinguishedName buildDn(Person p) { + assertSame(person, p); + return DistinguishedName.EMPTY_PATH; + } + + ContextMapper getContextMapper() { + return contextMapperMock; + } + }; + tested.setLdapOperations(ldapOperationsMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + ldapOperationsControl = null; + ldapOperationsMock = null; + + dirContextOperationsControl = null; + dirContextOperationsMock = null; + + contextMapperControl = null; + contextMapperMock = null; + + person = null; + tested = null; + } + + protected void replay() { + ldapOperationsControl.replay(); + dirContextOperationsControl.replay(); + contextMapperControl.replay(); + } + + protected void verify() { + ldapOperationsControl.verify(); + dirContextOperationsControl.verify(); + contextMapperControl.verify(); + } + + public void testBuildDn() { + tested = new PersonDaoImpl(); + Person person = new Person(); + person.setCountry("Sweden"); + person.setCompany("Some company"); + person.setFullName("Some Person"); + + DistinguishedName dn = tested.buildDn(person); + + assertEquals("cn=Some Person, ou=Some company, c=Sweden", dn.toString()); + } + + public void testCreate() { + ldapOperationsMock.bind(DistinguishedName.EMPTY_PATH, + dirContextOperationsMock, null); + + replay(); + + tested.create(person); + + verify(); + } + + public void testUpdate() { + ldapOperationsControl + .expectAndReturn(ldapOperationsMock + .lookup(DistinguishedName.EMPTY_PATH), + dirContextOperationsMock); + ModificationItem[] modificationItems = new ModificationItem[0]; + dirContextOperationsControl.expectAndReturn(dirContextOperationsMock + .getModificationItems(), modificationItems); + ldapOperationsMock.modifyAttributes(DistinguishedName.EMPTY_PATH, + modificationItems); + + replay(); + + tested.update(person); + + verify(); + + } + + public void testDelete() { + ldapOperationsMock.unbind(DistinguishedName.EMPTY_PATH); + + replay(); + + tested.delete(person); + + verify(); + } + + public void testFindAll() { + List expectedList = Collections.singletonList(null); + ldapOperationsControl.expectAndReturn(ldapOperationsMock.search( + DistinguishedName.EMPTY_PATH, "(objectclass=person)", + contextMapperMock), expectedList); + + replay(); + + List result = tested.findAll(); + + verify(); + + assertSame(expectedList, result); + } + + public void testFindByPrimaryKey() { + DistinguishedName dn = new DistinguishedName( + "cn=Some Person, ou=Some company, c=Sweden"); + + ldapOperationsControl.expectAndReturn(ldapOperationsMock.lookup(dn, + contextMapperMock), person); + + replay(); + + Person result = tested.findByPrimaryKey("Sweden", "Some company", + "Some Person"); + + verify(); + + assertSame(person, result); + + } + + public void testFind_Name() { + List expectedList = Collections.singletonList(null); + ldapOperationsControl.expectAndReturn(ldapOperationsMock.search( + DistinguishedName.EMPTY_PATH, + "(&(objectclass=person)(cn=*some*))", contextMapperMock), + expectedList); + + replay(); + + SearchCriteria criteria = new SearchCriteria(); + criteria.setName("some"); + List result = tested.find(criteria); + + verify(); + + assertSame(expectedList, result); + } +} diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/GroupTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/GroupTest.java new file mode 100644 index 00000000..a9ab3cd4 --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/GroupTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.domain; + +import java.util.Collections; +import java.util.Set; + +import junit.framework.TestCase; + +import com.gargoylesoftware.base.testing.EqualsTester; + +/** + * Unit tests for the Group class. + * + * @author Ulrik Sandberg + */ +public class GroupTest extends TestCase { + + public void testEquals() { + Set members = Collections.singleton("some dn"); + Set differentMembers = Collections.singleton("other dn"); + Group original = new Group(); + original.setName("some name"); + original.setMembers(members); + Group identical = new Group(); + identical.setName("some name"); + identical.setMembers(members); + Group different = new Group(); + different.setName("some name"); + different.setMembers(differentMembers); + Group subclass = new Group() { + private static final long serialVersionUID = 1L; + }; + subclass.setName("some name"); + subclass.setMembers(members); + new EqualsTester(original, identical, different, subclass); + } +} diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/PersonTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/PersonTest.java new file mode 100644 index 00000000..f3f34ef7 --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/PersonTest.java @@ -0,0 +1,25 @@ +package org.springframework.ldap.samples.person.domain; + +import com.gargoylesoftware.base.testing.EqualsTester; + +import junit.framework.TestCase; + +public class PersonTest extends TestCase { + + public void testEquals() { + Person original = new Person(); + original.setFullName("some name"); + original.setCompany("some company"); + Person identical = new Person(); + identical.setFullName("some name"); + identical.setCompany("some company"); + Person different = new Person(); + different.setFullName("other name"); + different.setCompany("some company"); + Person subclass = new Person() { + private static final long serialVersionUID = 1L;}; + subclass.setFullName("some name"); + subclass.setCompany("some company"); + new EqualsTester(original, identical, different, subclass); + } +} diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/SearchCriteriaTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/SearchCriteriaTest.java new file mode 100644 index 00000000..4f98a6ab --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/domain/SearchCriteriaTest.java @@ -0,0 +1,21 @@ +package org.springframework.ldap.samples.person.domain; + +import junit.framework.TestCase; + +import com.gargoylesoftware.base.testing.EqualsTester; + +public class SearchCriteriaTest extends TestCase { + + public void testEquals() { + SearchCriteria original = new SearchCriteria(); + original.setName("some"); + SearchCriteria identical = new SearchCriteria(); + identical.setName("some"); + SearchCriteria different = new SearchCriteria(); + different.setName("other"); + SearchCriteria subclass = new SearchCriteria() { + private static final long serialVersionUID = 1L;}; + subclass.setName("some"); + new EqualsTester(original, identical, different, subclass); + } +} diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/service/PersonServiceImplTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/service/PersonServiceImplTest.java new file mode 100644 index 00000000..efae0517 --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/service/PersonServiceImplTest.java @@ -0,0 +1,162 @@ +/* + * Copyright 2005-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.samples.person.service; + +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.samples.person.dao.PersonDao; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; +import org.springframework.ldap.samples.person.service.PersonServiceImpl; + +/** + * Unit tests for the PersonServiceImpl class. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PersonServiceImplTest extends TestCase { + + private MockControl personDaoControl; + + private PersonDao personDaoMock; + + private PersonServiceImpl tested; + + protected void setUp() throws Exception { + super.setUp(); + personDaoControl = MockControl.createControl(PersonDao.class); + personDaoMock = (PersonDao) personDaoControl.getMock(); + + tested = new PersonServiceImpl(); + tested.setPersonDao(personDaoMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + personDaoControl = null; + personDaoMock = null; + + tested = null; + } + + protected void replay() { + personDaoControl.replay(); + } + + protected void verify() { + personDaoControl.verify(); + } + + public void testCreate() { + Person person = setupPerson(); + + personDaoMock.create(person); + + replay(); + + tested.create("Sweden", "Some company", "Some Person", "Person", + new String[] { "Some description" }); + + verify(); + } + + private Person setupPerson() { + Person person = new Person(); + person.setCountry("Sweden"); + person.setCompany("Some company"); + person.setFullName("Some Person"); + person.setLastName("Person"); + person.setDescription(new String[] { "Some description" }); + return person; + } + + public void testUpdate() { + Person person = setupPerson(); + + personDaoMock.update(person); + + replay(); + + tested.update(person); + + verify(); + } + + public void testDelete() { + Person person = setupPerson(); + + personDaoMock.update(person); + + replay(); + + tested.update(person); + + verify(); + } + + public void testFindByPrimaryKey() { + Person person = new Person(); + + personDaoControl.expectAndReturn(personDaoMock.findByPrimaryKey( + "Sweden", "Some company", "Some Person"), person); + + replay(); + + Person result = tested.findByPrimaryKey("Sweden", "Some company", + "Some Person"); + + verify(); + + assertSame(person, result); + } + + public void testFindAll() { + List expected = Collections.singletonList(null); + + personDaoControl.expectAndReturn(personDaoMock.findAll(), expected); + + replay(); + + List actual = tested.findAll(); + + verify(); + + assertSame(expected, actual); + } + + public void testFind() { + List expected = Collections.singletonList(null); + + SearchCriteria criteria = new SearchCriteria(); + criteria.setName("some"); + personDaoControl + .expectAndReturn(personDaoMock.find(criteria), expected); + + replay(); + + List actual = tested.find(criteria); + + verify(); + + assertSame(expected, actual); + } +} diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/DetailFlowExecutionTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/DetailFlowExecutionTest.java new file mode 100644 index 00000000..23b97f84 --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/DetailFlowExecutionTest.java @@ -0,0 +1,152 @@ +package org.springframework.ldap.samples.person.web; + +import org.easymock.MockControl; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.service.PersonService; +import org.springframework.webflow.core.collection.LocalAttributeMap; +import org.springframework.webflow.core.collection.MutableAttributeMap; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.execution.support.ApplicationView; +import org.springframework.webflow.test.MockFlowServiceLocator; +import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests; + +public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests { + + private MockControl personServiceControl; + + private PersonService personServiceMock; + + private MutableAttributeMap attributeMap; + + protected void setUp() throws Exception { + super.setUp(); + + personServiceControl = MockControl.createControl(PersonService.class); + personServiceMock = (PersonService) personServiceControl.getMock(); + + attributeMap = new LocalAttributeMap(); + attributeMap.put("country", "Sweden"); + attributeMap.put("company", "company1"); + attributeMap.put("name", "Keith Donald"); + } + + protected void tearDown() throws Exception { + super.tearDown(); + personServiceControl = null; + personServiceMock = null; + } + + protected void replay() { + personServiceControl.replay(); + } + + protected void verify() { + personServiceControl.verify(); + } + + public void testStartFlow() { + expectFindByPrimaryKey(); + replay(); + + ApplicationView view = applicationView(startFlow(attributeMap)); + + verify(); + assertCurrentStateEquals("displayDetails"); + assertViewNameEquals("showDetails", view); + assertModelAttributeNotNull("person", view); + } + + public void testBack() { + expectFindByPrimaryKey(); + replay(); + + startFlow(attributeMap); + signalEvent("back"); + + verify(); + assertFlowExecutionEnded(); + } + + public void testEdit() { + expectFindByPrimaryKey(2); + replay(); + + startFlow(attributeMap); + ApplicationView view = applicationView(signalEvent("edit")); + + verify(); + assertCurrentStateEquals("editDetails"); + assertViewNameEquals("editDetails", view); + assertModelAttributeNotNull("person", view); + } + + public void testCancel() { + expectFindByPrimaryKey(3); + replay(); + + startFlow(attributeMap); + signalEvent("edit"); + ApplicationView view = applicationView(signalEvent("cancel")); + + verify(); + assertCurrentStateEquals("displayDetails"); + assertViewNameEquals("showDetails", view); + assertModelAttributeNotNull("person", view); + } + + public void testSubmit() { + expectFindByPrimaryKey(3); + expectUpdate(); + replay(); + + startFlow(attributeMap); + signalEvent("edit"); + ApplicationView view = applicationView(signalEvent("submit")); + + verify(); + assertCurrentStateEquals("displayDetails"); + assertViewNameEquals("showDetails", view); + assertModelAttributeNotNull("person", view); + } + + private void expectFindByPrimaryKey() { + expectFindByPrimaryKey(1); + } + + private void expectFindByPrimaryKey(int times) { + Person person = setupPerson(); + + personServiceControl.expectAndReturn(personServiceMock + .findByPrimaryKey("Sweden", "company1", "Keith Donald"), + person, times); + } + + private void expectUpdate() { + Person person = setupPerson(); + personServiceMock.update(person); + } + + private Person setupPerson() { + Person person = new Person(); + person.setFullName("Keith Donald"); + person.setCompany("company1"); + person.setCountry("Sweden"); + person.setPhone("some phone"); + person.setLastName("Donald"); + return person; + } + + /* + * @see org.springframework.webflow.test.execution.AbstractExternalizedFlowExecutionTests#getFlowDefinitionResource() + */ + protected FlowDefinitionResource getFlowDefinitionResource() { + return createFlowDefinitionResource("src/main/webapp/WEB-INF/flows/detail-flow.xml"); + } + + /* + * @see org.springframework.webflow.test.execution.AbstractExternalizedFlowExecutionTests#registerMockServices(org.springframework.webflow.test.MockFlowServiceLocator) + */ + protected void registerMockServices(MockFlowServiceLocator serviceRegistry) { + serviceRegistry.registerBean("personService", personServiceMock); + } +} \ No newline at end of file diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/PersonManagerFlowExecutionTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/PersonManagerFlowExecutionTest.java new file mode 100644 index 00000000..0d781cfe --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/PersonManagerFlowExecutionTest.java @@ -0,0 +1,180 @@ +package org.springframework.ldap.samples.person.web; + +import java.util.Collections; + +import org.easymock.MockControl; +import org.springframework.binding.mapping.AttributeMapper; +import org.springframework.binding.mapping.MappingContext; +import org.springframework.ldap.samples.person.domain.Group; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.service.GroupService; +import org.springframework.ldap.samples.person.service.PersonService; +import org.springframework.webflow.core.collection.AttributeMap; +import org.springframework.webflow.core.collection.MutableAttributeMap; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.engine.EndState; +import org.springframework.webflow.engine.Flow; +import org.springframework.webflow.execution.support.ApplicationView; +import org.springframework.webflow.test.MockFlowServiceLocator; +import org.springframework.webflow.test.MockParameterMap; +import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests; + +public class PersonManagerFlowExecutionTest extends + AbstractXmlFlowExecutionTests { + + private MockControl personServiceControl; + + private PersonService personServiceMock; + + private MockControl groupServiceControl; + + private GroupService groupServiceMock; + + protected void setUp() throws Exception { + super.setUp(); + + personServiceControl = MockControl.createControl(PersonService.class); + personServiceMock = (PersonService) personServiceControl.getMock(); + + groupServiceControl = MockControl.createControl(GroupService.class); + groupServiceMock = (GroupService) groupServiceControl.getMock(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + personServiceControl = null; + personServiceMock = null; + groupServiceControl = null; + groupServiceMock = null; + } + + protected void replay() { + personServiceControl.replay(); + groupServiceControl.replay(); + } + + protected void verify() { + personServiceControl.verify(); + groupServiceControl.verify(); + } + + public void testStartFlow() { + ApplicationView view = applicationView(startFlow()); + assertCurrentStateEquals("displayMenu"); + assertViewNameEquals("menu", view); + } + + public void testFindPerson() { + startFlow(); + ApplicationView view = applicationView(signalEvent("findPerson")); + assertCurrentStateEquals("displayResults"); + assertViewNameEquals("searchResult", view); + assertModelAttributeCollectionSize(1, "results", view); + } + + public void testNewSearch() { + startFlow(); + signalEvent("findPerson"); + ApplicationView view = applicationView(signalEvent("newSearch")); + assertCurrentStateEquals("displayResults"); + assertViewNameEquals("searchResult", view); + assertModelAttributeCollectionSize(1, "results", view); + } + + public void testSelectValidResult() { + startFlow(); + signalEvent("findPerson"); + + MockParameterMap parameters = new MockParameterMap(); + parameters = new MockParameterMap(); + parameters.put("name", "Keith Donald"); + parameters.put("company", "company1"); + parameters.put("country", "Sweden"); + ApplicationView view = applicationView(signalEvent("select", parameters)); + + assertCurrentStateEquals("displayResults"); + assertViewNameEquals("searchResult", view); + assertModelAttributeCollectionSize(1, "results", view); + } + + /* + * @see org.springframework.webflow.test.execution.AbstractExternalizedFlowExecutionTests#getFlowDefinitionResource() + */ + protected FlowDefinitionResource getFlowDefinitionResource() { + return createFlowDefinitionResource("src/main/webapp/WEB-INF/flows/personmanager-flow.xml"); + } + + /* + * @see org.springframework.webflow.test.execution.AbstractExternalizedFlowExecutionTests#registerMockServices(org.springframework.webflow.test.MockFlowServiceLocator) + */ + protected void registerMockServices(MockFlowServiceLocator serviceRegistry) { + Flow mockSearchFlow = new Flow("search-flow"); + + // test responding to finish result + EndState endState = new EndState(mockSearchFlow, "finish"); + // Simulate a search result of one item + endState.setOutputMapper(new AttributeMapper() { + public void map(Object source, Object target, MappingContext context) { + MutableAttributeMap outputMap = (MutableAttributeMap) target; + outputMap.put("results", Collections + .singletonList(new Person())); + } + }); + + serviceRegistry.registerSubflow(mockSearchFlow); + + Flow mockDetailFlow = new Flow("detail-flow"); + mockDetailFlow.setInputMapper(new AttributeMapper() { + public void map(Object source, Object target, MappingContext context) { + String name = "Keith Donald"; + String company = "company1"; + String country = "Sweden"; + assertEquals("name '" + name + + "' not provided as input by calling search flow", + name, ((AttributeMap) source).get("name")); + assertEquals("company '" + company + + "' not provided as input by calling search flow", + company, ((AttributeMap) source).get("company")); + assertEquals("company '" + country + + "' not provided as input by calling search flow", + country, ((AttributeMap) source).get("country")); + } + }); + // test responding to finish result + new EndState(mockDetailFlow, "finish"); + + serviceRegistry.registerSubflow(mockDetailFlow); + + Flow mockSearchGroupFlow = new Flow("search-group-flow"); + + // test responding to finish result + EndState endStateSearchGroup = new EndState(mockSearchGroupFlow, "finish"); + // Simulate a search result of one item + endStateSearchGroup.setOutputMapper(new AttributeMapper() { + public void map(Object source, Object target, MappingContext context) { + MutableAttributeMap outputMap = (MutableAttributeMap) target; + outputMap.put("groups", Collections + .singletonList(new Group())); + } + }); + + serviceRegistry.registerSubflow(mockSearchGroupFlow); + + Flow mockDetailGroupFlow = new Flow("detail-group-flow"); + mockDetailGroupFlow.setInputMapper(new AttributeMapper() { + public void map(Object source, Object target, MappingContext context) { + String name = "Some Group"; + assertEquals("name '" + name + + "' not provided as input by calling search group flow", + name, ((AttributeMap) source).get("name")); + } + }); + // test responding to finish result + new EndState(mockDetailGroupFlow, "finish"); + + serviceRegistry.registerSubflow(mockDetailGroupFlow); + + serviceRegistry.registerBean("groupService", groupServiceMock); + serviceRegistry.registerBean("personService", personServiceMock); + } +} \ No newline at end of file diff --git a/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/SearchFlowExecutionTest.java b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/SearchFlowExecutionTest.java new file mode 100644 index 00000000..46a5cd4e --- /dev/null +++ b/spring-ldap-person/src/test/java/org/springframework/ldap/samples/person/web/SearchFlowExecutionTest.java @@ -0,0 +1,79 @@ +package org.springframework.ldap.samples.person.web; + +import java.util.Collections; + +import org.easymock.MockControl; +import org.springframework.ldap.samples.person.domain.Person; +import org.springframework.ldap.samples.person.domain.SearchCriteria; +import org.springframework.ldap.samples.person.service.PersonService; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.execution.support.ApplicationView; +import org.springframework.webflow.test.MockFlowServiceLocator; +import org.springframework.webflow.test.MockParameterMap; +import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests; + +public class SearchFlowExecutionTest extends AbstractXmlFlowExecutionTests { + + private MockControl personServiceControl; + + private PersonService personServiceMock; + + protected void setUp() throws Exception { + super.setUp(); + + personServiceControl = MockControl.createControl(PersonService.class); + personServiceMock = (PersonService) personServiceControl.getMock(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + personServiceControl = null; + personServiceMock = null; + } + + protected void replay() { + personServiceControl.replay(); + } + + protected void verify() { + personServiceControl.verify(); + } + + public void testStartFlow() { + ApplicationView view = applicationView(startFlow()); + assertCurrentStateEquals("enterCriteria"); + assertViewNameEquals("searchForm", view); + assertModelAttributeNotNull("searchCriteria", view); + } + + public void testCriteriaSubmitSuccess() { + SearchCriteria searchCriteria = new SearchCriteria(); + searchCriteria.setName("Keith"); + personServiceControl.expectAndReturn(personServiceMock + .find(searchCriteria), Collections.singletonList(new Person())); + replay(); + + startFlow(); + MockParameterMap parameters = new MockParameterMap(); + parameters.put("name", "Keith"); + signalEvent("search", parameters); + + verify(); + + assertFlowExecutionEnded(); + } + + /* + * @see org.springframework.webflow.test.execution.AbstractExternalizedFlowExecutionTests#getFlowDefinitionResource() + */ + protected FlowDefinitionResource getFlowDefinitionResource() { + return createFlowDefinitionResource("src/main/webapp/WEB-INF/flows/search-flow.xml"); + } + + /* + * @see org.springframework.webflow.test.execution.AbstractExternalizedFlowExecutionTests#registerMockServices(org.springframework.webflow.test.MockFlowServiceLocator) + */ + protected void registerMockServices(MockFlowServiceLocator serviceRegistry) { + serviceRegistry.registerBean("personService", personServiceMock); + } +} \ No newline at end of file diff --git a/spring-ldap-person/trifork.map b/spring-ldap-person/trifork.map new file mode 100644 index 00000000..da11cac9 --- /dev/null +++ b/spring-ldap-person/trifork.map @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/spring-ldap/.checkstyle b/spring-ldap/.checkstyle new file mode 100644 index 00000000..c046ce20 --- /dev/null +++ b/spring-ldap/.checkstyle @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/spring-ldap/.classpath b/spring-ldap/.classpath new file mode 100644 index 00000000..cdaaac28 --- /dev/null +++ b/spring-ldap/.classpath @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap/.project b/spring-ldap/.project new file mode 100644 index 00000000..33c7cb5a --- /dev/null +++ b/spring-ldap/.project @@ -0,0 +1,34 @@ + + + spring-ldap + + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.ibm.etools.validation.validationbuilder + + + + + com.ibm.etools.ctc.serviceprojectbuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + com.ibm.etools.ctc.javaprojectnature + + diff --git a/spring-ldap/.settings/org.eclipse.jdt.core.prefs b/spring-ldap/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..a923f3d7 --- /dev/null +++ b/spring-ldap/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,248 @@ +#Sun Jul 02 11:21:34 EDT 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/spring-ldap/.settings/org.eclipse.jdt.ui.prefs b/spring-ldap/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000..21ae7c07 --- /dev/null +++ b/spring-ldap/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Fri Apr 21 13:43:14 CEST 2006 +eclipse.preferences.version=1 +formatter_settings_version=10 diff --git a/spring-ldap/.springBeans b/spring-ldap/.springBeans new file mode 100644 index 00000000..f9aa76ca --- /dev/null +++ b/spring-ldap/.springBeans @@ -0,0 +1,25 @@ + + + + src/iutest/conf/ldapTemplateBaseSuffixTestContext.xml + src/iutest/conf/ldapTemplateTestContext.xml + + + + iutest with base + false + false + + src/iutest/conf/ldapTemplateBaseSuffixTestContext.xml + + + + iutest + false + false + + src/iutest/conf/ldapTemplateTestContext.xml + + + + diff --git a/spring-ldap/build.xml b/spring-ldap/build.xml new file mode 100644 index 00000000..d9d767cb --- /dev/null +++ b/spring-ldap/build.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Unit test report has been generated. +The HTML report is ${target.testresults.html.dir}/index.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap/changelog.txt b/spring-ldap/changelog.txt new file mode 100644 index 00000000..760efdc3 --- /dev/null +++ b/spring-ldap/changelog.txt @@ -0,0 +1,212 @@ +Spring LDAP CHANGELOG +===================== +http://www.springframework.org/ldap + +http://www.ietf.org/rfc/rfc2251.txt +http://www.ietf.org/rfc/rfc2252.txt +http://www.ietf.org/rfc/rfc2253.txt +http://www.ietf.org/rfc/rfc2254.txt +http://www.ietf.org/rfc/rfc2255.txt +http://www.ietf.org/rfc/rfc2256.txt +http://www.ietf.org/rfc/rfc2696.txt + +Changes in version 1.1.2 (1.12.2006) +------------------------------------------- +* Fixed problem with DirContextAdapter.getNameInNameSpace. Now it really + returns the full DN. + +* There is now a wrapper class called PagedResult, which can be used to + wrap the resulting list and the PagedResultsCookie after using + PagedResultsRequestControl. + +* The actual cookie in PagedResultsCookie is now immutable. + +* The person sample is now a Spring WebFlow application, where the user + can manage persons and standard LDAP access groups. + +* Improved javadoc for DefaultDirObjectFactory and DistinguishedName. + +* Upgraded Spring to 2.0.1 internally. Spring 1.2.8 is still supported. + +Changes in version 1.1.1 (18.11.2006) +------------------------------------------- +* Added capability to use server-side controls in search by leveraging + DirContextProcessor. + +* Added generic DirContextProcessor that is run before and after a search. + +* Added paged search result functionality in PagedResultsRequestControl, + which is an implementation of DirContextProcessor. + +* Fixed problem with DirContextAdapter, where the wrong change was applied + when a change was followed by a reset to the original values. + +* DirContextAdapter.getNameInNamespace() now returns the full DN, as per the + documentation for javax.naming.Context. + +* The parsing of DistinguishedName has been changed from using regexp to + a JavaCC parser, which means improved performance (5-6 times faster) and + better error messages. + +* DistinguishedName now supports multi-valued RDNs separated by a '+' sign, + like "cn=Rod+sn=Johnson", for example. All according to spec 2253. + +* LdapRdn is now Serializable. + +* Added lookup methods that take an array of return attribute names. + +* Made DistinguishedName.EMPTY_NAME an immutable DistinguishedName instance. + +* Separated integration tests that require OpenLDAP from the other integration + tests that run the in-JVM Apache DS server. + +* Changed the spring-ldap-person sample application to authenticate and + authorize against groups rather than role attributes. + +* Upgraded Spring to 2.0 internally. Spring 1.2.8 is still supported. + +Changes in version 1.1 (28.8.2006) +------------------------------------------- +* Changed base package from net.sf.ldaptemplate to org.springframework.ldap + +* Changed package ...support.acegi to ...support.authentication + +* Replaced SearchResultCallbackHandler with NameClassCallbackHandler + to enable its use in all search operations (search, list, listBindings). + Changed all references and implementing classes accordingly, + including name changes where applicable: + ** CollectingSearchResultCallbackHandler was replaced by CollectingNameClassPairCallbackHandler. + ** CountSearchResultCallbackHandler was replaced by CountNameClassPairCallbackHandler + +* Added NameClassPairMapper for use with list operations + +* Added DefaultNameClassPairCallbackHandler. + +* Added DefaultValuesAuthenticationSourceDecorator to enable default authentication + information when AuthenticationSource returns empty values. + +* ContextSource implementations now creates authenticated Contexts by default, + since the previous behaviour has proven to be confusing. + The authenticatedReadOnly flag was replaced by an anonymousReadOnly flag. + +* AbstractContextSource now defaults the dirObjectFactory property to DefaultDirObjectFactory. + +* Added search methods to LdapTemplate for specifying return attributes. + +* Added list and listBindings methods to LdapTemplate. + +* Fixed bug in AbstractContextSource regarding java version number and base path. + +* Improved javadocs. + +* Upgraded Spring to 2.0-rc3. + +* Added full reference documentation. + +Changes in version 1.0.2 (LdapTemplate) (26.6.2006) +------------------------------------ +* Added methods in LdapTemplate to unbind recursively. + +* Added rename() method to LdapTemplate. + +* Fixed bug in getPrefix() of DistinguishedName. + +* Fixed bug in getModificationItems() of DirContextAdapter. + The method now correctly handles changes of individual vales in + multi-value attributes. + +* Introduced AbstractContextSource, moved the code from LdapContextSource there + and made LdapContextSource and DirContextSource inherit from this. + +* Upgraded to Acegi 1.0.0. Removed classes no longer needed: + LdapTemplateLdapAuthenticationProvider + LdapTemplateUserDetails + *NOTE*: + This means that configuration needs to be changed if using Acegi, + since the API and package structure has changed in Acegi between + versions 1.0.0-RC2 and 1.0.0 final. + + +Changes in version 1.0.1 (LdapTemplate) (5.5.2006) +----------------------------------- +* Now checking whether the first argument to getObjectInstance in + DefaultDirObjectFactory is a Context, and if so, closing it properly. + +* Fixed reference to non-existent ContextSourceImpl in ldaptemplate-person. + +* Upgraded Spring to 2.0-m4. + +* Upgraded DDSteps to 1.1-rc1 and EasyMock to 1.2. + +Changes in version 1.0 (LdapTemplate) (24.4.2006) +---------------------------------- +* Introduced the AuthenticationSource interface to enable other strategies for + retrieving principal and credentials than a hard-coded username/password. + +* Added the AcegiAuthenticationSource implementation for retrieving a previously + authenticated principal and credentials using Acegi. + +* Added a 'cacheEnvironmentProperties' property that enables the user to choose + whether to cache the environment HashMap or to re-create it each time a new + Context is created. + +* Added an ignorePartialResultException to LdapTemplate which causes all + PartialResultExceptions to be ignored during searches, for use when working + against Active Directory, which cannot handle referrals correctly. + +* Added search methods in LdapOperations (and LdapTemplate) that take a + parameter for SearchControls. + +* The methods getNamesOfModifiedAttributes, update, and getAttributeSortedStringSet + in DirContextOperations (and DirContextAdapter) no longer throw NamingException. + Instead, they throw unchecked DataAccessExceptions. + +* The method getModificationItems in AttributeModificationsAware no longer throws + NamingException. Instead, it throws unchecked DataAccessExceptions. + +* Removed the (unused) 'task' parameter to NamingExceptionTranslator.translate. + +* Removed the deprecated ContextSourceImpl class. + +* Integration tests now run using an in-memory version of Apache Directory Server, + rather than requiring a working installation of a directory server. + +* Integration tests now run together with pure unit tests under the 'tests' Ant target. + +* The ldaptemplate-person sample web application now uses an in-memory version of Apache + Directory Server, rather than requiring a working installation of a directory server. + +* Upgraded Spring to 2.0-m3. + +* The build now uses Ivy 1.3.1. + +Changes in version 1.0-RC2 (LdapTemplate) (22.2.2006) +-------------------------------------- +* LdapV2 is now supported. + ContextSourceImpl has been deprecated. In stead the new + LdapContextSource should be used for LdapV3 and a DirContextSource + has been added for LdapV2 compatibility. + +* Ability has been added in LdapContextSource and DirContextSource + to specify that an authenticated context should be used for + read-only operations as well. Use property 'authenticatedReadOnly' + in LdapContextSource/DirContextSource. + +* The Filter classes have been cleaned up. + +* DirContextAdapter has been cleaned up. Most important to note is that + in this operation the 'setStringAttribute/setStringAttributes' methods + have been removed and replaced by 'setAttributeValue/setAttributeValues'. + +* Base DNs are now correctly URL encoded when building the connection String. + This means that spaces and other 'unsafe' characters in base DNs should no + longer be manually URL encoded. + +* An AttributesIntegrityViolationException has been added and is thrown when + an InvalidAttributesException is encountered. + +* More unit tests have been added. + +Changes in version 1.0-RC1 (LdapTemplate) (27.1.2006) +-------------------------------------- +* First public release candidate. \ No newline at end of file diff --git a/spring-ldap/docs/quickstart/quickstart.pdf b/spring-ldap/docs/quickstart/quickstart.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c9e37ade43db45d933f4b2abbd4a4c56f2de0745 GIT binary patch literal 54787 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�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 b4#DSN_}nr1{JKlP+9=^4*=%>H{^NfE`j3*o literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/blank.png b/spring-ldap/docs/reference/images/admons/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..764bf4f0c3bb4a09960b04b6fa9c9024bca703bc GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1SEZ8zRdwrEa{HEjtmSN`?>!lvNA9*>Uz33 zhE&XXd(lylL4oIh!GZnHecj|txT>yO8>^qY%(y?B;Tppl#t7yOYze#vq#8^aMzDZb YLK^d5CO(feU_df>y85}Sb4q9e0Be`**{8_ndlqdgjcTGH1@5rAvWm>DH}V&z(E>{Q2|u@89nQ znoBxR{K>+|z@W#V1JVle69d~nhv}!E7VV7D!$l=+#gyARX+eW7x`wT@Cg?1ihH6;1 zs$!+xj1Yt%W31lvY*ooh8##Wqt4P*f&)W2{!b0}^@kv>5x2zLQef-gZgT0SEg>hLF z)Pd`+x;*(#oF^Yc1wYmptOPqEY|_Nz%wH;O`WPI6ayD{2tAO4N zo7{UG#GByI2%_fo|5LqMv{6N+A1o@_2o{w)&t4I@GfML`SWvEy;UY+Xf4Xzz&KO;h zV_?(HH9iCh`e$qcdSYD|*JluqH{jv}kl>0fV4tmS-PB+scb>_h18CFP6lf@4^@?vqT-$&hMpcE*)wGd!;~q-Q>IkUnZqz=PVt;M zK*p3gbLK2v%CK~4^3tV1#?q}@8MbbX+PXD)>(;G%_cH9=n|$sZ!?|yxmE{-7;w@N47?rU=3X_NkV zU|o{PnRTZ;lXp4>+)hZU_|Lw%*va*6=<@jI@BP^`_OsZ?pZg-2AaGf|;i2L0<>du@ zeRrO4er03}pLSxdREd>pap^;~&E+}=JYKy#vHnLI=Z$}pPyA_`zG;G~<$`Br2do;7 z$Heivv0AeyJYVI({@6?X6r+V~XS2Cs!|bddDqJz@2lKf$~4dA1c%lfOT+5KMUSWi#X5(9ePxx_W1Bsf2+N)z4*}Q$iB}K{RAP literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/caution.tif b/spring-ldap/docs/reference/images/admons/caution.tif new file mode 100644 index 0000000000000000000000000000000000000000..4a282948c4c7ed53a2cab4132152c9923f7eb363 GIT binary patch literal 1978 zcmebD)MDUaXJBaHTM%HOBF4+!!hOu3BSpZ2m-o=a4UGyOVRGC@78N*Fn1mTgu^*ne z;*L$0(G;HMj}kXtX=zR2W)oug(x;}vd4|pLf`&qbk&JK3goqWpg18tM4sYt>NNQ*5 zJO1L!te8d4X6?)=pC(QSU||)yt{QYgWZzM1M#kk|4=&{>4cy$*l3-xF?uL{AUz_5A z50}pAFgB%?DF*m>GD)-@{{F$i>YOfT;)C)He}4t3vbN+MR?Ki#WjWH`E;J#5fkSah z*CvDRdtCvNOpI%k6$_&6*{?lq*|st4mU-vV>qgQQdBM7KAGv%{?hRM3li^KVy1S9x zik*=G2sju77$g`J84MYm7@`=G8L}CQ8LAmtfUpM)r!auv95`Ic0D)T>AaF0kUWRi( zcnu8iF+kvR1_*r5@Sfp29R6n*g@Y>uM&o~Q#Rt7z11bTqgJPg?F|Y&xk=0NVR1Poz z%ZNF^GJpYGT5JXL8G!j8gs%ZfLk3G=Ndlpt1L^lb3@Tv^fu#V1MQ=Zj+J`d)yn#^y zss&&)AHzQe7O)6V5GchAW=nvWNNgr3n*%7$3}v$d*=$fYGmtIF2r&nwMieRzvPldo p4l+|5%Ki*wOEI#7?fS#Uz#t7}vjA&lTO_>>KsEyq{Q;^60RYt05`+K% literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/draft.png b/spring-ldap/docs/reference/images/admons/draft.png new file mode 100644 index 0000000000000000000000000000000000000000..0084708c9b8287c51efa6b40b8d492854191455e GIT binary patch literal 17454 zcmXwh2{_c>_y1e^C}m43S&}RzTQstU#!g0*n6YJ1aTS}>RLe1z8LVo z`rtm$Vp5JW1|R$HTrs@@LGR)Z?>PPkL8l=j-77Z&G8Tsi{RV4sPaGi)BBI`)`R~Q` z*=O$N8oBahuA1ujq=ONsH^Z$;Z@?A2zPOR;+t7%GvNscPQvtyu^ z^(He{(TNfAz{D>S76#pNt`V=aFm{t&tF)Lut!iq>3RU|!!{xbB|2@69Az7({KpgFX zBHUL)|7ydZKc0k%azcGA&PuCQV*kD$bT{P;b?=`M@6C_|b6!~s9j#tuU~e9n-MCHj zfV5S(js_`kv|ivaLE*6pY!G%r11u^qOVBw|g29`m16#D?@yi>zc0bwz%G@ za2kvxn$XS7{2WQ_ju!==VTs+`V&L;sVz(Pl4+J?F&ZZv3KoKW2c?bBtGq5)oRM?*)usx_-H@47Cu#_qL+2eow%ZDy0=bsNsUP&ms8wSUp@nG86W_bQDmNMRgINC`_}NgC zCcqF_Ta|ScVvPu;|0KG{NIio~DaGYcHYq4AEiIzkxEPqs@0$Z$*)*@J$yP3ObX$%T zzRS=t%7(g3t{Q*^ zEyTxT$*5+N*(plL90Bl6`Nb^WdKn_Pvpb{prO$Iu<5}~-EnXK7fy@_2c89d+ZhJ|)%qTOcbj#K2|l1B!3n*4em>_| zs0+)H9*C!kU%yVP5l({XnQMeRu}L5Sj@SNhX<@4AzfhMZW{P&$t(3w4cF;s3a!PkRM$$6I_u>8qK3>fr(_ zv-Y*v{SjgTfq|+BcyYvbM!vF^@bCsN)N`rpJ$><_Gs5*qVfQ0@761Os;NFEBr2V@4l75H}1u*H-x1FzIyrv zX4-neRxZt~y^&-x>*hYlIJHqt-rL&^c9<9eB-5QN-kNin&S^e!8s9rIjX$~r#FHSZ zPPGHSJ7NH?>J1WXHMp6{3_m_JHFb(pJM-&G@!UzwMZ19kYDMv8^_@35=1Qp*GU^C$ znS!nuvPQ5{W^@`l=K{0vn9d5B4sd@GNsqwYt13N;s_n$M5sF(Y{Gu{$f)Pqq6>`4( zoK6ZojptUz?t{2OQ@f4d24!GwYi6y465k8gmK^#vxd{Il-lBt^R7pE@jfteJwgkQ(YBxT%22tXdci&(7P>~Iov zlAF+-uyinD*mU_C1!Z!%vFE`wQx$H0WX*IMeKiv()c!!|Br&A#iWksE5wy*|X}DYF zOkmbb)NtBhwAgAQQ)W7>BzBj)^ec8BETv8dt~1Wtd}pfRmKnoYyMymV`fvW*bjTy@ zNFqchp{S-_%)XBfUmWyYYl$xVgQtxEVn358@gKtpQuu~+-Kl-33E21oa-Fi&oBI&`1N%T=`T3uD7xjR z1Q5DaVd-rOkkqXdK@Yti1APh3TN{S1DknOaE4Vdk=o-MQ!`zf#3^vm0RTp!s>(8+I z(BKlybb>#^&dE#xTWKkB5>RG$`5m60nzI~B_{R+DtsN)(K1(tUpuVHL0)mIKnUfCR zGE=xGXN@3g`N9QSG|T0c&wxuu*Qg<*+`PlfSfJAKfkWnRsVJ$bx1$Z`o)r~6%k4&i z<9I5}9(ypb2w!#-r7*;K+DjakI~Af;0mNtDxBc4R3|&8W^=h6KIf?>|@$@)*tlfRZ zrCkhM8ZMxnVd%Q>wKHQ6h;cwwxcI6738osp@h30JoAC1Si}3tS%4m{iuKSkF9xsrA%;wLv z8A#j|uifcVGx>ptY|-u;nJ$&yw-19u5smA=3C-sC-n~XzIV= z*~{{V0<$*x$DP?_zs?b?-Dsw+U(_(rI4}YY;n`g??R&MWiSNSHJ{;g>QuE+91GpRE zd9DfqUKVfdeAUwO7il>!iH(N~Y+WTTbX3b$$01o$aei(SD8PN9Ig|tehF6`&rMrwH z6C(}UhO7r4V(nXd&uyraV5X$iUUKSF7E#U?bu;$RHwXn03D2wdZR{}kbxlVH%&8F=8tR+X zZ7kKlMpt29EK0Mnb~Bm{1y*D227__FT~$T7>%Bs>RxQrlgI55^$os$sc`ic?+hwHQ zy%C%qRZZ?xjTT>R%HJvzYPmTbNJa&lc4N}*?d^eJ+TgWWrby|-X?$RL63$ocD0=1z zq>bD(K@l*w5V0aAqv-^DtQq(*B!;KK;S)?XERW0Z8_eB7>{FG!W0Tmu$$a@l#~e@t zb7eAjZ0Z_IN~+HjldvP|xLYiL+|mn)Q;HmqDMG^&^)mW(%Xyb~AG4Jkd@~F091U{i zRg(Zi(!S357h;^+d50bWLHO{(l58O+_d192vyD-Oh|kx|qkk|71w!Jdg*R ze=X`e#>jQ1n83%L37gJmxi{uYC;jRU__qGnk430EXC8CcRU^h&pyhVlHM8x(ce}=L+^|Pv zi|35MNQw6wsl4bw0P{NiUo&-{is+V{iXV*G{_L^ONZ@`H!#JZ@}t;bpd`Z>sx8;y zHg4#YSJ*anpi2Do=jWPejhaoGWKx!&jJeOVaku|#u8?8fCKc>EQ4j zn#0h@X_`cW22kHot+mSQz%;tAI|=i92)Mglsf!Nu*>=_g&(G0d>km#k&)3TllY#^u z02UV-NFuEUi@}-x=ETTTKA`X~EX5jv8~B<}HTK+*9&OvU2dkm`_BX*1VwV7Ij{pg= zxZNaUqPlcVYHAyHFof?m;I-ZD4bN%(@@2Td(VgI3 z{*lWmv$RZ|smov=_kGDznn+>_uX{A6;y}7pk@d`(Lh6{gFvrA5pAdMmu#G*QM1tQg z2^Fb6c;#}e`;nd&oQKh@*-zW!9ICOL;OFgA2-lpdOKmA=Bp;B_eB?c_df>veT)HW_ zs^sQQf+2B6j;5$>ZG`htEUcU*ioNkd+t(slRq00x_hk@N@P79aTAmlqe^(+dfnlOAm^WQavYofR?D70kyE!Q*mr z=MN`!PH<&(t6*5^bfSkgq80c+f6zkhX=!PVf1h^9o$GPX_wJAXim3%oV$)U9uWEOS zFZ=#iF~Q2FVvon!cVc(IvVedI_~ko1I5_AWe$&m4Pfz2dCm|J!YrHng`j<_W)9N6m zB@dJSV}^c#gL?<*=59v;JS=y@jX-JNZOq4)l)5={d`D-W!H@43<=pJ8Cgd+PhIgZ0 z&1}v2D7JC5c5m#$OqX|BP;TfUn_N`fm(NOG0@Nct5f0=5t?)gK>f*TZCP8 zE~vAz*f8;aNltIEzGmjk2?*gK)Xp4zr=6}59u!nRQiIH`r`BWA&&b%MJ+5|@JL))( z@lrFw!p1WBNbZB0IBSb692ygY3^VVnsCLI=p1DJ|9{R_viTo;ObrMJc9HN|9uopn6 zRxJ;a=NLyqW+8?@vXq*8_pkle?wWh-VSoPI3KIY*(nFq-Do;;Op#DRi6cuGIH zS7vFz0{w!T_jHtX9_!if-#4x3C9rYkU+2(KU|U3m|Bg{GCEc)G`)=}$uCcQ=o5}DE z4Qf|tZ$U3T&S;B0h&i3`PkyvL2&sK4L#)80)82naNsAnG!T4hTE7tIKfou;^sdejO z2^s6dG*bi~@XEf#g^+->YY)^i=j)rM{NpB6Os``bQrQDn`1IcCuH_tZo5u_RDCH9} z{A(qdv9-0;w%911g+6sdttId7K8LSzQx$iqDz9QJ%qEV5yOmP%C1^8VJ~&}mU03FL z5oO`+?_NbVx$89Jw_-65lS!LLL^<~>akOrQ*k8YT2f4npv!ne5LrBe1G zio4QV3V(pOPhsqCE2}mF#DXWKYCS~L->zo*5E`io01;dT5!%$~no!XU5w!2{HcD?P z$hkcJN$uNC-y%aa0(KSOy?hfCDA$n{jchN?d(tgsICQ1t%qbWQv5cv{T zBj3*W2{Wy5d$(v$@2djHMZWKG0-|MBp}dhVgo z`Vtvp{;P+IYGFXmo{Vm!Z+%cSOfN(pk`H&G(lF_arZgk!S9%x!bxKv`i?_8}mLXr- zfr-&54|LC~#MV?wRQm-EFSRGh4UA`d#pe!1bE-N?4{$Ro_JUO#b#A&ZN*AR84Q}u< zvAY2P2=^9%#QQFnV=U#iNT(o73@pmXuFN9 zR?J5~@ZQvv3RK1HlYa(JZ^_%8l~?wwv#lhDjuMeJDC(xS8@gFpX*CRJe8FTVfJFLE z`L1aE-QBK9wh8Lf=pv(3olJVvrY$Ug*U6Z?{29OF(VGVhgGPXNls7&Qa&U0KV+QnI zZN%rly6U%&wr&4qxD-ujjGO;@!kTH7t&RXS%qN%jTu85~jgj|mC`qh(pxU=LV<8nb z2*g-&X|S0`7pDK6F8O&>ow7=M28`!FRi!}mwg<&m&wRfJeJ}DJr|iWg3+r~FUb+VH z+^&Un8v5io|7I+;!f+OL&4~5g{fgrz&*uKPkBlbI#PEevl|9*Y;=ZITUOO{Xx3C?Q zjzzGgf??gQ$0$6k$=bjrn_FR?Ye1m&Alpp zIR2qAum=_rBrlX|_n?Z@`qf(Z0Kxll;~uBw&`7z9Rouxf&+){$ zT5l^SU3Q)C3!P4v<8`92?@GD3FQ>)aS@lWl&S_BItaudFE*~l)`|-f4TB#FImiY-_6&9CJ9!>+TEFxeaHO)c zvYblCdx~?kBnWI3y61_CZ7mPPn2!+y?I{+aqiJZV?FagXcV{P$qIQQ}eE8YeF~}-C z?~`EwR@Cieg6$PyJheqdg_twn9zXuoot>29+0UEtNnjKl>TgTSUIvF?r06FMW=5%U zVd7m{^kQJvRLT(~FbI!5QPR|t;QS06HwuN4s*dj5LYaTRDxc}ZbrgWm^`&@BlD%v{ z@k_@S)~9!76hB8Mu>D387Pt4nO+z=`W~vOK4w3_J5I>vM30q#&d2?0jd#W0;VqxAg z{*lOi191%V8^8z#kba|g@ zf4GgGK?gk~`S@>iRci6!kr&;RW(POG$iTAEX&_W3#)}zCBeQ12R}+C0SYWFB65117 zYx=X?gFD^+O{W+m*yAfTKmH~iyJk_ORwrFE`7|!~oOPP-{gCa4!U@A4tRgdFHX_Yj zXQ(+MhO_<^GRY)^`TEi#V?93xP#4UrcMTTD68zJ5m{DboqT=!RTMbx!3!QK?HvU2k za26tqP;3Z8*MmUwL{1I(@xTcd(1T(ot# zQ8@|QB&oA%VI6gn^=!_v)SeO)d`3{ewC>T3XM2ZqXV?iJKc$ft~<<46c!aV(J1mq1tLFMB0Q_){R1qliEw)EIh?S*NbRo*>YaPx z2D-q!@M}X!8+eqQe9(&`vcyr9*&Oc9DxIi1?hcoq6i$Ah{XCaH^2(3TA1)Kpu+!qk zA@V)hERaLu1FN%*CTT?U)U3}+-q2_=P0!NO%*+f=0%Wimi9$O7C`K!{L9kB*slT?q zUcI7*#C3?0;`R1E9%YCjZ^&A%sl;VB6)!NN8!ilSF2s{jaYk8%7*iwJVYB!}O?`NH z3i_o?`Ay@F!YSHq7T_a4Hx}qC1`Ys?_byXR)+^(UW^H6<{Jzm;NPkU97r0{^fT(G3 zA;><1llKwo;%)@{#|9*KE2Dmt;(B|5Xn)(d7V2nr5OXUnA1y_!SW`EtahHzmtl7EE z%djW%*H&HXZ5G=Zciw~l@@5<9~SRg`>1sdv54 zxFT-jCM&GG@`Q{Ed)0jXg#Q(;FzY%A{D;AwhdaxE884#bo;|{{h3OhPo0zbfk;Dak z&K2NDkc8^wVPB=SuB`+^8?cY^RCi~h^*4EmEc?J58r@|g3@t=ykaw*U{ z7v;3}@P2CDd|+0TV}fa|3wl21cs|OFu95chX_S0!)zbD}eUfC(!|&!sVnQ$17U~i3 z0k=jQ+>~NKF!oc>Kff(i>j!z@pZJbZ5Qp)A$c?DsJ8AAv!O6p8|34Q%YV*_nJIhup zmQ_{jUUf_x$nzc!4cNy^2`mY?*);JNgVn<>CsVJYluh4fgd_lF1||t597+ld|`Ww&*4Hb;}rzPmefkY`>P)eSO9!dk2T9lx>3Nj5=Mz z>r&3-+b)2!U(?WAgFX*rf@W9Zs)AS~lgtt0D77}&rQM~)i0CR!i>JVNn(;mN6vgZBRDJTdsnC?L>2H3nvZSp}#S z6*9#|of{57Sm7ktIRid*9b3ZPg&%fX92~R}5M69&e`W5`q8wIvKfBufD8f~ti%ujG zOKrw=EiJwBQ@H^*Kw5USk7cR`7;^B0t+_@D3FT&XdE}c8tK%QmNSn;A8RAsMn%(|0 z_}jjAHPj3;YFouX*X_FojE7Cjxz=b5i*s)&Yd&bUzA+NKT|Zgbdbmf54f|QjdK38q zi<5!1eI+@#xyQUC|DfNCc{vl9E=gF^==yjQil0#7c-)K`hM1O%+v4rCu<4wKEeA0> zEp7n)lZbgQlME&N{V?)eCoEp(d6K!Ss;kAyp#QBJcej|g)B$R7KOOkifc9VnF zpKF%Ab3TXaX3pJr!NN3W-J#nLcKyGkvKH+HgbCYH}OT?)qCnEf9AXZkAVH3MBfRj~6fiIx9-31EklLu#&A>uM1w2k;x{p z6SI?Q5Rg<8S^)#s7ktzJn2#%93?7_*{LTCC-tM45qH{l**RpP#OJ?_o|&r9_@2w=JQ0!~pTA3FNiUVF zjRt1OxG5gVaVzD&sIKBRWsLqX)%Dkp^<7D*ZZlOm3zvdK^caRuw0>+%#d)V}r&k&S9MyDr!%#@BU!SxwyIS8y<#pz4TMM)V&d^NaNs%w$r@xK#Z3m-2Z*B z!#C;VD$dR|<3`KMGMYA6xX-+QD(`rW%C9UZWiLh9%$D1dG#BLbF0BPZF6E_5rP3E_PtxKxwhc&v~_AC^KGDil_tZ4XGnVb_$U_s<> zm8kOFv>8SO#Z#<$=3;#hN0AoE1Eo}p(7cFS7Qu%^IP-@56DRm6;s!W0R~nyzVbeB3 zPAN{zeWb;hUGr&tp1Tb%L(Z#nGF@88afdvP=TZ9_k=he-T;vK+PJ?P6ZmqD(qF2)s za2N9|Lc_5Nh35`gW$V?KI?Em}*YAvfg$3DWNG(QvSZl?m(ctUi;Jj>c8s=iGQ_8IM5DCuHH6)h}yp2H=v=D>3DC$o5 zULiAntcT_b0+|=uYSp|RU-2AMnA6H6X~WBacfvSg6(!cva9ZpD*PX&B$NOGVW7m4Z zwa-Ri?VbD4_e>?M_?{Gp5;i_LZoeQ02^su&$#yDX?_v;bcFNw!ZP<6Xv&q9brr24? z|MPgFAc|V;-ru*smLhtJwEd+tn+gNbYoIlb_Kua^3mizF_sOpaD<1}%2z%fRbie!kaalVI{ zp@PyqhIH`4Lsqp;dXPhYq~D8f_H6FmSVw-c0o;ya;C8Y>viOHkmc!hn^U?c42ZCH^ zPvXs&ZghbhD2ne4J#b17FiS1I9RZ}k{S#@9{3>3owZjjy1{zN14ROf_w3vGo{JOw_ z5LgnbR;Hy3#ZJxN6{=$yTGHlT+Ef*p(!2*(M=pwq@gO`fH0Dr=&t+`4T`zSS&3H_CR^wcr&oGobo(9^R&aR88N zpw8q{)!yFVT7gxPn;IJlWjTZ@;6^gu0o~Co*Y0Z@emdc=ZP)|VUtU{c#1q@-m_(_F zc1`xg?iSXAbKiaJX8bOLsLi6+@?>^2T?51nOC5Th3E$~E6NxFrub(x#dXlO?;HtC3wTw{sEq|t|$syXv8Tfi8aLLm->hWZycx7?T zJAi@9^p4)TX$*q+{W7YJe2KLA=_$$-H9nhPJihFrO_S8hL+vnyy}LF)%0Bq3`+#x! z9*bF7ccIkdCZ@bjMt&SE&fg93dDU%csbne!aFMjR)C1<>dSOfAuTm{~rfOo&wrBMJ zi&P9Lc>oaIV)w+sO?^X8sjG-$-RvZfqbMm$3ez1Ue{7OHR`>b6Zq=_PrYSjFxJ0op{4-*e>HCa+ltbeRL&8rk zOpJhZ9$>74+^4>aDY$y1{+F~p?}C)d=kkO*yn}m+Ajw3dOKVp@e;LX1bbqRk?i+lw z|D*uJfF@Z)tVkhWM8?V&E# zyTmdhV1UEb^kae@-je}deN9LG-8T#3h1#ojCe(gby>*zW``~(Lb6U7b%MwpdqEq(K zEAS{$i7H)RbG~^`>SjFQj+Y?^Ft_1`?au+^$%R3VO1zaZ&?NS4Ry^!zZ^1c#NF#h@ z0TD8T#jmQSaL?JG8@5uub}qy}n+?f&XZkDn47o*x8=R+CS@9|@+5Sc{deuI{#-k@8 zGwVmk8dyt-NdoEExb}uMJCH}0UCrJi0uMR>5}ISY3=oBH&_hoY1^&b)i~yE}u?si% z-PVt&T)q;ZjLX0sQ_TA3bY0+hmGSl}+yLQsMKtH(tvC4_;^TC@vXLuNNTcgL$DnOmGiLhtBsMO^AN`&cRypL?h%J zBiGYxSf4}dsU(n)My$~2GQ(fLVZL#U{ho7-j1j?+)IK2=G zzXCkvL!y~{frb8dl#NEpiJ)7iad@m8(PH3p4?x|-%d5zWr95 z{rZdqX#)sbTEuODXWBnoDA=^8YbJDSV-L>lfASXZ8D5y&t!Z16)p2XHLUQ||$XzhY z(ZNTOhU=WEWxG?AOmpj8K~s1|a(9*t@!RB$%7U*=_M=t5`sWAFyuz~O>Pcjl@Xup- zgO1W}S3KEY&FGc`(1n6n{`G2ikZF>bki9HXRA3j<&l!tlbJ90F>rt$!$g75+5bn&= zjyM80QWmZjI!*;6oH#S|oUcV47FQsDUj%8+H$#7kjT51X^Jtx)%R6|}%#Dzl{ml^0 zsv`Nn-|Bz+48SiLI79mr$g&j&34dbw@n{EdZCF)Q;Eel#;Nmcdr^kRV94rNTeQ>Vz znJP$)fOxR055Bx)K9o5)r}JEv*;cD>C^DQx@@g87^oPS)Thwn;1zXm|@zi=;a?}5h8y* z6>(bt{|;@&f#h3nUIC~HE_8P)0gPfgF)Iz@RlCu`TI%(q~$n4sNz_?{|9BnSz}B&7{#_ zK1qBPIgO|{V&NqKX{rq+Kghb{e3jx$f^oK<{_owdP6x{tVp%vtu+-oKp~{XTyKKwM zX$Z`c@2!q%PLTgNKUeKOH3e?Z#(AjRAjfx2O^o-wLC-f~kXBCsjG2SB4k!3w&_%ssqiht1fi`gwthS zZRJxsc=Hc02T0kCbeye6=v`L}H=CcUFBS95I`opHXTIPR!vcLUKAVpo{skf;5|%cj zKZYwozQ@0;jmm7Ewzi zo<*oL>r^0lz>yz>?Cy#9!RQ(wwu(u2d3jTu6aCREon8S6b$ev_gGij5MEh0OwVHeY z3JMHR>*HK->0zGG9~TkshQO@B>eP?{hJE$f;3N>uRLhJ}P~ZraSC!2Z-m?eb14#V` z%Wf}!yyU^lkZyZXi204#!G+O?Q@ceB{!4N<(Xh3BuOxshEnNU26-F#`#RIs>N}(pBW@Si2rp;jR0tbkkeB?zr zS^vJtRoNXb>y}tW?zt}O@HIPqMztv8X1Mb1o1(k)Qcp6Pr6uU+Wr|!Hv7+$?#M_2O z8ozNt-UfLk4P2gUH6A!~G!t9m9h^|<)O4k5$cNw60eE=UoqqjQ71i%yE>IF5MMw53 zoVZpnlyb}7VoR-eL}JL|uKeGZGj%Bhl-tR>S%pT0QE3%}REJ4vlQXBz;^otxhg?Ch z8XD=ERaU!$Uo=nzVP$E_ymK_%iP6+MG{s;{Y7rF$-fQvmr}-!7R+5kFfp=OE?phks zAIRMnzl_f-n|fdFUx?=;*-?y8#j=PGKPpOOOfX}Ic6w;#a)+T)JYU|+Xv2w$zY|)U zEeeU^HM+hO--oSU>4i-+iF%MO_+IX?wo`R@!WLpS_grU1%73579~%ph(hCzw#gqKS z33(@oiGv3~@~gXqf5#i|_#YMm|B*Feu_oGLserI4H_P&w_AZb(3Isb~x3Ld2CgpT^#omehU$@8! zZ37~|Sa6Xc;y@q!+6z@#hh!4ucXrj8>Qxso@J<)u1I)@I5I^A46Xis^4@P!i0{?O+ zk)CZ~poU|sFD2L)#iE|&ssJ3xPipy!K=bolV9l|2Z(i}*43Z1Wl>m~3P4rKR z;{jYf=VLJmi^x2<{AMKuKw`P)#B;8nQBOIhHy->XNo^z$xthq*cY@X>W!5<4<@4FX zNAk9jj2q$VscrAdjGHmRtbN?guU-Ze<)BHW%*jo5k{5v?@U7yU_yhoD$uz_q-~545jZuxv;JUQ*eFqk?xfP@lh~jP(N?2I0NIZ-q zDGD#GS$Z5%#81&o5Ufv=)9xJ28~UMS`u^V4={bp#DxfwlU7@e?)*KGps|+y(T@tnr z9A#fLvb5wqpXG&eyWHhX@kN1}iO>(98#j(F*qUrT%3$LWY&VnO9gyxolrhty?u8%M zar#N)92>LMOfsB>_D%XweB1a5z8o_t7nV53zGhsGH=Ml{GE->_3^aZ?i1k+KH{Bi* zY{{urjeCUUx{4awMMqbyudOM4lcFe}f0kQxel&TCX;q8#ItaBSss?l>cfYcppL667 zS>TiWKH{ZWLw~L%seSo-t#ZVhl2DGsZb6V3qms|C<$Uq?0!WD znTe>ujm8kZr!xr(ULadh!(KEI*eP2e8ztmktEMSwD&hN43ddd7xbRW-tc40~ z19$nWlggKs>s;Od2Iq;+HaSzqE~nHmhvFSvxIn|naZo8v~4WofUl z>!4oJlcv$-(Hu&G#ZJ_w5Z)n~Rwk6YVkfc4?7^k&H4vyEOMEwEPa;GC(@sG9UK0l< zym3g}=fXdvShWk}JWOfm_hXjhW6NC8L44=y9MCIOFwlD^9541durm zIjxI`e%J5;RSEZ-PK64!Z$8JYxg)OYus$7X)=3YXtpuw8`FEZoHX-T27L3^3mCkP{ z&5K05BG=29L~TDoxs)Ze8YnCtB6r6s5%IM>J{E>lKnexjk zF8wpQnq>*y(C;*VyBSQLL0w@L?tQ?-PuO>uDOcCX?6xMc;$ZyH<_&W`uj1gXTP$N^ zG4Xa31VfrYj;M^;f(-Tw`<_7wa3DmU;dQiQf z7NxutM)uz=k#Ko!M0*iv^qY@@ibmclp2|7Ykd5wdL5{;9N3m~n4g=tUwe;P zI25w!A{9r;$eMW>q{hpo19Bk1pe=P>6r$o%=>7_cjN&Tm5M|IJuUvH+AK${CJX4oU zgO6^=eBKAuGz|tm+nSrK8|c$@b06AJVIe41Kb6p*)`8SjV>XRLlD=n zxmF_SZPNO?HOkAGmreqZP`zhDat0zvL6TUJs#jj+mv!eE2D(4H^wQ8v?J{{F_uNf{ z3Guwlmr_Y+?1xwv+DlCV!Qxf3`85lI9<3MYLPv#eKnDUu^wHQ zc>gm5549XSAWHZ;ccVn65dF5Y_!SFO%Z|}Q(6SZUI=Dtc;z5Ty%nrLYb#L*-Yh(x- zSIj@A+IWZB(0~zQg=&PNK%${P5hZ>29oZHuVGWHXY$x1YFsQbXHgN={wk@*qqJ+Nq zd)egXY~a_ZOiJe;TU+HKlsyJTMfblt8%od5*(H)*Q$D;z+^%AQ4mXPuX2k}%-4;79 zmQ1FAba2Ra`Bcxdj1l&?kFD%K^S3JRgKXK4^qjwecz_P2uJ-l zC)Qvqm+~M!v43_gwKDlR1nJf$++0o6yE@XCdZL3q)UgB#ypJ#vJ8S*1wxK1+=6B}+ zXR*cqf>giPZZtBQvI{Zak5z&s<%W6@C}Kc7|Jd$GBC>hYST1Qs6_hTGb>DuR924B0 zN83(4+CxS$>H&|*-r;Fo4NfL83)iN!YZ&TeJH98$Hv6Ebv4bJ|{_ja0c;iH3BS>3^ zpqgshmx8R31o2gdvH`OqjyW=UU6imxAx*C0^Zy99KL{oAvkpUJI(*CnkaZUKS|miv7yJG9ATWhm{X zmhwPou-YzMm|1!Q!U)jjx%z~gla=8UD)w?G&Zaq~DL{YDwlSN`Dnf>gnqOEH6`e=5 zK`qGvB4v}6phVXVBt;`Goq9`6$1(ekF#8@rQR!O?lVvgou3PA{Mrgg$a_qp=fEaM+ zd)RS3^IyJ;lNL~f*%#*d`QhDdtk^TrNIS|sGACrecpC80;-?Fs23-ZoFWU}~?O7@t zRJMKubhf|4AK65+^Yw8fyef3O1aA8v$s3mu7PHe^U+V4qu@K`r&lUl#^MSr$PX__o zkc4H6xZrmj{B9ymd8uZ1l@104i9rzScjn&(C@ri42@jd|ET?03nMCrOz62_&EiK<& zSBCb#CxX4Kax$9yU;Qik2A;XS4l0o}3esA}H7YGS`LFZ+Cp-+Ao3iV`;Y2#t+RBw4 zx0Nc0Q9y%mXU8X3P%JXaJSA=%)~{Chg+d_{`+@cih8jx$RRzetz1P5XI7rt8+K9*g zkSIZ8rn1WK#9AdD3qWOXE$*F3Ot={(vVp^%iu~vZN~NYgy8_O?l!!1aW}T^|BNP&6 z0?qjrcZN zmjmPbA_FH7lrCAL1d^70)DpX)@;aCfO87MXaxB1q=%jAw{{D`eJ!d-BNT7BMlMWP}{ZZ&o`DY!}ep;HhTV*iZR2Rod;vAPt=MM&iugW*ReqJUt5Qt_q8>ioMMBX>R9!hDFUD-8$eYs z1-TtSGqXUHgLC2i8u*t{Y|w|+jMebIyJ4s^A?cD}pz_yAd)%*nkt{$;7Zl-taBgGY z3@mR5iYU7aF`|s8$6+Otgv24;=D;){kh=%;5zgNp{HcTraHisq6ZRfb zGW_De>QlN^)>%P;wg-4IfgjGe)9@8oA5f2u;i&iuD70ZYZG>GVyG?KsVh7^@q^+_&<9k|1f{n8Ys}&4 zar=)5U>;^OAAH~;qzbCyEiJ*~gbv|vsZP*7fI2Zi@i+OI%Qu*&(tT@erO6Mb(Z$59 zguP#oe4eqid_2;#q}qW|`vO7O$`jJe$IvZwKK6c?Xzh#3XO?(!b^2k4;!# zYGW=JqVe>I?z~`PT4Q2xwFFNu6ey9UCv31nPenw9f8bRc#Vg5bJF+YgK;aIo$ualP wqI_@;Bx5sQADwv9=?)5}0VhV#cC~Kt`tEf9DgFWeNC#x3htMsB-+J`_0Fi|iga7~l literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/home.gif b/spring-ldap/docs/reference/images/admons/home.gif new file mode 100644 index 0000000000000000000000000000000000000000..6784f5bb01e0104c60e006a2ed525163a380135c GIT binary patch literal 321 zcmV-H0lxl6Nk%v~VJHA70KxzO;Nak3U|_JYumAu6&;S7N@bCZt@Bjb+EC2ui04M+` z000C22)f+N_DFSAmXsV{#*oJWIwOJ|OFii&dHVi$1?u8o=2teG> zb~7H4%2JKz`Tcy)XEL^=cAP+G_P7moKVb2g%$4rYhp9PeRzLz zfrD6ufORfRiHeIHgKCh5l6Fj1nwy-RR)UybJ_V$url+TLhynwsuCA(~Rj;(Av5lgv zwwtvDw^OsE0|vwftp&x&!i>OQw#ml^r_#R6Z_dKdq|~Li{txWV+q;;-NCjLKH8RzODs`x)zXFqfx?o2&^85@jF7AWJN0jDQd6 TqQ?;{LW&$ovZP522><{)rIw!r literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/home.png b/spring-ldap/docs/reference/images/admons/home.png new file mode 100644 index 0000000000000000000000000000000000000000..cbb711de712dcf06597a3a8a3d95f6fefda1f245 GIT binary patch literal 1156 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG|!3-oLGuzY{7?>FXd_r6WdIS`E6g8)48qP6v zn&afP)GK*ya`E2cmc1=K$9krmo3ixW(yjNl9=mt!-1BqS-d}tE{`vdw@Bfd2(GVCG zA@J$l5_e#hU`+CMcVXyYmGuB}CVRR#hE&{I8+eiLumVSprtq8v761QlTpYPgC-&05 zDJ{&8o?4V1EYqU7+)vOI#yLg7ec#$`gxH85}f}H9d0^ z(^GvD(=(H^6-@Mu^ehxCE%gm7^bHIZl8Z8nODY|5D~n4qll4-I^-@X;^7BgclJj#X z?o!+VG)@a_TxNP+Vo52`JVR3xV`HP#G)t4DL{lRpBV!ZeBojj;vlKG}W79NC!#D3= nHUM?;fpi4`tz|GatuQpzHqbT@s&o4Ulwt66^>bP0l+XkK0lack literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/important.gif b/spring-ldap/docs/reference/images/admons/important.gif new file mode 100644 index 0000000000000000000000000000000000000000..6795d9a819874ca8b833c4d4993988721489070f GIT binary patch literal 1003 zcmd5)v2xQu5Iutd0|w+k5&Zs3?l2X}aDS zjTF}vbzOHH$Mba8b;e`IbzRT%eBTcOF$gq_YY0gQX<;}D0zVAhF!bZtiem@kQ53ld zc?kJw3X()jQz=b5X{r%YqZCjoWEse^T9yffD1>wGXnD2O6PLX4*vhfx$E#2ysKF~)d4pDz}RBuUaVC4^8)m&+y7^CACN zNWZET0BmraH<<4P+`FFGYnVCKQ9;ZBR3T)qVf|%U7d>simE()pGuDQwHb2TG+MBQ_ zvDDA4Qf1%Pj=rj3vOLN4H;wu(_qSJ$@rtK60JzIpt9fbL=6P}WBLJ%VyrBKnwv9gL z@+koKj|(oEHhf+1r)*HA;C;h{WiuO<>j@AFLq1UdID5A%&u-GCYUTM&`rF#A&P{r^ z_xRIVhqhjHEgv=NdwEBz@%x57)QYSpY=k4uyJx0tows>V2jGshqK7Z@I~q3m5W5c^ zZt#o~c$MEO+~MK7@*>Lh!0mEumT-7-ns3eG+lQO)ySz&7zEB7GF&sm<)jwePAZ~s8 Q_s=i~Dg!i1^#?fn4NukiE&u=k literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/important.png b/spring-ldap/docs/reference/images/admons/important.png new file mode 100644 index 0000000000000000000000000000000000000000..12c90f607a1b27ddde0a7d922ae255e8c90e883e GIT binary patch literal 722 zcmV;@0xkWCP)Gdz_qOoSb{LwMwNgp7=gl$4aErG%}mjHRWNrKOy`y@b8JoTa6ut*xc4t*y1SwY|N)#>U3Z&d%1> z*52OU=jZ3|@9+2b_y7O@tTMkk%M`~Kg@u8&dg_P^_0l3yQb639!jLZt^Lx<-O17UeeJ z-|=!77W(jGx&e#?FOku-gKofoU0$~4M+dhLFueEauP`}l7LV=;lsOdn%WHure=x;k`m0(bF&MU#) z-qv#^n8(MjB|ykioqII#+`g4no-MU=BK|Sahu_3M_-d*=7hq=~t?^}A)G7 zbairN0An*{V`DL9V>K}|HDobmIW;*pIW=W9HaTQ6F*7kTGI9=S@Bjb+07*qoM6N<$ Ef=i}M4FCWD literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/important.tif b/spring-ldap/docs/reference/images/admons/important.tif new file mode 100644 index 0000000000000000000000000000000000000000..184de63711510990ab0a8f483c274d2f11596cef GIT binary patch literal 2020 zcmebD)M7AWXJBX$dk|ousK?9JTDdL8Uq@YU@bJG?*jxfpA<|j-!WmZOftnGps z2`M(7+NV;37GB736>XW?tSpqXE>}~nv-Ps%oEtMlIQW-6+n$q%9M;|CK z_#F#ZV$1tJGvEmalTiEz3u}o#Tuh>mHiUOeO7JnuKG`_As3Jnn>nKNe(yJ$T`WW1e~GYvWZ4Wap86IdPu0ZRZU zVEzvR=YI)c=}-+U1EPR<3b=fz29^QIz>)z}8Z2c{1j=VaONynyvH(;CHn0?60O~UY>I?#w0~|oMCXfdzd#ZtD0Rym90=efsxO4)k@&c9v z5Z5Y>mIBlY0dHWCG6FG-=41HBzycNl3Ie5=!E6Z-6N$|PWrOMuW+jIb=LGEI8QAA*>a1B0!;`T|n7uj>pG`jtu{evhJMNxcGSe4+aUA4;zBR~SJyxQRUcWR@_F-^jeWYB);NUiculZ3jmx6N0 zeB+OSXDhy@IoCx0FO{tph>zHm!T!klb*W-Q^N$-zxf}}=>~`{%GD&ps=U<*F$^Pgw z_kzS@O+PsF&r}G^Pim1AepDS}@Ytzl3Ts+UM}N_=nLk9*dAj;P>|etE;is#v!2PUi yKjIc2Q@7UKxAw<}hlktwFXd_r6qS{MX+1QdG|HK%AA z&M|bFA9tAudUsBZ|kvp$Id-JckTVP=kK4t z|Nj2}C>RZap&SB+ixVCKvjk(3x4R2N2dk_Hkkjkw;uunKYwyH|T!$5ST0$SiY~H5U zR{cLbR)lT!-5c|b6rGCX%N?2P<`-xxUu`gZx87&*3!~4wH@%p0)WuYX}UBIC~8cAiK_+plk!-xP|nq~%Rem@g?39waS$dFIAw`2be&`&H`~ zup7N@y!g@N+18CSR#dLnIlgB9pXN>WRz-=n38I0oRnmeW@(a^WRPZVkYb)}kZ6%y pT0bWnsEZGzD*$LMgRyCap{cfkwt-Nc+b5t5gQu&X%Q~loCIEjWXuALa literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/note.gif b/spring-ldap/docs/reference/images/admons/note.gif new file mode 100644 index 0000000000000000000000000000000000000000..f329d359e55c7ed753170a6f04fbc0cba1e1e565 GIT binary patch literal 580 zcmZ?wbhEHblwgox_`=Ho1YTZVK|w)LQBlds$=TW2#l^+d)zvL6Ej>LwQ>IK=x^(H* zty}l*-FxiVv2*9nUAuPe-o1OzpFe;9{{8>||AFElBX9%7pDc_F45AD=ASEC>8Cd@% zghGJlBo$966GSzJUe!6ZN$1q35SXB^-zJAkEPj)pXq*a$h_ zXQ+sXsjhEmXhNv37hJ?OaLOg1X|~+1jSyWR(o`3y(c1;Ai!}%$em*Glyc1BwlJ~NK zuZpLThNs9@k1ImH0$Wth2s`>W>73rA(RIXT!4{9MLpCC+wq2hkd_`O*d~)g9;?U*N zC}OI4M1Z6Hl7Y`-pGiWx6O;l)uFCkcxOF@EUU3NwS>oY6#RI6O?U2byr$d1v9)TjN znwNw$j~n?OWwbpf2zH99Zo*Lqk)s;^7gg9U27sNV>(8nyV%m64QG)9cM8x-WNa$(j zzz`MJAQq_8eSmmjy7}|Lu@zf kf(CKug-JSrEM6BktMtGlBGk2ik;bV{KB5sIO^OWG0Fd3m^#A|> literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/note.png b/spring-ldap/docs/reference/images/admons/note.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c3c645ab9af6318035b026dd86944b9ddc9114 GIT binary patch literal 490 zcmeAS@N?(olHy`uVBq!ia0vp^5+KY0Bp8m$B&h%?rX+877Y2q^y~;)m42&$EE{-7; zw^Ao5PC9JB<666~wbh%Oo7tJ0_rGWfi({a(qjR96>_P4H$tJl=Pxd^1p6`8M?=jE( z!hchf6<8Mi`NHe6`iia69>!lxe4C2-S>+Wvj;l63k!MNSb9|1+f-i>irDi|a^uLl% z^#-f2#pQ2lC%m~9m9JWJZL3|T8FRX>A78<>cU{Z6XGFG336=OLGkw25|29|RG_k%U z>j|M}Ih2i#-w+9_WSj8)*j_s0*s+gA3;Sh&ja)bx!VF_Sf>*se@&+kCgO zr+R@?&ik*cqgb|1nDsf`Smu_<(#~sYRz=fNIgWLC7l}#=|C@V!^7^u?J-&S9hp(U4 z$p4Zq##20*5QGIHvwJ-nxqBD;h literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/prev.gif b/spring-ldap/docs/reference/images/admons/prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..64ca8f3c7c6856d17625615c7845d9adf8b35e6d GIT binary patch literal 1118 zcmZ?wbh9u|RAW$Q_|5jIb=LGEI8QAA*>a1V#C72?E=btEDjqN9qpDd4zl5RF#mYJf^(P5PkwoZW(JQ{ zF_D*4y!wR%9~DOmG#sD7{_&y;#{p%(<{xE#Uw&*>uv^H)Skbd{qJrHLc7}?c9UtQz zYXTT6YHoZvu)pcYrmCD9p$~wJBmbf!%0P@OYB}B?fNF{YnIe9ySJ<~ln9<}1LcYr;@((b@HMtAlPLh^PsKR!G>+|CbXxWHL3#->LwIhe?U cW`4ULC`3qLrpm*X4$b9ricTFB5n!+e06MwKH~;_u literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/prev.png b/spring-ldap/docs/reference/images/admons/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..cf24654f8a9d6826bf5ee3f6b640d0b34f44d2ed GIT binary patch literal 1132 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG|!3-oLGuzY{7?>FXd_r6qS{MX+1QdG|HK%AA z&M|bFA9tAudO|H@7THL=dQiK_Wb?x_ut?D z9|fZ!FvLS(&zmEwfLVeu$=lt9p@UV{1IVfNba4!+xV3fSLB2x#g-7SkiDHi<0%5c709k4@>c%U5PUn6XiNrQ7+$BX-K(BEj>;XDjvwZcIF~ zikDl%a$|T|&B@5M-I14sdv^1r*gkp|z3k=crb$1i`yH45`zBpRc(KYI-u^rPzjiy@ zGH(5%+Qq}Yvm59P=MvY5lHmNblJdl&R0anPWlhiA#Pn3(#PrPMYy}fNBRvZROG|wN z3w;Aah2)~l;*v^-+{)sT%w)aPV!f2og8aM^z2yAdiMtec0FBcE8<&}$msnB?G|wQ- z!aOlC%^=CZB-O|yDbdi(G|ec{Bq=S?EGaqB)I9sbjHy6fd>~x`Kx-L{O)CsdwGFfl UgzDTr0c99GUHx3vIVCg!0Q2->tpET3 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/tip.gif b/spring-ldap/docs/reference/images/admons/tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..823f2b417c797bcc5b5af0d86034bbbe68a9c5d8 GIT binary patch literal 598 zcmaKpzfZzI6vwMTVkAa>9EomJF@dB^cAyaw8YzNW>;V&-Ax?~pOgK0Qkwp3j7=?eJ zp(Bd}iDHPQ&cwK|BZjz$_padR<(hoox1W3W-n*l8G9sLBGh57bgCWc1aD#QQmI@nS1Ofyy{@WiyWQ4xz1!{fdcDD5FdB`<y3!k zEzMQ}>2XNH@2x$azJrio4y76u%{aaSQ8iI0-$_v{WV^70wC+frSXf@6n4D`V#?Bj* zZt`izA4lq-+})D%wiNUU4VVF+%2sLK@TMg8DV7ztp%Z(?@L;tQU1CsK&Qwqezj{Cq zSwCP?&P}GNbF_4EK-+twGeQq!I#zP|Y+{WP*FI?V_Kf=>vV0rySc_v6yVepU`O=gc N_rd2$!U|dD;1^e0&sYEe literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/tip.png b/spring-ldap/docs/reference/images/admons/tip.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4aab3bb3543191c360387c4af9a3cbaa051345 GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^l0YoM0VEi-?r};1DW)WEcNYeRRlUkaK;CUn7srr_ zTcwkB3m#VBagbEhuIO1a$!w|j^feEHv@=+|woj32oF*6|l<3XH$!T}Lao)e6jJhoQ z_vr?OZVprC|7iZ8xaicUR0b&zR-JdP408=+?zC0Rn8IN&QLTWhMIcU0X8P7uUN4WB zR_?a_;&p>ll{>(OzfJ4N{OX={Q&zNgO}j31DC;|ya^r9Fjd348&p+!^cT+^sws+=& zCu*T*mRNK3PE;$BNx$Fa_9(Y=&DoXLMFRd#U31O)<`W^F&-o=xbIqK-c?mr!bmn>! zky6TW;ML~4nXw$T{yra=OteL6G!=B;0=?;6;u=vBoS#-wo>-L1;Gm(b>6x3Dp6Z*J zo|&AjV4`QFXQ5zesc&GRZ(yj9T$EW{Qt6OeSzMBtte0A>mr`1gpI4%noS!>!m*Ngk zP=bxiOwUU!DFvFBnrfM1VQy}0X_lO7WM-b2nq**TZkb|inr2~`WR#dJWc*7VsEZGz hD*$LMgOO>4k%_i}w!yxSoa=!y44$rjF6*2UngF(YpwIvS literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/tip.tif b/spring-ldap/docs/reference/images/admons/tip.tif new file mode 100644 index 0000000000000000000000000000000000000000..4a3d8c75fd58190ceae8d6ffa621ecf7e925c3c1 GIT binary patch literal 420 zcmebD)M8*_WMF8pe-L1yJdc;H$tf{F-CELXO3;xcp67e?gucfex%0l_j;Y3!bk~Iw z*}inn73j9T)O}-3=fCGcYZHT(zR^l}-s<&G=c&#%w(qtbzQr9{)4X|tE-LgF&v4l4 z)p%aZSR=ZsmwRfU)`umDZ@!1L>ZTZTei3kDV32yV!Q3h+-nMlqyV>lRzWV|5XS|!R zJ9po!|JC=_hMz9Ex3Ove_O<7Ki^+ZG3OW)0HK&YExa~knT17|Dw`}IsahgrSch^-` zbR3#}CTEJE3FpcFHhEeT>m*%ClD6O_#XWHUqAtUxv!lnpXbkP%`INR23xxENF% fWR5tL{SwHQVq^u|^$Ez9hO&PF*|tb}fm{Xvme+K0 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/toc-blank.png b/spring-ldap/docs/reference/images/admons/toc-blank.png new file mode 100644 index 0000000000000000000000000000000000000000..6ffad17a0c7a78deaae58716e8071cc40cb0b8e0 GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngf!VDzk7iOmbDT4r?5LY1G0LBeqssYGrXgF}- zKtn^rf1vn(hW}s+NCR0w;4iG^2^42c@^*J&=wOxg0CMC!T^vIyZYBTtzyH6zKuy9A zentg0F+qV0g#~P97#OBpaJrNsxA6f`rE`gEL`iUdT1k0gQ7VIjhO(w-Zen_>Z(@38 za<+nro{^q~f~BRtfrY+-p+a&|W^qZSLvCepNoKNMYO!8QX+eHoiC%Jk?!;Y+JAlS% zfsM;d&r2*R1)7&;o@#7ik&>8{Vv?F>U|?x(ZfKHZYGz`bmXczeoR*Z-Hs=yh7cWRx f0MJ?nL(>XNZ3Ars^Rf>h;}|?${an^LB{Ts5OHX0g literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/toc-minus.png b/spring-ldap/docs/reference/images/admons/toc-minus.png new file mode 100644 index 0000000000000000000000000000000000000000..abbb020c8e2d6705ebc2f0fc17deed30f2977a46 GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngf0VEhsJkjh1QcOwS?k)@rt9q4-G!sMP)HD-wQzH`-1CumMgJctv6pLi@6hos# qqtv?{|7HPo@q%;(0Ig*(G_A1IHqbUOFZ%#8j=|H_&t;ucLK6V~f=xvL literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/toc-plus.png b/spring-ldap/docs/reference/images/admons/toc-plus.png new file mode 100644 index 0000000000000000000000000000000000000000..941312ce0dab168e0efcc5b572e387259880e541 GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngf0VEhsJkjh1QcOwS?k)@rt9q49T#T`K7w7|w?rspM=lmg95OfodLFfd9rOi4*hH8wIdOfpPPHA_l1 vPBO4aOiebg{jIb=LGEI8QAA*>a1V#C72?E=bjEDjqN9qpDd4szjmF#mYJf^(P5Pk#A^PL<$Q zI+;RG?K?R>ZZ+XJpnRtJN17PRgOAG`Ypgh#KAaFZVBhwmiI3&M#ti2gFIJ`xI|LdI z)N_AywPiSv9NPY48`Fms0t^T1xjuG&jrgXxZ|i>{CW9aPigr7S6dxV77JO*m^5e&) zo(}&F0j>Y}9vSZmQL;N0Bl*v`gWrf@#t#YRf*HM~)&2b!mjeThEhE5z G!5RR%al9%3 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/up.png b/spring-ldap/docs/reference/images/admons/up.png new file mode 100644 index 0000000000000000000000000000000000000000..07634de26b325b09b6686543e3743ec58426e64b GIT binary patch literal 1111 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG|!3-oLGuzY{7?>FXd_r6qS{MX+1QdG|HK%AA z&M|bF#=*s&OJYO?ftdq@1MW_{{H_c7!85p5(1lc z&#VJx3C1LEcNc~ZR#^`qC(YBvF{I+w)Ct~v2NXD1b6>NwI=-vFd2Ozz_LBUAZ6_V# z0_-2ED|^IRKipvRGe~yg+2{$+0#aW-GMHneR${}Twfy{=Zu8*Wewig#Kj<-8yG4i7iAWgR668V7MElu>!lX!rIZ%r=auLs=jTq` zrMLrVoEF%)%=Em(l2V{~M&{;5#umm#78a?N$;qjPhKZ(zMyW=L7Ktfo#^y-|**sf- lni%*%x&naKG8mgy7@BGuXd4LCxqSjjdAjiitKf)ghIjv$xRfA5@!fkDH{bMrpZER!`M%%z$hqF& zRTo^?=>a_=-~^4}0c5}joCOph4kUmZz-=G{VS5-sP2q6X`MO`-x!!*rW ztyZts8;wS@*(?@mpZ^}uZ$}#tfY(x3o*?Xoo>h`d8|jmC(W5ivVgErE1sEKfo%%8K zZm_%KW2+i;iCOE!&3{olD%O0Ac=Thp(EZgCUC z>m{!ZyCyqrXB4)SL^$CI^0ECR$tT=P*F@;1lfy%=Q(o%DDkk-3k1-hj`YC2`iO!;PB{{!F!o39xr+d_Vw5fMTEwpb-s#9q<5Nzz6gIepyU?Lctpr{ZK zVzWaWPAC)#17S8h%;AIuf(Q_yeIybEqS0s^i1YdJcsv0ln9M{Xkpz;-I_^=P))~D~!!Hvpq{Dl8O{rN@cECkt>#DncX%I(O&3i_YgL-$m$VU zT3cLBLS%M1`o{TBX}S|Tbhc)vk!Yp)%rdDd&my(RPsxl%lU$)tC?(1~WuEwClUQn! n$Q8O{Mxt@ukkcT{K0> literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/admons/warning.tif b/spring-ldap/docs/reference/images/admons/warning.tif new file mode 100644 index 0000000000000000000000000000000000000000..7b6611ec7a1980022c11ad6877fedf32f41b3df0 GIT binary patch literal 1990 zcmebD)MAieXJBaHR|qhCa3Ybt#fe?OBZVhOke}_5p}~zDOYXJdOmf$P_Zjir-v(f(n1LVCeE22NskqJ)$I5g z8XP9S{LzviJ+sf*L4iXe*;u-Tjq%lq8EgzJ!Hcg+?M+EyWoUYBc3S038aqStx-zY! zDFTdKac@c|p3q>CIvAgpWRM#aTC%3+U_*~obs9PKLA zwdWf7S{m)1m+z3c?Wmx@z`-EEAipvhp!;Kbm?5X2D0kj+rcP|eW7(8DkV2Fki5IhEj=NKUH8UqO41H$KE_?`g-zXRd_Q8-9KfPnz02B(N>pejpX z>SzI`howNaA&_POrkNgK+E@xq2Mpl!zyMB5$ACOgn$iTTxCSKe0kI-51uy_p+j}7S z9f(I$z~Bf0U{v4*qwzmD;)zDC@CHUcBM`%AK8Ak`EMO6Es$gUWvn4>Pkl0L6HV06g z8Omk_ve}?)W*}RT5n>KVjVM$cWRn>L~%oSd9oTwL7T+&nxy zyu7@8e0==;`~m_3f`WoVLPEmA!XhFfqN1W=Vq)Ur;t~=Pl9G~AQc}{=(lRnKva+&r za&q$W@(KzHii(O#N=nMg$|@=KYmvnwpwgT3XuL+B!Nqy1Kf0dV2c$ z`UVCDhK7blMn=ZQ#wI2vrlzK5W@hH*<`xzfmX?-QR#w*5);2aawzjr*c6Rpm_6`mX zj*gB_PEO9w&Mq!4uCA_bZf@@G?j9ZO-;?s%`Gi0t*xzX zZEfxC?HwH*ot>RsU0vPX-90@$y}iACeSQ7?{Szikm^g9bq)C$|Po6ww%9N>7r%szT zZTj@-GiJ<~IdkT$S+i!(o;_#IoVj!7&YL%H{`~n17A#n}aN(jwixw|lykyCerAwDC zTefWZ^5rX5tXR2n<*HSyRoH%*%du|NsArKUo+Uftf%D zloLRCf`MZx!~eg#-8I=+I4mvh{{H^{{!R%71_cjB28W*F|L=~16e_0!iH^d4K?Vk| zb9al`Kw>>fAksk-B*h@W3^J6Vpa?9*ApqhqsDq^%6u@FoDMJacLWtCX7jZxbFc_?2 mWngHK`2KIMH&~K^;fMv$8T+eyk`x>!G+)|V|DTD8!5RQaJghJP literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/1.png b/spring-ldap/docs/reference/images/callouts/1.png new file mode 100644 index 0000000000000000000000000000000000000000..7d473430b7bec514f7de12f5769fe7c5859e8c5d GIT binary patch literal 329 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQC}X^4DKU-G|w_t}fLBA)Suv#nrW z!^h2QnY_`l!BOq-UXEX{m2up>JTQkX)2m zTvF+fTUlI^nXH#utd~++ke^qgmzgTe~DWM4ffP81J literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/10.gif b/spring-ldap/docs/reference/images/callouts/10.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb50b06d150685fbc333906361e32afbf7684993 GIT binary patch literal 968 zcmV;(12_CfNk%w1VGIBa0QUd@000010RaL60s{jB1Ox;H1qB8M1_uWR2nYxX2?+`c z3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_$0-K}2ss$t`}gnPyBrWO06>re zLJV*J{^dYWt5yncz0OHVaj#T}cmHbDss&(<}jYB?hWAjdxpF-idd;H(xSYY-?o1HkBC4gkG4 qLFjeQT8tF;{=Lfq000002mqw;_V3@nf0S|{K#+pcy?_4#0suRd literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/10.png b/spring-ldap/docs/reference/images/callouts/10.png new file mode 100644 index 0000000000000000000000000000000000000000..997bbc8246a316e040e0804174ba260e219d7d33 GIT binary patch literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQWtZ~+OvdJMW|Y+^UT?O-M{rKJsmzxdayJ{ zDCQA!%%@7Jj$q%-wf8e0_jRx8Dqi$}^?K=?6FriQFLv>>oc^CE+aVHhW3=nZ+fQ4!M=ZC7H>3sl|FJr3LwU zC3?yExf6FO?f@F61vV}-Juk7O6lk8Yg;}bFaZ-|HQc7Azopr01?u8M*si- literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/11.gif b/spring-ldap/docs/reference/images/callouts/11.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f5dba4f8df99fff77747affe9c6c03492ec896b GIT binary patch literal 244 zcmZ?wbhEHb*_Mn*=~*4EC>&cVUKsi~=%nVHqq z)opEU{r&yZr%#_dckZG^i`K1Mw|VpC9Xoa$IdbIe*|V1}UAley_T$Ho-@JMA;lqc2 z|Neo@1p~#OEDVf5mJWyqvXgP}^2;9)OfJm7I)A)~{gLS`_d;ZPy>0S|_X3{XE z)7O>#600DeuDZ?5tOl@ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=9KoYUDZ+`aP)jU z&ny=ErrK^#Gw!AcR}pdfMERuV^@&0$@(#^6b8c@rn^6RWX3pUb z4*6@PZ+H0#u=rjsXzS?6n6*sBGbHqGTU%mCsH?n#%j;eD^2}qe=iX*J@VQ3BRpz+u z{PX#N(^9X${`$90+;!pWs>o@z_n8G)7Uo7PJz`jrS+)QE@=PWHmc~UIw=WmUe73o7 z>^bR(M752aYoNg~ozu7U7&{(U>{s!;bn#f?ItjL^o`e{*EOQHqO;ccnz9hLK5@2cAyw@AaPFL~Cp#02|E|4xeQteNtB7waMs QVCXP-y85}Sb4q9e0GRUFb^rhX literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/12.gif b/spring-ldap/docs/reference/images/callouts/12.gif new file mode 100644 index 0000000000000000000000000000000000000000..a373d0b4f4203dc34d00cfc337fce3c6940ac0a5 GIT binary patch literal 244 zcmZ?wbhEHb2m08OKLyy@67BNn1 zV`M$b;Hb*j&z8jCVAzz(*|0d1*}-svnJ2^2O#T7^_7xgl3o~c6fy_O;6lj#|@c@$< P%QAt6&q75}91PX~p`BKN literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/12.png b/spring-ldap/docs/reference/images/callouts/12.png new file mode 100644 index 0000000000000000000000000000000000000000..31daf4e2f25b6712499ee32de9c2e3b050b691ca GIT binary patch literal 617 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1SD^YpWXnZI14-?iy0V%N{XE z)7O>#600De9$%>2LVd81Yeb1-X-P(Y5yQ%LXFPyHJS9LOm(=3qqRfJl%=|nCVNOM5 zpg0#u+&RCXvM4h>ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=Cn>wTzx1(qV@bS z0hYvspf(--lM>otrqbK$7p{3DzJ|+KN8%5ows)AI?zWk_n>jwEHXrTJecpEW_0xL= z?}N`*R`T~d2{AN${y8T#GEn4hUb&52^}Op@TW4{oc)A6)%$5=G}h# z?O{QLj@aRcAIf&y&OiUN=H2gq=_}V|pWfuReDV|{jwXw~>#w)I|9$3x|moMMCb?eciM{nM|`S|hUzkmNgCL#gF zpDYZFK)w!03}hz*YvF=rnZlC|CNImJwM-Kz+OQ~d)-w*#q=p-*7PHz|r?uJeim=Ww zV{C0@=>Ntrnaz(OL9u;eM8lFu#sozHRo??kGr1dh7*7~9Ey|P%1DVSLG^)+=Sc1ij PWtl+3XQ84f4hCxgsBBm& literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/13.png b/spring-ldap/docs/reference/images/callouts/13.png new file mode 100644 index 0000000000000000000000000000000000000000..14021a89c2ed3d4881afea6e3a315bce4f95efce GIT binary patch literal 623 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1SD^YpWXnZI14-?iy0V%N{XE z)7O>#600Dep5bGK9wD%hYeb1-X-P(Y5yQ%LXFPyHJS9LOm(=3qqRfJl%=|nCVNOM5 zpg0#u+&RCXvM4h>ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=Cn>w>~AWNX^a2R zbkveVY|45D7UnZ&JtjPwvdCCscZp0EA*0()#GOw)UH4-^&)y^E*4%UC)*|J}q_Ss;tN`nd8$>x9$_Xb^O2EpX&@C ZI46EzbLxq-voTO7gQu&X%Q~loCIF_C`w;*D literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/14.gif b/spring-ldap/docs/reference/images/callouts/14.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d6642ee96d73aa5b2efe17277f15c63e15ff643 GIT binary patch literal 244 zcmZ?wbhEHbgv_2w{G2f{P^+Pw{Jgw{P^$RKag>#K=CIF z10zsK2P6!#lYzA`VOnY=t7jyToEFN;z;JkSYGfEE2V(<6l11b+S?_5KEX!CT+8F(( zvRqlp;LjGuAfVc->c}`bkwHN5baLRK$*JrYWEePfJPT4IRYB%D08MZc1e)(ZEfr|E OB-C)A`C!DsU=08}Mo-uP literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/14.png b/spring-ldap/docs/reference/images/callouts/14.png new file mode 100644 index 0000000000000000000000000000000000000000..64014b75fe2e84d45ed861974c72462727979360 GIT binary patch literal 411 zcmV;M0c8G(P)!ax*-PXaQ9e~6^e1gu=a6a&KSz}bR`+prYG9ayB$BDjWGfIE;t#wl!+ zR3S(jA%y#i_@eOOedXoc%RQe%L;wH~k+s%ZI~)!<=dD%?4MaplaU9QPGski2q3`>r z(}{j@0a$CLl+)={2vLWml*i-oa5#J}DW$gCZB~Z!(!M#)2St|1_V^0qpmCrBof=Y&NUas@LmfSw=)4B4f;8Fu)(eFsv24 zJzXxBrayquXcR?Ji+1bU# z#kIAy&CSg{Jw1~rPo6n*=86?7wrtt5XV0EPhYnr2a^>dDn-3m5c>DJ4moH!b{rd+p z6b2N3vM?|LIXWN#kev*yg%7sn&Q|rkxh?nhwpdmMhK9|#x2N%XFg5sYwz$1bx0{Xk z_GO0a+gN$Os>~K+Jja&BAYj`ToN;JVE|Y+*Pie-X&AB`WbeJq+xeIcm-9YAoOlVUC XntyRyF3|Aku*lmW!=WgegTWdA>{?yt literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/15.png b/spring-ldap/docs/reference/images/callouts/15.png new file mode 100644 index 0000000000000000000000000000000000000000..0d65765fcf13dcfd87914744dec8bda115e4adf1 GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1SD^YpWXnZI14-?iy0V%N{XE z)7O>#600De0j~t#c`vY#Yeb1-X-P(Y5yQ%LXFPyHJS9LOm(=3qqRfJl%=|nCVNOM5 zpg0#u+&RCXvM4h>ql94%{~0TwC?8m~C^ZqJRG}m@H-L1 z5L@scq?{XUcxG{OP9jig5ySQaTl#^*93bKF#G<^+ymW>G($Cs~V(bw8rA5i93}62@ zzlJGu&d<$F%`0K}c4pdspcorSSx9C{PAbEScbC)|7#JBmT^vIy=9Eq_Jl&Ka(%QdX zh{H8O%#_7)Tc@t$mM`p4(Ne7omR*~(>gd8_8AZH{=3ms$Fmzm^yL@_+(#aQQ5>7QW z>3g2fIsH(ugM)!V$x4Rr_+!J_XU%4xbz0aE;^N{m@42Z|@0S@TQ=WbP`TMV5Ok;<| z^Ihv+@6tQ{sciRF9dD7Nr=KobwJJ68zJK$<1Pd9rz%4O)*;}Jzj&~nTGMecz>B%lV zK|`fmIc8mp-h8iSXiGFW=C(L+XH4DRxZQX87^-dLuD>odo6YLT@Sw)dfBEIG)v2@6 zR)%mL7GRj1x-&v&+2q@A%a&h0`Lw7|#(w_!tgT!PoJ|+re`l6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2FM=1vc2st?2`}gnPxflQdqzC~3 zK#X($?!^EQ!rHla#vlNQagPxI0Hv$}2yu@Q004|)006*f4*&q(Y5@Qc0|5X40001p zac>R)001^@s67~R_g00000F&F^=u;$*F7%?ya0Kn*83;>+Y qojZ4K4}ci={+){f00000006`|_wV1odyHZrK#+sdy?_4#0suS0gSs35 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/2.png b/spring-ldap/docs/reference/images/callouts/2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d09341b2f6d2ea2d1d5dad5d980f14b4b05dfd2 GIT binary patch literal 353 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQxaY7e*=hH)_rZeB4|imU1$R#1`!P>&$poQl;nzm}mD5ZFopaX|GsS%q*{P~< z;WtmO%lhToBL0i}yfkaOt?EN=nkLNGuU`ywhI5H)L`iUdT1k0gQ7VIjhO(w-Zen_> zZ(@38a<+nro{^q~f~BRtfrY+-p+a&|W^qZSLvCepNoKNMYO!8QX+eHoiC%Jk?!;Y+ zJAlS%fsM;d&r2*R1)67JkeZlkYGj#gX_9E3W@4U_nw*@Ln38B@k(iuhnUeN2e6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2FM=1vc2st?2`}gnPxflQtl zK#X($?!^EA!J9R2&L9AYagPxI0CUbEfbee(004|)0000X1po;D)&Kwy0|5X4006W) zXAJ=W001^@tB7y$s_tQG(OF&F^=!026!9PbDL0Kn*83;+;X q-MiNc0e~3y{+&w!00062006`|_wV1odyHZrfDnVyy?_4#0suROfV)2c literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/3.png b/spring-ldap/docs/reference/images/callouts/3.png new file mode 100644 index 0000000000000000000000000000000000000000..ef7b70047158970cf4e09f1bab2954d39c2d596b GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQF0kK0(Y1u|9Rc(19XFPiEBhjaDG}zd16s2gM)^$re|(qda7?? zdS-IAf{C7yo`r&?rM`iMzJZ}aa#3b+Nu@(>WpPPnvR-PjUP@^}eqM=Qa(?c_U5Yz^ z#%Y0#%S_KpEGY$=XJL?(l#*ybuErX#^g`ttQfwn6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_*Gfu?6iQ0{`}gnPJtY7D07wA= zK#p_&{wVRjGG#0000G0|Nj6TFybZ zHwOR!00=Mu2=Q)CihGPO004kM34k&G{{8#+uM_|PF-idd0001hdvgE)0Kn*84gdfE q0Pwa30Du(t{=Lfq00000005-$_V3@ndz@lGKoEn`y?_4#0suSSP`y|H literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/4.png b/spring-ldap/docs/reference/images/callouts/4.png new file mode 100644 index 0000000000000000000000000000000000000000..adb8364eb5d21ecdd4086e16110b62ddcb42aa4a GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQ3r>K)tuC)r#2`iJ>Prt42#Ndx#Uc~1)>aw z3jE@Q4|!9Z%lVv}- zc=48cF7H)t`(Ck`^+mtha~Np7bBSw2NpOBzNqJ&XDuaWDvZiNlVtT4?VtQtBwt|VC zk)DNurKP@sg}#BILUK`NaY>~^Ze?*vX0l#tv0h4PL4IC|UUGi!#9fLzfW~Qojmu2W zODrh`nrE42VU(7fm~5G9U~HM3l#*m_WNcxOXkuz6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_$0-K}2ss$t`}gnPyBr8oqzI7$ zK@4yI{^bCW<{Pv;Y7==^Ow6F-idd5aXYc5Z)*O0Kn*94gdfM qy}MTm0)Q0v{=Lfq00066005-$_V3@nf0S|{KoEn`y?_4#0suQhF}%G1 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/5.png b/spring-ldap/docs/reference/images/callouts/5.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7eb460021e845981861d77614539314f553993 GIT binary patch literal 348 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQEX4g z+-vfUhb0A>b04=Im{6XiQd1v%r%>h0$G8U7E1If8OQ!N~xOYY5h0NDT$p9(iZ?Q&e z18-(+l~J8O`)kc}e&uL$eW&>P-#`~Qm$*ih1m~xflqVLYGB{``YkKA;rl!p+yCFkc(+@-h!Xq*<< zxXkpt#FA2=d1VEBsYynrsitN|Y01eJ$;p;U#>wWX2KP5v&I9V=1L+C? fTFYQ)RAFeOZJ=$?lDoSWD8u0C>gTe~DWM4f^}upZ literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/6.gif b/spring-ldap/docs/reference/images/callouts/6.gif new file mode 100644 index 0000000000000000000000000000000000000000..d39640707444f5f67b2cd324143c2d6b40d27a40 GIT binary patch literal 968 zcmV;(12_CfNk%w1VGIBa0QUd@000010RaL60s{jB1Ox;H1qB8M1_uWR2nYxX2?+`c z3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_*Gfu?6iQ0{`}gnPJtY7DU`PP~ zK#p_&{wV<}SN&x`ij1T|-F-iddu;yKe5ciY-0Kn*84gdfs q-MdE!0Du(t{=Lfq00066005-$_V3@ndz^A0KoEn`y?_4#0suR2o4}_4 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/6.png b/spring-ldap/docs/reference/images/callouts/6.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba694af6c07d947d219b45a629bd32c60a0f5fe GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQ*)Bra@SU# zmiz#bR~{$s2si{S(aY|Z}Vd7tb ouUmn-_&~Y>fYve?8dVq?X&Y!8wB+ut16ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_S4&EY6iQm%`}gnPJt+_{K)?V2 zLXLC){%HZw>fgVA|EvLsajzEu00000z;I3r005M<000000DxM(0001xBL)Bf002n2 z7XttQ00?3L0001hwORlG004kM3jhEBa{QA500000F=_z-0D#dw1ONa40Kn*<5&!^d q)dBzj0Du(t{=E|d00000005*o_wV1of1Gk4K#+pby?_4#0suR4=(v0U literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/7.png b/spring-ldap/docs/reference/images/callouts/7.png new file mode 100644 index 0000000000000000000000000000000000000000..472e96f8ac36862c5645732f2fff19d06ee11a8e GIT binary patch literal 344 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQu%w%U~xZhnMEEs6JbBSw2NpOBzNqJ&XDuaWDvZiNlVtT4?VtQtBwt|VC zk)DNurKP@sg}#BILUK`NaY>~^Ze?*vX0l#tv0h4PL4IC|UUGi!#9fLzfW~Qojmu2W zODrh`nrCEbVQgk$XkwI@Y+{_8nv`N>YGIaQkz#0QY@Te9lBQ<)awbq0A4pdK&{_sV bqY6VKZ3AtCmfYR7Kp6&4S3j3^P66ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_*Gfu?5K>D0`}gnPJ0$=BKnMW< zK#p_&{s{p9pp-Xjy&wRHajz5r07~vb0B~*&005Mf001E59s~sM)&Kwy0|Nj60BW7{ zW(@%V00=Mu0HEcb6eaK0004kM2><}4dI12?suutNF-iddFy~#05a$R106^)V5C8}$ qoqIu&S`V$cAh@R~F=4@V4jxkzlaQrcFYWK{)(`o5XZnut z=nE4SU2g1ZW%;@@I$>_e3F8a=8WK~|CVXt1DqisQxtIX|`YW_n&?Nh#1gQ}d)$LrYTw(_{nVG)tp2V+#}WG*e^KRLdkoLz7g? qn(IA84Qgo42`r6v<+Hvch>@C7(8A5T-G@yGywn*$#_oy literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/9.gif b/spring-ldap/docs/reference/images/callouts/9.gif new file mode 100644 index 0000000000000000000000000000000000000000..bc5c8125b03849986c2df04f65f7406235c700a6 GIT binary patch literal 968 zcmV;(12_CfNk%w1VGIBa0QUd@000010RaL60s{jB1Ox;H1qB8M1_uWR2nYxX2?+`c z3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LV0RR91EC2ui01N;O000Q30RR2_*Gfu?5K>y*`}gnPJs|)9K!5-M zK#q6+{wV=~pp~_Ar2qiPajz8s0CT({z;I6s005Mf002;`6#xL%N&x_n0|Nj6d%PjQ zaIY5t00=Mu005!ayL0Di0RVtN2mk;85FkKcjS>I=F-iddAmm;MCI4~&0Kn*84gdgJ q{d>0t0Du(t{=JI<00062006}B_V3@nf0SZCKoEn`y?_4#0suSwcfTJ1 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/images/callouts/9.png b/spring-ldap/docs/reference/images/callouts/9.png new file mode 100644 index 0000000000000000000000000000000000000000..a0676d26cc2ff1de12c4ecdeefb44a0d71bc6bde GIT binary patch literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^JRr;gBp8b2n5}^nQNRqa;^5&H%t0&v*|C|wdb9$wI zR@+N9#RIowg@Uqn&z-__Tzhhz!sG|vTxA7?=O|Y?u(d4T{!RM9c7chr6d%1?R=i16 z?@Ic{f32YJFJnVhX)qGzOMplv!L->5yAlT#}irms+fsQd*FoSE84k zpF44v;trs3T43Wc)AJHbN`dAXo0u6Hr<$gkq?lM38ycjV7+5A5Sr{ayr5c%-n;95g pF*H#D>f!_G3IJNmU}#ifXryhRZP1dtyA~+J;OXk;vd$@?2>@J{cB%jX literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/readme.txt b/spring-ldap/docs/reference/readme.txt new file mode 100644 index 00000000..6280723d --- /dev/null +++ b/spring-ldap/docs/reference/readme.txt @@ -0,0 +1,20 @@ +This project uses the 'DocBook XSL distribution' for HTML and PDF +generation of project reference documentation. + +This project's build.xml file contains targets to generate the +project reference documentation. + +To generate project documentation, execute one of the following +build targets: + +* doc-all - generate documentation in all supported formats +* doc-pdf - generate the PDF documentation +* doc-html - generate the HTML documentation +* doc-htmlsingle - generate single page HTML documentation +* doc-clean - clean any output directories for docs + +For generation to complete successfully, you must have first extracted +the .jar libraries contained in this archive: + - http://static.springframework.org/spring/files/docbook-reference-libs.zip +... to ${basedir}/docs/reference. If you have not yet done so, download this file +and unzip the contents of the archive into ${basedir}/docs/reference. \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/basic.xml b/spring-ldap/docs/reference/src/basic.xml new file mode 100644 index 00000000..ed0efa86 --- /dev/null +++ b/spring-ldap/docs/reference/src/basic.xml @@ -0,0 +1,385 @@ + + + Basic Operations + + + Search and Lookup Using AttributesMapper + + In this example we will use an AttributesMapper + to easily build a List of all common names of all person objects. + + + AttributesMapper that returns a single attribute + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + + public void setLdapTemplate(LdapTemplate ldapTemplate) { + this.ldapTemplate = ldapTemplate; + } + + public List getAllPersonNames() { + return ldapTemplate.search( + "", "(objectclass=person)", + new AttributesMapper() { + public Object mapFromAttributes(Attributes attrs) + throws NamingException { + return attrs.get("cn").get(); + } + }); + } +} + + + The inline implementation of AttributesMapper + just gets the desired attribute value from the + Attributes and returns it. Internally, + LdapTemplate iterates over all entries found, calling + the given AttributesMapper for each entry, and collects + the results in a list. The list is then returned by the + search method. + + Note that the AttributesMapper implementation + could easily be modified to return a full Person + object: + + + AttributesMapper that returns a Person object + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + private class PersonAttributesMapper implements AttributesMapper() { + public Object mapFromAttributes(Attributes attrs) throws NamingException { + Person person = new Person(); + person.setFullName((String)attrs.get("cn").get()); + person.setLastName((String)attrs.get("sn").get()); + person.setDescription((String)attrs.get("description").get()); + return person; + } + } + + public List getAllPersons() { + return ldapTemplate.search("", "(objectclass=person)", new PersonAttributesMapper(); + } +} + + + If you have the distinguished name (dn) that + identifies an entry, you can retrieve the entry directly, without + searching for it. This is called a lookup in Java + LDAP. The following example shows how a lookup results in a Person + object: + + + A lookup resulting in a Person object + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + public Person findPerson(String dn) { + return (Person) ldapTemplate.lookup(dn, new PersonAttributesMapper()); + } +} + + + This will look up the specified dn and pass the + found attributes to the supplied AttributesMapper, in + this case resulting in a Person object. + + + + Building Dynamic Filters + + We can build dynamic filters to use in searches, using the classes + from the org.springframework.ldap.support.filter + package. Let's say that we want the following filter: + (&(objectclass=person)(sn=?)), where we want the + ? to be replaced with the value of the parameter + lastName. This is how we do it using the filter support + classes: + + + Building a search filter dynamically + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + public List getPersonNamesByLastName(String lastName) { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "person")); + filter.and(new EqualsFilter("sn", lastName)); + return ldapTemplate.search( + "", filter.encode(), + new AttributesMapper() { + public Object mapFromAttributes(Attributes attrs) + throws NamingException { + return attrs.get("cn").get(); + } + }); + } +} + + + To perform a wildcard search, it's possible to use the + WhitespaceWildcardsFilter: + + + Building a wildcard search filter + + AndFilter filter = new AndFilter(); +filter.and(new EqualsFilter("objectclass", "person")); +filter.and(new WhitespaceWildcardsFilter("cn", cn)); + + + + + In addition to simplifying building of complex search filters, + the Filter classes also provide proper escaping + of any unsafe characters. This prevents "ldap injection", + where a user might use such characters to inject unwanted operations + into your LDAP operations. + + + + + + Building Dynamic Distinguished Names + + The standard Name + interface represents a generic name, which is basically an ordered + sequence of components. The Name interface also + provides operations on that sequence; e.g., add or + remove. LdapTemplate provides an implementation of the + Name interface: DistinguishedName. + Using this class will greatly simplify building distinguished names, + especially considering the sometimes complex rules regarding escapings and + encodings. As with the Filter classes this helps preventing + potentially malicious data being injected into your LDAP operations. + + + The following example illustrates how + DistinguishedName can be used to dynamically construct + a distinguished name: + + + Building a distinguished name dynamically + + package com.example.dao; + +import org.springframework.ldap.support.DistinguishedName; +import javax.naming.Name; + +public class PersonDaoImpl implements PersonDao { + public static final String BASE_DN = "dc=example,dc=com"; + ... + protected Name buildDn(Person p) { + DistinguishedName dn = new DistinguishedName(BASE_DN); + dn.add("c", p.getCountry()); + dn.add("ou", p.getCompany()); + dn.add("cn", p.getFullname()); + return dn; + } +} + + + Assuming that a Person has the following attributes: + + + + + + country + + Sweden + + + + company + + Some Company + + + + fullname + + Some Person + + + + + + The code above would then result in the following distinguished + name: + + cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com + + In Java 5, there is an implementation of the Name interface: LdapName. + If you are in the Java 5 world, you might as well use + LdapName. However, you may still use + DistinguishedName if you so wish. + + + + Binding and Unbinding + + + Binding Data + + Inserting data in Java LDAP is called binding. In order to do + that, a distinguished name that uniquely identifies the new entry is + required. The following example shows how data is bound using + LdapTemplate: + + + Binding data using Attributes + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + public void create(Person p) { + Name dn = buildDn(p); + ldapTemplate.bind(dn, null, buildAttributes(p)); + } + + private Attributes buildAttributes(Person p) { + Attributes attrs = new BasicAttributes(); + BasicAttribute ocattr = new BasicAttribute("objectclass"); + ocattr.add("top"); + ocattr.add("person"); + attrs.put(ocattr); + attrs.put("cn", "Some Person"); + attrs.put("sn", "Person"); + return attrs; + } +} + + + The Attributes building is--while dull and verbose--sufficient for + many purposes. It is, however, possible to simplify the binding + operation further, which will be described in . + + + + Unbinding Data + + Removing data in Java LDAP is called unbinding. A distinguished + name (dn) is required to identify the entry, just as in the binding + operation. The following example shows how data is unbound using + LdapTemplate: + + + Unbinding data + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + public void delete(Person p) { + Name dn = buildDn(p); + ldapTemplate.unbind(dn); + } +} + + + + + + Modifying + + In Java LDAP, data can be modified in two ways: either using + rebind or + modifyAttributes. + + + Modifying using <literal>rebind</literal> + + A rebind is a very crude way to modify data. + It's basically an unbind followed by a + bind. It looks like this: + + + Modifying using rebind + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + public void update(Person p) { + Name dn = buildDn(p); + ldapTemplate.rebind(dn, null, buildAttributes(p)); + } +} + + + + + Modifying using <literal>modifyAttributes</literal> + + If only the modified attributes should be replaced, there is a + method called modifyAttributes that takes an array of + modifications: + + + Modifying using modifyAttributes + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + ... + public void updateDescription(Person p) { + Name dn = buildDn(p); + Attribute attr = new BasicAttribute("description", p.getDescription()) + ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr); + ldapTemplate.modifyAttributes(dn, new ModificationItem[] {item}); + } +} + + + Building Attributes and + ModificationItem arrays is a lot of work, but as you + will see in , the update operations + can be simplified. + + + + + Sample applications + + It is recommended that you review the Spring LDAP sample + applications included in the release distribution for best-practice + illustrations of the features of this library. A description of each + sample is provided below: + + + + spring-ldap-person - the sample demonstrating most + features. + + + + spring-ldap-article - the sample application that was written + to accompany a java.net + article about Spring LDAP. + + + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/configuration.xml b/spring-ldap/docs/reference/src/configuration.xml new file mode 100644 index 00000000..09f1a45b --- /dev/null +++ b/spring-ldap/docs/reference/src/configuration.xml @@ -0,0 +1,195 @@ + + + Configuration + + + ContextSource Configuration + + There are several properties in AbstractContextSource + (superclass of DirContextSource and LdapContextSource) + that can be used to modify its behaviour. + + + LDAP Server URLs + + The URL of the LDAP server is specified using the url property. + The URL should be in the format ldap://myserver.example.com:389. + For SSL access, use the ldaps protocol and the appropriate port, e.g. + ldaps://myserver.example.com:636 + It is possible to configure multiple alternate LDAP servers using the + urls property. In this case, supply all server urls in a String + array to the urls property. + + + + Authentication + + Authenticated contexts are created for both read-only and + read-write operations by default. You specify + userName and password of the LDAP + user to be used for authentication on the + ContextSource. + + + The userName needs to be the full + Distinguished Name (DN) of the user. + + + Some LDAP server setups allow anonymous read-only access. If you + want to use anonymous Contexts for read-only operations, set the + anonymousReadOnly property to + true. + + + Custom Authentication Using Acegi + + While the user name (i.e. user DN) and password used for + creating an authenticated Context are static by + default - the ones set on the ContextSource on + startup will be used throughout the lifetime of the + ContextSource - there are however several cases in + which this is not the desired behaviour. A common scenario is that the + principal and credentials of the current user should be used when + executing LDAP operations for that user. The default behaviour can be + modified by supplying a custom AuthenticationSource + implementation to the ContextSource on startup, + instead of explicitly specifying the userName and + password. The + AuthenticationSource will be queried by the + ContextSource for principal and credentials each + time an authenticated Context is to be + created. + + To use the authentication information of the currently logged in + user using Acegi + Security, use the + AcegiAuthenticationSource: + + + The Spring bean definition for an + AcegiAuthenticationSource + + <beans> + ... + <bean id="contextSource" class="org.springframework.ldap.support.LdapContextSource"> + <property name="url" value="ldap://localhost:389" /> + <property name="base" value="dc=example,dc=com" /> + <property name="acegiAuthenticationSource" ref="authenticationSource" /> + </bean> + + <bean id="acegiAuthenticationSource" + class="org.springframework.ldap.support.authentication.AcegiAuthenticationSource" /> + ... +</beans> + + + + We don't specify any userName or + password to our ContextSource + when using an AuthenticationSource - these + properties are needed only when the default behaviour is + used. + + + + When using the AcegiAuthenticationSource + you need to use Acegi's + LdapAuthenticationProvider to authenticate the + users against LDAP. + + + + + Default Authentication + + When using AcegiAuthenticationSource, + authenticated contexts will only be possible to create once the user + is logged in using Acegi. To use default authentication information + when no user is logged in, use the + DefaultValuesAuthenticationSourceDecorator: + + + Configuring a + DefaultValuesAuthenticationSourceDecorator + + <beans> + ... + <bean id="contextSource" class="org.springframework.ldap.support.LdapContextSource"> + <property name="url" value="ldap://localhost:389" /> + <property name="base" value="dc=example,dc=com" /> + <property name="authenticationSource" ref="authenticationSource" /> + </bean> + + <bean id="authenticationSource" + class="org.springframework.ldap.support.DefaultValuesAuthenticationSourceDecorator"> + <property name="target" ref="acegiAuthenticationSource" /> + <property name="defaultUser" value="cn=myDefaultUser" /> + <property name="defaultPassword" value="pass" /> + </bean> + + <bean id="acegiAuthenticationSource" + class="org.springframework.ldap.support.authentication.AcegiAuthenticationSource" /> + ... +</beans> + + + + + + Pooling + + LDAP connection pooling can be turned on/off using the + pooled flag. Default is true. The + configuration of LDAP connection pooling is managed using + System properties, so this needs to be handled + manually. Details of pooling configuration can be found here. + + + + Advanced ContextSource Configuration + + Alternate ContextFactory + + It is possible to configure the ContextFactory that the + ContextSource is to use when creating Contexts using the + contextFactory property. The default value is + com.sun.jndi.ldap.LdapCtxFactory. + + + Custom DirObjectFactory + + As described in , a DirObjectFactory + can be used to translate the Attributes of found Contexts + to a more useful DirContext implementation. This can be + configured using the dirObjectFactory property. You can use + this property if you have your own, custom DirObjectFactory implementation. + The default value is DefaultDirObjectFactory. + + + Custom DirContext Environment Properties + + In some cases the user might want to specify additional environment setup properties + in addition to the ones directly configurable from AbstractContextSource. + Such properties should be set in a Map and supplied to + the baseEnvironmentProperties property. + + + + + LdapTemplate Configuration + + + Ignoring PartialResultExceptions + + Some Active Directory (AD) servers are unable to automatically following + referrals, which often leads to a PartialResultException being + thrown in searches. You can specify that PartialResultException + is to be ignored by setting the ignorePartialResultException + property to true. + This causes all referrals to be ignored, and no notice will be given that + a PartialResultException has been encountered. + There is currently no way of manually following referrals using LdapTemplate. + + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/contextprocessor.xml b/spring-ldap/docs/reference/src/contextprocessor.xml new file mode 100644 index 00000000..dae84b91 --- /dev/null +++ b/spring-ldap/docs/reference/src/contextprocessor.xml @@ -0,0 +1,226 @@ + + + Processing the DirContext + + + Custom DirContext Pre/Postprocessing + + In some situations, one would like to perform operations on the + DirContext before and after the search operation. The + interface that is used for this is called + DirContextProcessor: + + + public interface DirContextProcessor { + public void preProcess(DirContext ctx) throws NamingException; + public void postProcess(DirContext ctx) throws NamingException; +} + + + The LdapTemplate class has a search method that + takes a DirContextProcessor: + + + public void search(SearchExecutor se, NameClassPairCallbackHandler handler, + DirContextProcessor processor) throws DataAccessException; + + + Before the search operation, the preProcess + method is called on the given DirContextProcessor + instance. After the search has been executed and the resulting + NamingEnumeration has been processed, the + postProcess method is called. This enables a user to + perform operations on the DirContext to be used in the + search, and to check the DirContext when the search has + been performed. This can be very useful for example when handling request + and response controls. + + There are also a few convenience methods for those that don't need a + custom SearchExecutor: + + + 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) + + + + + Implementing a Request Control DirContextProcessor + + 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 + DirContextProcessor, Spring LDAP provides the base + class AbstractRequestControlDirContextProcessor. This + class handles the retrieval of the current request controls from the + LdapContext, calls a template method for creating a + request control, and adds it to the LdapContext. All + you have to do in the subclass is to implement the template method + createRequestControl, and of course the + postProcess method for performing whatever you need to + do after the search. + + + public abstract class AbstractRequestControlDirContextProcessor implements + DirContextProcessor { + + public void preProcess(DirContext ctx) throws NamingException { + ... + } + + public abstract Control createRequestControl(); +} + + This is what it can look like when you implement your own request + control DirContextProcessor: + + + + A request control DirContextProcessor implementation + + 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 < responseControls.length; i++) { + if (responseControls[i] instanceof SomeCoolResponseControl) { + SomeCoolResponseControl control = (SomeCoolResponseControl) responseControls[i]; + this.cookie = new MyCoolCookie(control.getCookie()); + } + } + } +} + + + + Make sure you use LdapContextSource when you + use Controls. The Control + interface is specific for LDAPv3 and requires that + LdapContext is used instead of + DirContext. If an + AbstractRequestControlDirContextProcessor subclass is + called with an argument that is not an LdapContext, + it will throw an IllegalArgumentException. + + + + + Paged Search Results + + 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 paged search results. 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. + + Some LDAP servers have support for the + PagedResultsControl, 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 cookie 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. + + Spring LDAP provides support for paged results by leveraging the + concept for pre- and postprocessing of an LdapContext that was discussed + in the previous sections. It does so by providing two classes: + PagedResultsRequestControl and + PagedResultsCookie. The + PagedResultsRequestControl class creates a + PagedResultsControl with the requested page size and + adds it to the LdapContext. After the search, it gets + the PagedResultsResponseControl 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 + PagedResultsControl. In order to make it easy to store + this cookie between searches, Spring LDAP provides the wrapper class + PagedResultsCookie. + + This is an example of how the paged search results functionality can + be used: + + + Example of an integration test for paged search results + + public class LdapTemplatePagedSearchITest extends TestCase { + private LdapTemplate tested; + ... + // LDAP contains 5 persons matching the filter. Page size is 3. + // Expects two batches of 3 and 2 persons respectively. + public void testPagedResult() { + SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + String base = "dc=example,dc=com"; + String filter = "(&(objectclass=person)(cn=Some Person*))"; + PersonAttributesMapper mapper = new PersonAttributesMapper(); + CollectingNameClassPairCallbackHandler handler = + tested.new AttributesMapperCallbackHandler(mapper); + + PagedResultsRequestControl requestControl; + requestControl = new PagedResultsRequestControl(3); + tested.search(base, filter, searchControls, handler, requestControl); + PagedResultsCookie cookie = requestControl.getCookie(); + assertNotNull("Cookie should not be null yet", cookie.getCookie()); + assertEquals(3, callbackHandler.getList().size()); + + // Prepare for second and last search + requestControl = new PagedResultsRequestControl(3, cookie); + tested.search(base, filter, searchControls, handler, requestControl); + cookie = requestControl.getCookie(); + assertNull("Cookie should be null now", cookie.getCookie()); + assertEquals(5, callbackHandler.getList().size()); + } + + + + Important to note here is that we use the same + CollectingNameClassPairCallbackHandler for both + searches. This means that the results are appended to the same list. The + second batch of two are added to the first three, giving a total of five + after the second search. + + When using the PagedResultsRequestControl it is imperative + that you keep track of the cookie returned from an operation and supply the same + instance to subsequent calls. This means that your Dao method will typically need to + wrap the result list together with the cookie in the value returned to the higher tiers. + + + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/dirobjectfactory.xml b/spring-ldap/docs/reference/src/dirobjectfactory.xml new file mode 100644 index 00000000..5c5edbc8 --- /dev/null +++ b/spring-ldap/docs/reference/src/dirobjectfactory.xml @@ -0,0 +1,286 @@ + + + DirObjectFactory and DirContextAdapter + + + Introduction + + A little-known--and probably underestimated--feature of the Java + LDAP API is the ability to register a DirObjectFactory + to automatically create objects from found contexts. One of the reasons + why it is seldom used is that you will need an implementation of + DirObjectFactory that creates instances of a meaningful + implementation of DirContext. The Spring LDAP library + provides the missing pieces: a default implementation of + DirContext called DirContextAdapter, + and a corresponding implementation of DirObjectFactory + called DefaultDirObjectFactory. Used together with + DefaultDirObjectFactory, the + DirContextAdapter can be a very powerful tool. + + + + Search and Lookup Using ContextMapper + + The DefaultDirObjectFactory is registered with + the ContextSource by default, which means that whenever + a context is found in the LDAP tree, its Attributes and + Distinguished Name (DN) will be used to construct a + DirContextAdapter. This enables us to use a + ContextMapper instead of an + AttributesMapper to transform found values: + + + Searching using a ContextMapper + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + ... + private static class PersonContextMapper implements ContextMapper { + public Object mapFromContext(Object ctx) { + DirContextAdapter context = (DirContextAdapter)ctx; + Person p = new Person(); + p.setFullName(context.getStringAttribute("cn")); + p.setLastName(context.getStringAttribute("sn")); + p.setDescription(context.getStringAttribute("description")); + return p; + } + } + + public Person findByPrimaryKey( + String name, String company, String country) { + Name dn = buildDn(name, company, country); + return ldapTemplate.lookup(dn, new PersonContextMapper()); + } +} + + + The above code shows that it is possible to retrieve the attributes + directly by name, without having to go through the + Attributes and BasicAttribute + classes. + + + + Binding and Modifying Using ContextMapper + + The DirContextAdapter can also be used to hide the Attributes when + binding and modifying data. + + + Binding + + This is an example of an improved implementation of the create DAO + method. Compare it with the previous implementation in . + + + Binding using DirContextAdapter + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + ... + public void create(Person p) { + Name dn = buildDn(p); + DirContextAdapter context = new DirContextAdapter(dn); + + context.setAttributeValues("objectclass", new String[] {"top", "person"}); + context.setAttributeValue("cn", p.getFullname()); + context.setAttributeValue("sn", p.getLastname()); + context.setAttributeValue("description", p.getDescription()); + + ldapTemplate.bind(dn, context, null); + } +} + + + Note that we use the retrieved + DirContextAdapter as the second parameter to bind, + which should be a Context. The third parameter is + null, since we're not using any + Attributes. + + + + Modifying + + The code for a rebind would be pretty much + identical to , except + that the method called would be rebind. However, + let's say that you don't want to remove and re-create the entry, but + instead update only the attributes that have changed. The + DirContextAdapter has the ability to keep track of + its modified attributes. The following example takes advantage of this + feature: + + + Modifying using DirContextAdapter + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + ... + public void update(Person p) { + Name dn = buildDn(p); + DirContextAdapter context = (DirContextAdapter)ldapTemplate.lookup(dn); + + context.setAttributeValues("objectclass", new String[] {"top", "person"}); + context.setAttributeValue("cn", p.getFullname()); + context.setAttributeValue("sn", p.getLastname()); + context.setAttributeValue("description", p.getDescription()); + + ldapTemplate.modifyAttributes(dn, context.getModificationItems()); + } +} + + + The observant reader will see that we have duplicated code in the + create and update methods. This + code maps from a domain object to a context. It can be extracted to a + separate method: + + + Binding and modifying using DirContextAdapter + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + + ... + public void create(Person p) { + Name dn = buildDn(p); + DirContextAdapter context = new DirContextAdapter(dn); + mapToContext(p, context); + ldapTemplate.bind(dn, context, null); + } + + public void update(Person p) { + Name dn = buildDn(p); + DirContextAdapter context = (DirContextAdapter)ldapTemplate.lookup(dn); + mapToContext(person, context); + ldapTemplate.modifyAttributes(dn, context.getModificationItems()); + } + + protected void mapToContext (Person p, DirContextAdapter context) { + context.setAttributeValues("objectclass", new String[] {"top", "person"}); + context.setAttributeValue("cn", p.getFullName()); + context.setAttributeValue("sn", p.getLastName()); + context.setAttributeValue("description", p.getDescription()); + } +} + + + + + + A Complete PersonDao Class + + To illustrate the power of Spring LDAP, here is a complete Person + DAO implementation for LDAP in just 68 lines: + + + A complete PersonDao class + + package com.example.dao; + +import java.util.List; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.springframework.ldap.AttributesMapper; +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.ldap.support.filter.EqualsFilter; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + + public void setLdapTemplate(LdapTemplate ldapTemplate) { + this.ldapTemplate = ldapTemplate; + } + + public void create(Person person) { + DirContextAdapter context = new DirContextAdapter(); + mapToContext(person, context); + ldapTemplate.bind(buildDn(person), context, null); + } + + public void update(Person person) { + Name dn = buildDn(person); + DirContextAdapter context = (DirContextAdapter)ldapTemplate.lookup(dn); + mapToContext(person, context); + ldapTemplate.modifyAttributes(dn, context.getModificationItems()); + } + + public void delete(Person person) { + ldapTemplate.unbind(buildDn(person)); + } + + public Person findByPrimaryKey(String name, String company, String country) { + Name dn = buildDn(name, company, country); + return (Person) ldapTemplate.lookup(dn, getContextMapper()); + } + + public List findAll() { + EqualsFilter filter = new EqualsFilter("objectclass", "person"); + return ldapTemplate.search(DistinguishedName.EMPTY_PATH, filter.encode(), getContextMapper()); + } + + protected ContextMapper getContextMapper() { + return new PersonContextMapper(); + } + + protected Name buildDn(Person person) { + return buildDn(person.getFullname(), person.getCompany(), person.getCountry()); + } + + protected Name buildDn(String fullname, String company, String country) { + DistinguishedName dn = new DistinguishedName(); + dn.add("c", country); + dn.add("ou", company); + dn.add("cn", fullname); + return dn; + } + + protected void mapToContext(Person person, DirContextAdapter context) { + context.setAttributeValues("objectclass", new String[] {"top", "person"}); + context.setAttributeValue("cn", person.getFullName()); + context.setAttributeValue("sn", person.getLastName()); + context.setAttributeValue("description", person.getDescription()); + } + + private static class PersonContextMapper implements ContextMapper { + public Object mapFromContext(Object ctx) { + DirContextAdapter context = (DirContextAdapter)ctx; + Person person = new Person(); + person.setFullName(context.getStringAttribute("cn")); + person.setLastName(context.getStringAttribute("sn")); + person.setDescription(context.getStringAttribute("description")); + return person; + } + } +} + + + + In several cases the Distinguished Name (DN) of an object is + constructed using properties of the object. E.g. in the above example, + the country, company and full name of the Person are + used in the DN, which means that updating any of these properties will + actually require moving the entry in the LDAP tree using the + rename() operation in addition to updating the + Attribute values. Since this is highly implementation + specific this is something you'll need to keep track of yourself - + either by disallowing the user to change these properties or performing + the rename() operation in your + update() method if needed. + + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/executors.xml b/spring-ldap/docs/reference/src/executors.xml new file mode 100644 index 00000000..237fa3a1 --- /dev/null +++ b/spring-ldap/docs/reference/src/executors.xml @@ -0,0 +1,133 @@ + + + Adding Missing Overloaded API Methods + + + Implementing Custom Search Methods + + While LdapTemplate contains several overloaded + versions of the most common operations in DirContext, + we have not provided an alternative for each and every method signature, + mostly because there are so many of them. We have, however, provided a + means to call whichever overloaded method you want. Let's say, for + example, that you want to use the following method: + + NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls ctls) + + The way to do this is to use a custom + SearchExecutor implementation: + + + public interface SearchExecutor { + public NamingEnumeration executeSearch(DirContext ctx) throws NamingException; +} + + + + A custom search method using SearchExecutor and + AttributesMapper + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + ... + public List search(final Name base, final String filter, final String[] params, + final SearchControls ctls) { + SearchExecutor executor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) { + return ctx.search(base, filter, params, ctls); + } + }; + + NameClassPairCallbackHandler handler = + ldapTemplate.new AttributesMapperCallbackHandler(new PersonAttributesMapper()); + + return ldapTemplate.search(executor, handler); + } +} + + + If you prefer the ContextMapper to the + AttributesMapper, this is what it would look + like: + + + A custom search method using SearchExecutor and + ContextMapper + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + ... + public List search(final Name base, final String filter, final String[] params, + final SearchControls ctls) { + SearchExecutor executor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) { + return ctx.search(base, filter, params, ctls); + } + }; + + NameClassPairCallbackHandler handler = + ldapTemplate.new ContextMapperCallbackHandler(new PersonContextMapper()); + + return ldapTemplate.search(executor, handler); + } +} + + + + When using the + LdapTemplate.ContextMapperCallbackHandler you must + make sure that you have called + setReturningObjFlag(true) on your + SearchControls instance. + + + + + Implementing Other Custom Context Methods + + In the same manner as for custom search methods, + you can actually execute any method in DirContext by + using a ContextExecutor. + + + public interface ContextExecutor { + public Object executeWithContext(DirContext ctx) throws NamingException; +} + + When implementing a custom ContextExecutor, you + can choose between using the executeReadOnly() or the + executeReadWrite() method. Let's say that we want to + call this method: + + + Object lookupLink(Name name) + + It's available in DirContext, but there is no + matching method in LdapTemplate. It's a lookup method, + so it should be read-only. We can implement it like this: + + + A custom DirContext method using ContextExecutor + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + ... + public Object lookupLink(final Name name) { + ContextExecutor executor = new ContextExecutor() { + public Object executeWithContext(DirContext ctx) { + return ctx.lookupLink(name); + } + }; + + return ldapTemplate.executeReadOnly(executor); + } +} + + In the same manner you can execute a read-write operation using + the executeReadWrite() method. + + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/images/banner4.jpg b/spring-ldap/docs/reference/src/images/banner4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef33d2aefed9e2bfba11add8d1841ea5e7be11e9 GIT binary patch literal 83374 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 z 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 ZS8OItGvK?g2SfIM{e>0(*I)Sc{{bz;*^&SN literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/src/images/bannerR.gif b/spring-ldap/docs/reference/src/images/bannerR.gif new file mode 100644 index 0000000000000000000000000000000000000000..548ab8848daf59ca783e1a21d131d7af7a71ff68 GIT binary patch literal 7949 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 literal 0 HcmV?d00001 diff --git a/spring-ldap/docs/reference/src/images/logo.png b/spring-ldap/docs/reference/src/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..31396b8a49cd65687bce18f95777cd610d195c5c GIT binary patch literal 23834 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 + + + + + + + +]> + + + + + + Spring LDAP + Reference Documentation + Version 1.1.2 + December 2006 + + + Mattias + Arthursson + + + Ulrik + Sandberg + + + + + Copies of this document may be made for your own use and for + distribution to others, provided that you do not charge any + fee for such copies and further provided that each copy + contains this Copyright Notice, whether distributed in print + or electronically. + + + + + + &preface; + &overview; + &basic; + &dirobjectfactory; + &executors; + &contextprocessor; + &configuration; + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/overview.xml b/spring-ldap/docs/reference/src/overview.xml new file mode 100644 index 00000000..67bd5172 --- /dev/null +++ b/spring-ldap/docs/reference/src/overview.xml @@ -0,0 +1,325 @@ + + + Introduction + + + Overview + + Spring-LDAP (http://www.springframework.org/ldap) + is a library for simpler LDAP programming in Java, built on the same + principles as the JdbcTemplate + in Spring JDBC. It completely eliminates the need to worry about creating + and closing LdapContext and looping through + NamingEnumeration. It also provides a more + comprehensive unchecked Exception hierarchy, built on Spring's + DataAccessException. As a bonus, it also contains + classes for dynamically building LDAP filters and DNs (Distinguished + Names). + + Consider, for example, a method that should search some storage for + all persons and return their names in a list. Using JDBC, we would create + a connection and execute a query + using a statement. We would then loop over the + result set and retrieve the + column we want, adding it to a list. In contrast, + using Java LDAP, we would create a context and + perform a search using a search + filter. We would then loop over the resulting naming + enumeration and retrieve the attribute we + want, adding it to a list. + + The traditional way of implementing this person name search method + in Java LDAP looks like this: + + + package com.example.dao; + +public class TraditionalPersonDaoImpl implements PersonDao { + public List getAllPersonNames() { + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, "ldap://localhost:389/dc=example,dc=com"); + + DirContext ctx; + try { + ctx = new InitialDirContext(env); + } catch (NamingException e) { + throw new RuntimeException(e); + } + + LinkedList list = new LinkedList(); + NamingEnumeration results = null; + try { + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + results = ctx.search("", "(objectclass=person)", controls); + + while (results.hasMore()) { + SearchResult searchResult = (SearchResult) results.next(); + Attributes attributes = searchResult.getAttributes(); + Attribute attr = attributes.get("cn"); + String cn = (String) attr.get(); + list.add(cn); + } + } catch (NameNotFoundException e) { + // The base context was not found. + // Just clean up and exit. + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + return list; + } +} + + + By using the Spring LDAP AttributesMapper, we get + the exact same functionality with the following code: + + + package com.example.dao; + +public class PersonDaoImpl implements PersonDao { + private LdapTemplate ldapTemplate; + + public void setLdapTemplate(LdapTemplate ldapTemplate) { + this.ldapTemplate = ldapTemplate; + } + + public List getAllPersonNames() { + return ldapTemplate.search( + "", "(objectclass=person)", + new AttributesMapper() { + public Object mapFromAttributes(Attributes attrs) + throws NamingException { + return attrs.get("cn").get(); + } + }); + } +} + + + + + Packaging overview + + At a minimum, to use Spring LDAP you need: + + + + spring-ldap (the Spring LDAP library) + + + + spring-core (miscellaneous utility classes used internally by + the framework) + + + + spring-beans (contains interfaces and classes for manipulating + Java beans) + + + + spring-dao (exception hierarchy enabling sophisticated error + handling independent of the data access approach in use) + + + + commons-logging (a simple logging facade, used + internally) + + + + commons-lang (misc utilities, used internally) + + + + commons-collections (tools for working with collections, used + internally) + + + + If your application is wired up using the Spring ApplicationContext, + you also need: + + + + spring-context (adds the ability for application objects to + obtain resources using a consistent API) + + + + If you use the AcegiAuthenticationSource, you + also need: + + + + acegi-security + + + + Set up the required beans in your Spring context file and inject the + LdapTemplate into your data access object: + + + <beans> + ... + <bean id="contextSource" class="org.springframework.ldap.support.LdapContextSource"> + <property name="url" value="ldap://localhost:389" /> + <property name="base" value="dc=example,dc=com" /> + <property name="userName" value="cn=Manager" /> + <property name="password" value="secret" /> + </bean> + + <bean id="ldapTemplate" class="org.springframework.ldap.LdapTemplate"> + <constructor-arg ref="contextSource" /> + </bean> + + <bean id="myDataAccessObject" class="com.example.MyDataAccessObject"> + <property name="ldapTemplate" ref="ldapTemplate" /> + </bean> + ... +</beans> + + + + + Package structure + + This section provides an overview of the logical package structure + of the Spring LDAP codebase. The dependencies for each package are clearly + noted. A package dependency noted as (optional) means + that the dependency is needed to compile the package but is optionally + needed at runtime (depending on your use of the package). For example, use + of Spring LDAP together with Acegi Security entails use of the + org.acegisecurity package. Cyclic package dependencies + are noted with (cycle). These are candidates for + removal in future releases. + + + org.springframework.ldap + + The ldap package contains the central + abstractions of the library. These abstractions include + AuthenticationSource, ContextSource, DirContextProcessor, and + NameClassPairCallbackHandler. This package also contains the central + class LdapTemplate, plus various mappers and executors. + + + + Dependencies: ldap.support (cycle), spring-beans, spring-dao, + commons-lang, commons-logging + + + + + + org.springframework.ldap.support + + The support package contains supporting + implementations of the central interfaces as well as the + DirContextAdapter abstraction. + + + + Dependencies: ldap, + ldap.util, spring-core, spring-beans, commons-lang, + commons-collections, commons-logging + + + + + + org.springframework.ldap.support.authentication + + The support.authentication package contains + an implementation of the AuthenticationSource interface that can be used + with Acegi + Security. + + + + Dependencies: ldap, acegi-security (optional), spring-beans, + commons-lang, commons-logging + + + + + + org.springframework.ldap.support.control + + The support.control package contains an + abstract implementation of the DirContextProcessor interface that can be + used as a basis for processing RequestControls and ResponseControls. + There is also a concrete implementation that handles paged search + results. The LDAP + Booster Pack is used to get support for controls. + + + + Dependencies: ldap, LDAP booster pack, spring-core, + commons-logging + + + + + + org.springframework.ldap.support.filter + + The support.filter package contains the + Filter abstraction and several implementations of it. + + + + Dependencies: ldap.support, commons-lang + + + + + + org.springframework.ldap.util + + The util package contains utility + classes that are used internally. + + + + Dependencies: none + + + + + For the exact list of jar dependencies, see the Spring LDAP Ivy dependency manager descriptor + located within the Spring LDAP distribution at + spring-ldap/ivy.xml + + + + Support + + Spring LDAP 1.2 is supported on Spring 1.2.8 or later. + + The community support forum is located at http://forum.springframework.org, + and the project web page is http://www.springframework.org/ldap. + + \ No newline at end of file diff --git a/spring-ldap/docs/reference/src/preface.xml b/spring-ldap/docs/reference/src/preface.xml new file mode 100644 index 00000000..b0a97605 --- /dev/null +++ b/spring-ldap/docs/reference/src/preface.xml @@ -0,0 +1,32 @@ + + + Preface + + The Java Naming and Directory Interface (JNDI) is for LDAP programming + what Java Database Connectivity (JDBC) is for SQL programming. There are + several similarities between JDBC and JNDI/LDAP (Java LDAP). Despite + being two completely different APIs with different pros and cons, they + share a number of less flattering characteristics: + + + + They require extensive plumbing code, even to perform the simplest of tasks. + + + All resources need to be correctly closed, no matter what happens. + + + Exception handling is difficult. + + + + The above points often lead to massive code duplication in common usages + of the APIs. As we all know, code duplication is one of the worst code smells. + All in all, it boils down to this: JDBC and LDAP programming in Java are both + incredibly dull and repetitive. + + + Spring JDBC, a part of the Spring framework, provides excellent utilities for + simplifying SQL programming. We need a similar framework for Java LDAP programming. + + diff --git a/spring-ldap/docs/reference/styles/fopdf.xsl b/spring-ldap/docs/reference/styles/fopdf.xsl new file mode 100644 index 00000000..d47be44b --- /dev/null +++ b/spring-ldap/docs/reference/styles/fopdf.xsl @@ -0,0 +1,475 @@ + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copyright ©right; 2005-2006 + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -5em + -5em + + + + + + + + + + + Spring LDAP () + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bold + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 0 + 1 + + 1 + + + + + + book toc + + + + 2 + + + + + + + + + + 0 + 0 + 0 + + + 5mm + 10mm + 10mm + + 15mm + 10mm + 0mm + + 18mm + 18mm + + + 0pc + + + + + justify + false + + + 11 + 8 + + + 1.4 + + + + + + + 0.8em + + + + + + 17.4cm + + + + 4pt + 4pt + 4pt + 4pt + + + + 0.1pt + 0.1pt + + + + + 1 + + + + + + + + left + bold + + + pt + + + + + + + + + + + + + + + 0.8em + 0.8em + 0.8em + + + pt + + 0.1em + 0.1em + 0.1em + + + 0.6em + 0.6em + 0.6em + + + pt + + 0.1em + 0.1em + 0.1em + + + 0.4em + 0.4em + 0.4em + + + pt + + 0.1em + 0.1em + 0.1em + + + + + bold + + + pt + + false + 0.4em + 0.6em + 0.8em + + + + + + + + + pt + + + + + 1em + 1em + 1em + #444444 + solid + 0.1pt + 0.5em + 0.5em + 0.5em + 0.5em + 0.5em + 0.5em + + + + 1 + + #F0F0F0 + + + + + + 0 + 1 + + + 90 + + + + + '1' + &admon_gfx_path; + + + + + + figure after + example before + equation before + table before + procedure before + + + + 1 + + + + 0.8em + 0.8em + 0.8em + 0.1em + 0.1em + 0.1em + + + + + + + + + + + + + + + + + diff --git a/spring-ldap/docs/reference/styles/html.css b/spring-ldap/docs/reference/styles/html.css new file mode 100644 index 00000000..c603be90 --- /dev/null +++ b/spring-ldap/docs/reference/styles/html.css @@ -0,0 +1,270 @@ +BODY { + text-align: justify; + margin-right: 2em; + margin-left: 2em; +} + +A[accesskey^="p"] { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + color: #003399; +} + +A[accesskey^="u"] { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + color: #003399; +} + +A[accesskey^="h"] { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + color: #003399; +} + +A[accesskey^="n"] { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + color: #003399; +} + +A { + color: #003399; + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; +} + +A:active { + color: #003399; +} + +A:visited { + color: #888888; +} + +P { + font-family: Verdana, Arial; +} + +DT { + font-family: Verdana, Arial; + font-size: 12px; +} + +P, DL, DT, DD, BLOCKQUOTE { + color: #000000; + margin-bottom: 3px; + margin-top: 3px; + padding-top: 0px; +} + +OL, UL, P { + margin-top: 6px; + margin-bottom: 6px; +} + +P, BLOCKQUOTE { + font-size: 90%; +} + +P.releaseinfo { + font-size: 100%; + font-weight: bold; + font-family: Verdana, Arial, helvetica, sans-serif; + padding-top: 10px; +} + +P.pubdate { + font-size: 120%; font-weight: bold; + font-family: Verdana, Arial, helvetica, sans-serif; +} + +td { + font-size: 80%; +} + +TD, TH, SPAN { + color: #000000; +} + +TD[width^="40%"] { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + color: #003399; +} + +TABLE[summary^="Navigation header"] tbody tr th[colspan^="3"] { + font-family: Verdana, Arial, helvetica, sans-serif; +} + +BLOCKQUOTE { + margin-right: 0px; +} + +H1, H2, H3, H4, H5, H6 { + color: #000000; + font-weight:500; + margin-top:0px; + padding-top:14px; + font-family: Verdana, Arial, helvetica, sans-serif; + margin-bottom: 0px; +} + +H2.title { + font-weight:800; + margin-bottom: 8px; +} + +H2.subtitle { + font-weight:800; + margin-bottom: 20px; +} + +.firstname, .surname { + font-size: 12px; + font-family: Verdana, Arial, helvetica, sans-serif; +} + +TABLE { + border-collapse: collapse; + border-spacing:0; + border: 1px thin black; + empty-cells: hide; + margin: 10px 0px 30px 50px; + width: 90%; +} + +div.table { + margin: 30px 0 30 0; + border: 1px dashed gray; + padding: 10px; +} + +div.table > p.title { + padding-left: 10px; +} + +table[summary^="Navigation footer"] { + border-collapse: collapse; + border-spacing:0; + border: 1px thin black; + empty-cells: hide; + margin: 0px; + width: 100%; +} + +table[summary^="Note"], table[summary^="Warning"], table[summary^="Tip"] { + border-collapse: collapse; + border-spacing:0; + border: 1px thin black; + empty-cells: hide; + margin: 10px 0 10 -20; + width: 100%; +} + +TD { + padding: 4pt; + font-family: Verdana, Arial, helvetica, sans-serif; +} + +div.warning TD { + text-align: justify; +} + +H1 { + font-size: 150%; +} +H2 { + font-size: 110%; +} +H3 { + font-size: 100%; font-weight: bold; +} +H4 { + font-size: 90%; font-weight: bold; +} +H5 { + font-size: 90%; font-style: italic; +} +H6 { + font-size: 100%; font-style: italic; +} + +TT { + font-size: 110%; + font-family: "Courier New", Courier, monospace; + color: #000000; +} + +.navheader, .navfooter { + background-color: #e4eff3; +} + +PRE { + font-size: 110%; + padding: 5px; + border-style: solid; + border-width: 1px; + border-color: #CCCCCC; + background-color: #F4F4F4; +} + +UL, OL, LI { + list-style: disc; +} + +HR { + width: 100%; + height: 1px; + background-color: #CCCCCC; + border-width: 0px; + padding: 0px; + color: #CCCCCC; +} + +.variablelist { + padding-top: 10; + padding-bottom:10; + margin:0; +} + +.term { + font-weight:bold; +} + +.mediaobject { + padding-top: 30px; + padding-bottom: 30px; +} + +.legalnotice { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + font-style: italic; +} + +.sidebar { + float: right; + margin: 10px 0px 10px 30px; + padding: 10px 20px 20px 20px; + width: 33%; + border: 1px solid black; + background-color: #F4F4F4; + font-size: 14px; +} + +.programlisting * .classname { + font-size: 95%; +} + +.programlisting * .interfacename { + font-size: 95%; +} + +.programlisting * .literal { + font-size: 95%; +} + +.property { + font-family: "Courier New", Courier, monospace; +} diff --git a/spring-ldap/docs/reference/styles/html.xsl b/spring-ldap/docs/reference/styles/html.xsl new file mode 100644 index 00000000..0b35acad --- /dev/null +++ b/spring-ldap/docs/reference/styles/html.xsl @@ -0,0 +1,100 @@ + + + + + +]> + + + + + + + + ../styles/html.css + + + 1 + 0 + 1 + 0 + + + + + + book toc + + + + 3 + + + + + 1 + + + + + + + 1 + &callout_gfx_path; + + + 90 + + + + + '1' + &admon_gfx_path; + + + + + figure after + example before + equation before + table before + procedure before + + + + , + + + + + + + + +
+

Authors

+

+ +

+
+ +
diff --git a/spring-ldap/docs/reference/styles/html_chunk.xsl b/spring-ldap/docs/reference/styles/html_chunk.xsl new file mode 100644 index 00000000..258b97ce --- /dev/null +++ b/spring-ldap/docs/reference/styles/html_chunk.xsl @@ -0,0 +1,103 @@ + + + + + +]> + + + + '5' + '1' + ../styles/html.css + + 1 + 0 + 1 + 0 + + + + book toc + + + 3 + + + 1 + + + + + 1 + &callout_gfx_path; + + 90 + + + '1' + &admon_gfx_path; + + + + figure after + example before + equation before + table before + procedure before + + + + , + + + + + + + + +
+

Authors

+

+ +

+
+ + + + +
+ + + + + 1 + + diff --git a/spring-ldap/docs/reference/styles/tld.to.docbook.xsl b/spring-ldap/docs/reference/styles/tld.to.docbook.xsl new file mode 100644 index 00000000..b0823a14 --- /dev/null +++ b/spring-ldap/docs/reference/styles/tld.to.docbook.xsl @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + -intro + + Introduction + + + + This appendix describes the + + + + tag library descriptor. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The + + + + tag + + + + + + + Attributes + + + + 4 + + + + center + + + + + center + + + + + center + + + + + center + + + + + + + center + + Attribute + + + + center + + Required? + + + + center + + Runtime Expression? + + + + center + + Description + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + diff --git a/spring-ldap/docs/reference/styles/xsd.to.docbook.xsl b/spring-ldap/docs/reference/styles/xsd.to.docbook.xsl new file mode 100644 index 00000000..4a9bb86d --- /dev/null +++ b/spring-ldap/docs/reference/styles/xsd.to.docbook.xsl @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + -intro + + + Introduction + + + + + This appendix describes the + + + + schema. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The + + + + element + + + [TODO : insert the description of the element here] + + + + + + + . + + + diff --git a/spring-ldap/itest-openldap-targets.xml b/spring-ldap/itest-openldap-targets.xml new file mode 100644 index 00000000..7edf57ab --- /dev/null +++ b/spring-ldap/itest-openldap-targets.xml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compiling itest-openldap sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Integration test report has been generated. +The HTML report is ${target.itest.openldap.results.html.dir}/index.html + + + + + diff --git a/spring-ldap/itest-targets.xml b/spring-ldap/itest-targets.xml new file mode 100644 index 00000000..d8775077 --- /dev/null +++ b/spring-ldap/itest-targets.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compiling itest sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Integration test report has been generated. +The HTML report is ${target.itestresults.html.dir}/index.html + + + + + diff --git a/spring-ldap/ivy.xml b/spring-ldap/ivy.xml new file mode 100644 index 00000000..774def0a --- /dev/null +++ b/spring-ldap/ivy.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap/license.txt b/spring-ldap/license.txt new file mode 100644 index 00000000..0c8a028d --- /dev/null +++ b/spring-ldap/license.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2006 Mattias Arthursson and Ulrik Sandberg + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/spring-ldap/notice.txt b/spring-ldap/notice.txt new file mode 100644 index 00000000..4e701033 --- /dev/null +++ b/spring-ldap/notice.txt @@ -0,0 +1,16 @@ + ====================================================================== + == NOTICE file corresponding to section 4 d of the Apache License, == + == Version 2.0, for the LdapTemplate distribution. == + ====================================================================== + + This product includes software developed by + the Apache Software Foundation (http://www.apache.org). + + The end-user documentation included with a redistribution, if any, + must include the following acknowledgement: + + "This product includes software developed by the LdapTemplate + Project (http://ldaptemplate.sourceforge.net)." + + Alternately, this acknowledgement may appear in the software itself, + if and wherever such third-party acknowledgements normally appear. diff --git a/spring-ldap/pom.xml b/spring-ldap/pom.xml new file mode 100644 index 00000000..334113e1 --- /dev/null +++ b/spring-ldap/pom.xml @@ -0,0 +1,176 @@ + + + + spring-ldap + org.springframework.ldap + 1.1.1-SNAPSHOT + + 4.0.0 + org.springframework + spring-ldap + Spring LDAP Core + 1.1.1-SNAPSHOT + + + + + org.codehaus.mojo + javacc-maven-plugin + 2.1 + + + + javacc + + + + + + + + + + + commons-logging + commons-logging + 1.0.4 + provided + + + commons-lang + commons-lang + 2.1 + provided + + + commons-collections + commons-collections + 3.1 + provided + + + com.sun + ldapbp + 1.0 + provided + + + org.acegisecurity + acegi-security + 1.0.1 + true + provided + + + + org.springframework + spring-beans + 2.0 + provided + + + org.springframework + spring-context + 2.0 + provided + + + org.springframework + spring-core + 2.0 + provided + + + org.springframework + spring-dao + 2.0 + provided + + + + junit + junit + 3.8.1 + test + + + easymock + easymock + 1.2_Java1.3 + test + + + gsbase + gsbase + 2.0.1 + test + + + + org.apache.directory.server + apacheds-core + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-core-shared + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-server-jndi + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-server-main + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-protocol-shared + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-protocol-changepw + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-protocol-kerberos + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-kerberos-shared + 1.0-RC3 + test + + + org.apache.directory.server + apacheds-protocol-ldap + 1.0-RC3 + test + + + org.apache.directory.shared + shared-asn1 + 0.9.5.1 + test + + + org.apache.directory.shared + shared-ldap + 0.9.5.1 + test + + + diff --git a/spring-ldap/project.properties b/spring-ldap/project.properties new file mode 100644 index 00000000..ea1803a9 --- /dev/null +++ b/spring-ldap/project.properties @@ -0,0 +1,17 @@ +# properties defined in this file are overridable by a local build.properties in this project dir + +# The location of the common build system +common.build.dir=${basedir}/../common-build + +src.javacc.dir=${basedir}/src/main/javacc +javacc.home.dir=c:/java/javacc-4.0 + +project.base.version=1.2-dev +#project.version=${project.base.version} +#ivy.status=release + +javac.source=1.3 +javac.target=1.3 + +# extend common-build with source capability +main.build.configs=global,buildtime,test,source diff --git a/spring-ldap/project.xml b/spring-ldap/project.xml new file mode 100644 index 00000000..683ca71c --- /dev/null +++ b/spring-ldap/project.xml @@ -0,0 +1,240 @@ + + + 3 + + spring-ldap + Spring LDAP + org.springframework + spring-ldap + 1.1 + http://opensource.atlassian.com/projects/spring/browse/LDAP + 2006 + org.springframework.ldap + + <p> + Spring LDAP is a library to simplify LDAP programming in + Java, built on the same principles as Spring JDBC. + </p> + <p> + The LdapTemplate class encapsulates all the plumbing work + involved in traditional LDAP programming, such as creating + contexts, looping through NamingEnumerations, handling + Exceptions and cleaning up resources. This leaves the programmer + to handle the important stuff - where to find data (DNs and + Filters) and what to do with it (map to and from domain objects, + bind, modify, unbind, etc.), in the same way that JdbcTemplate + relieves the programmer from everything but the actual SQL and + how the data maps to the domain model. + </p> + <p> + In addition to this, LdapTemplate provides Exception translation + from NamingExceptions to DataAccessExceptions, as well as + several utilities for working with filters, LDAP paths and + Attributes. + </p> + + + Java framework for easier LDAP programming + + http://www.springframework.org/ldap + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + scm:svn:https://svn.sourceforge.net/svnroot/springframework/spring-projects/trunk/spring-ldap + + http://svn.sourceforge.net/viewvc/springframework/spring-projects/ + + + + Mattias Arthursson + marthursson + mattias-DOT-arthursson-AT-jayway-dot-se + Jayway AB + http://www.jayway.se + 1 + + Project Lead + SourceForge Admin + Committer + + + + Ulrik Sandberg + ulsa + ulrik_DOT_sandberg-AT-jayway_DOT_se + Jayway AB + http://www.jayway.se + 1 + + Project Lead + SourceForge Admin + Committer + + + + + + Gregor Middell + + + + Jayway AB + http://www.jayway.se + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + manual + + + + + junit + junit + 3.8.1 + jar + + + commons-logging + commons-logging + 1.0.4 + jar + + + commons-lang + commons-lang + 2.1 + jar + + + commons-collections + commons-collections + 3.1 + jar + + + easymock + easymock + 1.1 + jar + + + easymock + easymockclassextension + 1.1 + jar + + + springframework + spring-core + 1.2.6 + jar + + + springframework + spring-context + 1.2.6 + jar + + + springframework + spring-beans + 1.2.6 + jar + + + springframework + spring-dao + 1.2.6 + jar + + + cglib + cglib-full + 2.0.1 + jar + + + gsbase + gsbase + 2.0 + jar + + + acegisecurity + acegi-security + 1.0.0-RC2 + jar + + + + mattias.arthursson@jayway.se + src/java + src/test + + + **/*Test.java + + + + src/test + + **/*.dtd + **/*.xls + **/*.xml + **/*.properties + + false + + + + + + src/java + + **/*.dtd + **/*.xml + **/*.properties + **/*.xls + + false + + + src/test + + **/*.dtd + **/*.xml + **/*.properties + **/*.xls + + false + + + + + + maven-changes-plugin + + + maven-faq-plugin + + maven-javadoc-plugin + maven-jdepend-plugin + maven-jcoverage-plugin + maven-junit-report-plugin + maven-jxr-plugin + maven-license-plugin + + + + + + + \ No newline at end of file diff --git a/spring-ldap/readme.txt b/spring-ldap/readme.txt new file mode 100644 index 00000000..94092187 --- /dev/null +++ b/spring-ldap/readme.txt @@ -0,0 +1,82 @@ +Spring-LDAP 1.1.2 (Dec 2006) +----------------------------- +http://www.springframework.org/ldap + +1. INTRODUCTION + +Spring-LDAP is a library to simplify LDAP programming in Java, built on the same +principles as Spring Jdbc. + +The LdapTemplate class encapsulates all the plumbing work involved in traditional LDAP +programming, such as creating, looping through NamingEnumerations, handling Exceptions +and cleaning up resources. This leaves the programmer to handle the important stuff - +where to find data (DNs and Filters) and what do do with it (map to and from domain +objects, bind, modify, unbind, etc.), in the same way that JdbcTemplate relieves the +programmer of all but the actual SQL and how the data maps to the domain model. + +In addition to this, Spring-LDAP provides Exception translation from NamingExceptions +to DataAccessExceptions, as well as several utilities for working with filters, LDAP +paths and Attributes. + +The DirContextProcessor interface provides the programmer with the possibility to +get callbacks before and after a search, which enables things like processing of +the LDAPv3 feature of RequestControls and ResponseControls. An abstract base class +that simplifies this is provided, as is a full implementation of PagedSearchResult. + +2. RELEASE INFO + +Spring-LDAP requires J2SE 1.4. J2SE 1.4, and javacc version 4.0 is required for building. +J2EE 1.4 (Servlet 2.3, JSP 1.2) is required for running the example. + +The Spring-LDAP release comes in three different distributables: +* spring-ldap-bin-x.x.zip + ** readme.txt - this readme file. + ** license.txt - terms and conditions for use, reproduction and distribution + ** dist/spring-ldap-x.x.jar - the library + ** dist/spring-ldap-src-x.x.zip - the source code of the library + ** dist/ivys - ivy configuration + ** doc/api - api javadoc documentation + ** doc/reference - full project reference documentation + +* spring-ldap-bin-with-dependencies-x.x.zip + ** readme.txt - this readme file. + ** license.txt - terms and conditions for use, reproduction and distribution + ** dist/spring-ldap-x.x.jar - the library + ** dist/spring-ldap-src-x.x.zip - the source code of the library + ** dist/ivys - ivy configuration + ** lib - all referenced libraries necessary to use spring-LDAP + ** doc/api - api javadoc documentation + ** doc/reference - full project reference documentation + +* spring-ldap-buildable-x.x.zip + ** readme.txt - this readme file. + ** license.txt - terms and conditions for use, reproduction and distribution + ** common-build - the ant 1.6 "common build system" used by all spring-ldap projects to compile/build/test + ** repository - build artifacts that are not available from public repositories + ** spring-ldap/build-spring-ldap - master build files to produce this release archive + ** spring-ldap/spring-ldap - project sources + ** spring-ldap/spring-ldap-person - a sample web project. + ** spring-ldap/spring-ldap-article - source code for an article published on java.net. + + +Spring-LDAP is released under the terms of the Apache Software License (see license.txt). + +3. DISTRIBUTION JAR FILES + +The following distinct jar files are included in the distribution. This list +specifies the respective contents and third-party dependencies. + +* spring-ldap-x.x.jar +- Contents: The Spring-LDAP library +- Dependencies: Commons Logging, Commons Lang, Commons Collections, spring-beans, + spring-core, spring-context, spring-dao + +4. WHERE TO START + +The distribution contains extensive JavaDoc documentation as well as full reference +documentation and a sample application illustrating different ways to use Spring-LDAP. +The Spring-LDAP homepage can be found at the following URL: + +http://www.springframework.org/ldap + +There you will find resources related to the project. diff --git a/spring-ldap/src/itest-openldap/java/conf/ldap-openldap.properties b/spring-ldap/src/itest-openldap/java/conf/ldap-openldap.properties new file mode 100644 index 00000000..57aa1478 --- /dev/null +++ b/spring-ldap/src/itest-openldap/java/conf/ldap-openldap.properties @@ -0,0 +1,4 @@ +urls=ldap://127.0.0.1 +userName=cn=manager,dc=jayway,dc=se +password=secret +base=dc=jayway,dc=se diff --git a/spring-ldap/src/itest-openldap/java/conf/ldap.conf b/spring-ldap/src/itest-openldap/java/conf/ldap.conf new file mode 100644 index 00000000..aa4372ea --- /dev/null +++ b/spring-ldap/src/itest-openldap/java/conf/ldap.conf @@ -0,0 +1,23 @@ +# Start slapd with this file as configuration file: -f ldap.conf +# The first time, fill the database using the load script in +# src/itest/java/setup_data.ldif, like this: +# +# cd \program\openldap +# ldap_add -f ...\src\itest\java\setup_data.ldif -d cn=Manager,dc=jayway,dc=se -W +# +# The password can be seen below + +include "c:/Program/OpenLDAP/schema/core.schema" +include "c:/Program/OpenLDAP/schema/cosine.schema" +include "c:/Program/OpenLDAP/schema/inetorgperson.schema" +database bdb +suffix "dc=jayway,dc=se" +rootdn "cn=Manager,dc=jayway,dc=se" +rootpw secret +directory "c:/Program/OpenLDAP/data" + +TLSCipherSuite HIGH:MEDIUM:+SSLv2 +TLSCACertificateFile /tmp/cacert.pem +TLSCertificateFile /tmp/servercrt.pem +TLSCertificateKeyFile /tmp/serverkey.pem +TLSVerifyClient never diff --git a/spring-ldap/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml b/spring-ldap/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml new file mode 100644 index 00000000..e905b1c3 --- /dev/null +++ b/spring-ldap/src/itest-openldap/java/conf/ldapTemplateTestContext-openldap.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplateLookupOpenLdapITest.java b/spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplateLookupOpenLdapITest.java new file mode 100644 index 00000000..08e2f968 --- /dev/null +++ b/spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplateLookupOpenLdapITest.java @@ -0,0 +1,217 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the lookup methods of LdapTemplate on OpenLdap. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplateLookupOpenLdapITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext-openldap.xml" }; + } + + /** + * This method depends on a DirObjectFactory ({@link org.springframework.ldap.support.DefaultDirObjectFactory}) + * being set in the ContextSource. + */ + public void testLookup_Plain() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person2, ou=company1,c=Sweden"); + + assertEquals("Some Person2", result.getStringAttribute("cn")); + assertEquals("Person2", result.getStringAttribute("sn")); + assertEquals("Sweden, Company1, Some Person2", result + .getStringAttribute("description")); + } + + public void testLookup_AttributesMapper() { + AttributesMapper mapper = new PersonAttributesMapper(); + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", mapper); + + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + public void testLookup_AttributesMapper_DistinguishedName() { + AttributesMapper mapper = new PersonAttributesMapper(); + Person person = (Person) tested.lookup(new DistinguishedName( + "cn=Some Person2, ou=company1,c=Sweden"), mapper); + + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + /** + * An {@link AttributesMapper} that only maps a subset of the full + * attributes list. Used in tests where the return attributes list has been + * limited. + * + * @author Ulrik Sandberg + */ + private final class SubsetPersonAttributesMapper implements + AttributesMapper { + /** + * Maps the cn attribute into a {@link Person} object. + * Also verifies that the other attributes haven't been set. + * + * @see org.springframework.ldap.AttributesMapper#mapFromAttributes(javax.naming.directory.Attributes) + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException { + Person person = new Person(); + person.setFullname((String) attributes.get("cn").get()); + assertNull("sn should be null", attributes.get("sn")); + assertNull("description should be null", attributes + .get("description")); + return person; + } + } + + /** + * Verifies that only the subset is used when specifying a subset of the + * available attributes as return attributes. + */ + public void testLookup_ReturnAttributes_AttributesMapper() { + AttributesMapper mapper = new SubsetPersonAttributesMapper(); + + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", new String[] { "cn" }, + mapper); + + assertEquals("Some Person2", person.getFullname()); + assertNull("lastName should not be set", person.getLastname()); + assertNull("description should not be set", person.getDescription()); + } + + /** + * Verifies that only the subset is used when specifying a subset of the + * available attributes as return attributes. Uses DistinguishedName instead + * of plain string as name. + */ + public void testLookup_ReturnAttributes_AttributesMapper_DistinguishedName() { + AttributesMapper mapper = new SubsetPersonAttributesMapper(); + Person person = (Person) tested.lookup(new DistinguishedName( + "cn=Some Person2, ou=company1,c=Sweden"), + new String[] { "cn" }, mapper); + + assertEquals("Some Person2", person.getFullname()); + assertNull("lastName should not be set", person.getLastname()); + assertNull("description should not be set", person.getDescription()); + } + + /** + * This method depends on a DirObjectFactory ({@link org.springframework.ldap.support.DefaultDirObjectFactory}) + * being set in the ContextSource. + */ + public void testLookup_ContextMapper() { + ContextMapper mapper = new PersonContextMapper(); + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", mapper); + + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + /** + * Verifies that only the subset is used when specifying a subset of the + * available attributes as return attributes. + */ + public void testLookup_ReturnAttributes_ContextMapper() { + ContextMapper mapper = new PersonContextMapper(); + + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", new String[] { "cn" }, + mapper); + + assertEquals("Some Person2", person.getFullname()); + assertNull("lastName should not be set", person.getLastname()); + assertNull("description should not be set", person.getDescription()); + } + + /** + * Verifies that we can lookup an entry that has a multi-valued rdn, which + * means more than one attribute is part of the relative DN for the entry. + */ + public void testLookup_MultiValuedRdn() { + AttributesMapper mapper = new PersonAttributesMapper(); + Person person = (Person) tested.lookup( + "cn=Some Person+sn=Person, ou=company1,c=Norway", mapper); + + assertEquals("Some Person", person.getFullname()); + assertEquals("Person", person.getLastname()); + assertEquals("Norway, Company1, Some Person+Person", person + .getDescription()); + } + + /** + * Verifies that we can lookup an entry that has a multi-valued rdn, which + * means more than one attribute is part of the relative DN for the entry. + */ + public void testLookup_MultiValuedRdn_DirContextAdapter() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person+sn=Person, ou=company1,c=Norway"); + + assertEquals("Some Person", result.getStringAttribute("cn")); + assertEquals("Person", result.getStringAttribute("sn")); + assertEquals("Norway, Company1, Some Person+Person", result + .getStringAttribute("description")); + } + + public void testLookup_GetNameInNamespace_Plain() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person2, ou=company1,c=Sweden"); + + assertEquals("cn=Some Person2, ou=company1, c=Sweden", result.getDn() + .toString()); + assertEquals( + "cn=Some Person2, ou=company1, c=Sweden, dc=jayway, dc=se", + result.getNameInNamespace()); + } + + public void testLookup_GetNameInNamespace_MultiRdn() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person+sn=Person, ou=company1,c=Norway"); + + assertEquals("cn=Some Person+sn=Person, ou=company1, c=Norway", result + .getDn().toString()); + assertEquals( + "cn=Some Person+sn=Person, ou=company1, c=Norway, dc=jayway, dc=se", + result.getNameInNamespace()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplatePagedSearchITest.java b/spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplatePagedSearchITest.java new file mode 100644 index 00000000..9891ac45 --- /dev/null +++ b/spring-ldap/src/itest-openldap/java/org/springframework/ldap/LdapTemplatePagedSearchITest.java @@ -0,0 +1,153 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Name; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.SearchControls; + +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.ldap.support.control.PagedResultsCookie; +import org.springframework.ldap.support.control.PagedResultsRequestControl; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the paged search result capability of LdapTemplate. + *

+ * Note: Currently, ApacheDS does not support paged results controls, so this + * test must be run under another directory server, for example OpenLdap. This + * test will not run under ApacheDS, and the other integration tests assume + * ApacheDS and will probably not run under OpenLdap. + * + * @author Ulrik Sandberg + */ +public class LdapTemplatePagedSearchITest extends + AbstractDependencyInjectionSpringContextTests { + + private static final Name BASE = DistinguishedName.EMPTY_PATH; + + private static final String FILTER_STRING = "(&(objectclass=person))"; + + private LdapTemplate tested; + + private CollectingNameClassPairCallbackHandler callbackHandler; + + private SearchControls searchControls; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext-openldap.xml" }; + } + + protected void onSetUp() throws Exception { + super.onSetUp(); + PersonAttributesMapper mapper = new PersonAttributesMapper(); + callbackHandler = tested.new AttributesMapperCallbackHandler(mapper); + searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + } + + protected void onTearDown() throws Exception { + super.onTearDown(); + callbackHandler = null; + tested = null; + searchControls = null; + } + + public void testSearch_PagedResult() { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(BASE, FILTER_STRING, searchControls); + } + }; + Person person; + List list; + PagedResultsCookie cookie; + PagedResultsRequestControl requestControl; + + // Prepare for first search + requestControl = new PagedResultsRequestControl(3); + tested.search(searchExecutor, callbackHandler, requestControl); + cookie = requestControl.getCookie(); + assertNotNull("Cookie should not be null yet", cookie.getCookie()); + list = callbackHandler.getList(); + assertEquals(3, list.size()); + person = (Person) list.get(0); + assertEquals("Some Person", person.getFullname()); + assertEquals("+46 555-123456", person.getPhone()); + person = (Person) list.get(1); + assertEquals("Some Person2", person.getFullname()); + assertEquals("+46 555-654321", person.getPhone()); + person = (Person) list.get(2); + assertEquals("Some Person3", person.getFullname()); + assertEquals("+46 555-123654", person.getPhone()); + + // Prepare for second and last search + requestControl = new PagedResultsRequestControl(3, cookie); + tested.search(searchExecutor, callbackHandler, requestControl); + cookie = requestControl.getCookie(); + assertNull("Cookie should be null now", cookie.getCookie()); + assertEquals(5, list.size()); + person = (Person) list.get(3); + assertEquals("Some Person", person.getFullname()); + assertEquals("+46 555-456321", person.getPhone()); + person = (Person) list.get(4); + assertEquals("Some Person", person.getFullname()); + assertEquals("+45 555-654123", person.getPhone()); + } + + public void testSearch_PagedResult_ConvenienceMethod() { + Person person; + List list; + PagedResultsCookie cookie; + PagedResultsRequestControl requestControl; + + // Prepare for first search + requestControl = new PagedResultsRequestControl(3); + tested.search(BASE, FILTER_STRING, searchControls, + callbackHandler, requestControl); + cookie = requestControl.getCookie(); + assertNotNull("Cookie should not be null yet", cookie.getCookie()); + list = callbackHandler.getList(); + assertEquals(3, list.size()); + person = (Person) list.get(0); + assertEquals("Some Person", person.getFullname()); + person = (Person) list.get(1); + assertEquals("Some Person2", person.getFullname()); + person = (Person) list.get(2); + assertEquals("Some Person3", person.getFullname()); + + // Prepare for second and last search + requestControl = new PagedResultsRequestControl(3, cookie); + tested.search(BASE, FILTER_STRING, searchControls, + callbackHandler, requestControl); + cookie = requestControl.getCookie(); + assertNull("Cookie should be null now", cookie.getCookie()); + assertEquals(5, list.size()); + person = (Person) list.get(3); + assertEquals("Some Person", person.getFullname()); + person = (Person) list.get(4); + assertEquals("Some Person", person.getFullname()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/conf/apacheDsContext.xml b/spring-ldap/src/itest/java/conf/apacheDsContext.xml new file mode 100644 index 00000000..f5230c1e --- /dev/null +++ b/spring-ldap/src/itest/java/conf/apacheDsContext.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + simple + + + ${userName} + + + ${password} + + + + + + + + + + + + + + + + + + + + + objectClass: top + objectClass: domain + objectClass: extensibleObject + dc: jayway + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap/src/itest/java/conf/ldap.properties b/spring-ldap/src/itest/java/conf/ldap.properties new file mode 100644 index 00000000..74163056 --- /dev/null +++ b/spring-ldap/src/itest/java/conf/ldap.properties @@ -0,0 +1,4 @@ +urls=ldap://127.0.0.1:390 +userName=uid=admin,ou=system +password=secret +base=dc=jayway,dc=se diff --git a/spring-ldap/src/itest/java/conf/ldapContextSourceTestContext.xml b/spring-ldap/src/itest/java/conf/ldapContextSourceTestContext.xml new file mode 100644 index 00000000..1d898922 --- /dev/null +++ b/spring-ldap/src/itest/java/conf/ldapContextSourceTestContext.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/spring-ldap/src/itest/java/conf/ldapTemplateAcegiTestContext.xml b/spring-ldap/src/itest/java/conf/ldapTemplateAcegiTestContext.xml new file mode 100644 index 00000000..cf2af0de --- /dev/null +++ b/spring-ldap/src/itest/java/conf/ldapTemplateAcegiTestContext.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap/src/itest/java/conf/ldapTemplateNoBaseSuffixTestContext.xml b/spring-ldap/src/itest/java/conf/ldapTemplateNoBaseSuffixTestContext.xml new file mode 100644 index 00000000..1b033d2f --- /dev/null +++ b/spring-ldap/src/itest/java/conf/ldapTemplateNoBaseSuffixTestContext.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap/src/itest/java/conf/ldapTemplateTestContext.xml b/spring-ldap/src/itest/java/conf/ldapTemplateTestContext.xml new file mode 100644 index 00000000..92408451 --- /dev/null +++ b/spring-ldap/src/itest/java/conf/ldapTemplateTestContext.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-ldap/src/itest/java/log4j.properties b/spring-ldap/src/itest/java/log4j.properties new file mode 100644 index 00000000..f57302e8 --- /dev/null +++ b/spring-ldap/src/itest/java/log4j.properties @@ -0,0 +1,9 @@ +log4j.rootCategory=WARN, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +#Enable debug logging +log4j.category.net.sf.ldaptemplate=INFO +log4j.category.net.sf.ldaptemplate.LdapTemplate=DEBUG diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckAttributesMapper.java b/spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckAttributesMapper.java new file mode 100644 index 00000000..bd30624b --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckAttributesMapper.java @@ -0,0 +1,66 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; + +import junit.framework.Assert; + +/** + * Dummy AttributesMapper for testing purposes to check that the received + * Attributes are the expected ones. + * + * @author Mattias Arthursson + */ +class AttributeCheckAttributesMapper implements AttributesMapper { + private String[] expectedAttributes = new String[0]; + + private String[] expectedValues = new String[0];; + + private String[] absentAttributes = new String[0];; + + public Object mapFromAttributes(Attributes attributes) + throws NamingException { + Assert.assertEquals("Values and attributes need to have the same length ", + expectedAttributes.length, expectedValues.length); + for (int i = 0; i < expectedAttributes.length; i++) { + Attribute attribute = attributes.get(expectedAttributes[i]); + Assert.assertNotNull("Attribute " + expectedAttributes[i] + + " was not present", attribute); + Assert.assertEquals(expectedValues[i], attribute.get()); + } + + for (int i = 0; i < absentAttributes.length; i++) { + Assert.assertNull(attributes.get(absentAttributes[i])); + } + + return null; + } + + public void setAbsentAttributes(String[] absentAttributes) { + this.absentAttributes = absentAttributes; + } + + public void setExpectedAttributes(String[] expectedAttributes) { + this.expectedAttributes = expectedAttributes; + } + + public void setExpectedValues(String[] expectedValues) { + this.expectedValues = expectedValues; + } +} \ No newline at end of file diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckContextMapper.java b/spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckContextMapper.java new file mode 100644 index 00000000..179606d0 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/AttributeCheckContextMapper.java @@ -0,0 +1,65 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import junit.framework.Assert; + +import org.springframework.ldap.support.DirContextAdapter; + +/** + * Dummy ContextMapper for testing purposes to check that the received + * Attributes are the expected ones. + * + * @author Mattias Arthursson + */ +class AttributeCheckContextMapper implements ContextMapper { + private String[] expectedAttributes = new String[0]; + + private String[] expectedValues = new String[0]; + + private String[] absentAttributes = new String[0]; + + public Object mapFromContext(Object ctx) { + DirContextAdapter adapter = (DirContextAdapter) ctx; + Assert.assertEquals("Values and attributes need to have the same length ", + expectedAttributes.length, expectedValues.length); + for (int i = 0; i < expectedAttributes.length; i++) { + String attributeValue = adapter + .getStringAttribute(expectedAttributes[i]); + Assert.assertNotNull("Attribute " + expectedAttributes[i] + + " was not present", attributeValue); + Assert.assertEquals(expectedValues[i], attributeValue); + } + + for (int i = 0; i < absentAttributes.length; i++) { + Assert.assertNull(adapter.getStringAttribute(absentAttributes[i])); + } + + return null; + } + + public void setAbsentAttributes(String[] absentAttributes) { + this.absentAttributes = absentAttributes; + } + + public void setExpectedAttributes(String[] expectedAttributes) { + this.expectedAttributes = expectedAttributes; + } + + public void setExpectedValues(String[] expectedValues) { + this.expectedValues = expectedValues; + } +} \ No newline at end of file diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java b/spring-ldap/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java new file mode 100644 index 00000000..20710fae --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/ConfigEnvHelper.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.io.File; +import java.util.Hashtable; + +import javax.naming.Context; + +import org.apache.directory.server.configuration.MutableServerStartupConfiguration; +import org.apache.directory.server.jndi.ServerContextFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * Helper class to simplify Spring configuration of ApacheDS. + * + * @author Mattias Arthursson + */ +public class ConfigEnvHelper implements InitializingBean { + private final MutableServerStartupConfiguration configuration; + + private final Hashtable initialEnv; + + private final File workingDir = new File(System + .getProperty("java.io.tmpdir") + + File.separator + "ldaptemplate_apacheds"); + + public ConfigEnvHelper(Hashtable initialEnv, + MutableServerStartupConfiguration configuration) { + + this.initialEnv = initialEnv; + this.configuration = configuration; + } + + public Hashtable getEnv() { + return initialEnv; + } + + public void afterPropertiesSet() throws Exception { + initialEnv.put(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName()); + configuration.setWorkingDirectory(workingDir); + initialEnv.putAll(configuration.toJndiEnvironment()); + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapServerManager.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapServerManager.java new file mode 100644 index 00000000..70101b1a --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapServerManager.java @@ -0,0 +1,123 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.Properties; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.ContextNotEmptyException; +import javax.naming.InitialContext; +import javax.naming.Name; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + + +import org.apache.directory.server.core.configuration.ShutdownConfiguration; +import org.apache.directory.server.jndi.ServerContextFactory; +import org.apache.directory.server.protocol.shared.store.LdifFileLoader; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.support.DefaultDirObjectFactory; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Utility class to initialize the apache directory server for use in the + * integration tests. + * + * @author Mattias Arthursson + * + */ +public class LdapServerManager implements InitializingBean, DisposableBean { + + private ContextSource contextSource; + + public void setContextSource(ContextSource contextSource) { + this.contextSource = contextSource; + } + + public void destroy() throws Exception { + Properties env = new Properties(); + env.setProperty(Context.INITIAL_CONTEXT_FACTORY, + ServerContextFactory.class.getName()); + env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); + env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); + env.setProperty(Context.SECURITY_CREDENTIALS, "secret"); + + ShutdownConfiguration configuration = new ShutdownConfiguration(); + env.putAll(configuration.toJndiEnvironment()); + + new InitialContext(env); + } + + public void afterPropertiesSet() throws Exception { + DirContext ctx = contextSource.getReadWriteContext(); + + // First of all, make sure the database is empty. + Name startingPoint = null; + + // Different test cases have different base paths. This means that the + // starting point will be different. + if (ctx.getEnvironment().get( + DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY) != null) { + startingPoint = DistinguishedName.EMPTY_PATH; + } else { + startingPoint = new DistinguishedName("dc=jayway,dc=se"); + } + + try { + clearSubContexts(ctx, startingPoint); + // Load the ldif to the recently started server + LdifFileLoader loader = new LdifFileLoader(ctx, "setup_data.ldif"); + loader.execute(); + } finally { + ctx.close(); + } + } + + private void clearSubContexts(DirContext ctx, Name name) + throws NamingException { + + NamingEnumeration enumeration = null; + try { + enumeration = ctx.listBindings(name); + while (enumeration.hasMore()) { + Binding element = (Binding) enumeration.next(); + DistinguishedName childName = new DistinguishedName(element + .getName()); + childName.prepend((DistinguishedName) name); + + try { + ctx.destroySubcontext(childName); + } catch (ContextNotEmptyException e) { + clearSubContexts(ctx, childName); + ctx.destroySubcontext(childName); + } + } + } catch (NamingException e) { + e.printStackTrace(); + } finally { + try { + enumeration.close(); + } catch (Exception e) { + // Never mind this + } + } + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateAttributesMapperITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateAttributesMapperITest.java new file mode 100644 index 00000000..53c7e2fd --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateAttributesMapperITest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + + +import org.springframework.ldap.AttributesMapper; +import org.springframework.ldap.LdapTemplate; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the attributes mapper search method. + * + * @author Mattias Arthursson + */ +public class LdapTemplateAttributesMapperITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + public void testSearch_AttributeMapper() throws Exception { + AttributesMapper mapper = new PersonAttributesMapper(); + List result = tested.search("ou=company1,c=Sweden", + "(&(objectclass=person)(sn=Person2))", mapper); + + assertEquals(1, result.size()); + Person person = (Person) result.get(0); + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java new file mode 100644 index 00000000..2762f764 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateBindUnbindITest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; + + +import org.springframework.ldap.EntryNotFoundException; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the bind and unbind methods of LdapTemplate. The test methods in this + * class tests a little too much, but we need to clean up after binding, so the + * most efficient way to test is to do it all in one test method. Also, the + * methods in this class relies on that the lookup method works as it should - + * that should be ok, since that is verified in a separate test class. NOTE: if + * any of the tests in this class fails, it may be necessary to run the cleanup + * script as described in README.txt under /src/iutest/. + * + * @author Mattias Arthursson + */ +public class LdapTemplateBindUnbindITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + private static String DN = "cn=Some Person4,ou=company1,c=Sweden"; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + public void testBindAndUnbind_Attributes_Plain() { + Attributes attributes = setupAttributes(); + tested.bind(DN, null, attributes); + verifyBoundCorrectData(); + tested.unbind(DN); + verifyCleanup(); + } + + public void testBindAndUnbind_Attributes_DIstinguishedName() { + Attributes attributes = setupAttributes(); + tested.bind(new DistinguishedName(DN), null, attributes); + verifyBoundCorrectData(); + tested.unbind(new DistinguishedName(DN)); + verifyCleanup(); + } + + public void testBindAndUnbind_DirContextAdapter_Plain() { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person4"); + adapter.setAttributeValue("sn", "Person4"); + + tested.bind(DN, adapter, null); + verifyBoundCorrectData(); + tested.unbind(DN); + verifyCleanup(); + } + + public void testBindAndUnbind_DirContextAdapter_DIstinguishedName() { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person4"); + adapter.setAttributeValue("sn", "Person4"); + + tested.bind(new DistinguishedName(DN), adapter, null); + verifyBoundCorrectData(); + tested.unbind(new DistinguishedName(DN)); + verifyCleanup(); + } + + private Attributes setupAttributes() { + Attributes attributes = new BasicAttributes(); + BasicAttribute ocattr = new BasicAttribute("objectclass"); + ocattr.add("top"); + ocattr.add("person"); + attributes.put(ocattr); + attributes.put("cn", "Some Person4"); + attributes.put("sn", "Person4"); + return attributes; + } + + private void verifyBoundCorrectData() { + DirContextAdapter result = (DirContextAdapter) tested.lookup(DN); + assertEquals("Some Person4", result.getStringAttribute("cn")); + assertEquals("Person4", result.getStringAttribute("sn")); + } + + private void verifyCleanup() { + try { + tested.lookup(DN); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextExecutorTest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextExecutorTest.java new file mode 100644 index 00000000..3e5e6548 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextExecutorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests for LdapTemplate's context executor methods. + * + * @author Mattias Arthursson + */ +public class LdapTemplateContextExecutorTest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + protected void onSetUp() throws Exception { + super.onSetUp(); + } + + protected void onTearDown() throws Exception { + super.onTearDown(); + } + + public void testLookupLink() { + ContextExecutor executor = new ContextExecutor(){ + public Object executeWithContext(DirContext ctx) throws NamingException { + return ctx.lookupLink("cn=Some Person,ou=company1,c=Sweden"); + } + }; + + Object object = tested.executeReadOnly(executor); + assertTrue("Should be a DirContextAdapter", object instanceof DirContextAdapter); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextMapperITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextMapperITest.java new file mode 100644 index 00000000..55eda910 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateContextMapperITest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + + +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.LdapTemplate; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the ContextMapper search method. In its way this method also + * demonstrates the use of DirContextAdapter and the DirObjectFactory. + * + * @author Mattias Arthursson + */ +public class LdapTemplateContextMapperITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + /** + * This method depends on a DirObjectFactory ({@link org.springframework.ldap.support.DefaultDirObjectFactory}) + * being set in the ContextSource. + */ + public void testSearch_ContextMapper() { + ContextMapper mapper = new PersonContextMapper(); + List result = tested.search("ou=company1,c=Sweden", + "(&(objectclass=person)(sn=Person2))", mapper); + + assertEquals(1, result.size()); + Person person = (Person) result.get(0); + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateListITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateListITest.java new file mode 100644 index 00000000..d3a67c9b --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateListITest.java @@ -0,0 +1,150 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import org.springframework.ldap.support.CountNameClassPairCallbackHandler; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests for LdapTemplate's list methods. + * + * @author Ulrik Sandberg + */ +public class LdapTemplateListITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapTemplate tested; + + private AttributeCheckContextMapper contextMapper; + + private static final String BASE_STRING = ""; + + private static final DistinguishedName BASE_NAME = new DistinguishedName( + BASE_STRING); + + private static final String[] ALL_ATTRIBUTES = { "cn", "sn", "description", + "telephoneNumber" }; + + private static final String[] ALL_VALUES = { "Some Person", "Person", + "Sweden, Company2, Some Person", "+46 555-456321" }; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + protected void onSetUp() throws Exception { + super.onSetUp(); + + contextMapper = new AttributeCheckContextMapper(); + } + + protected void onTearDown() throws Exception { + super.onTearDown(); + + contextMapper = null; + } + + public void testListBindings_ContextMapper() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + List list = tested.listBindings("ou=company2,c=Sweden" + BASE_STRING, + contextMapper); + assertEquals(1, list.size()); + } + + public void testListBindings_ContextMapper_Name() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + DistinguishedName dn = new DistinguishedName("ou=company2,c=Sweden"); + dn.append(BASE_NAME); + List list = tested.listBindings(dn, contextMapper); + assertEquals(1, list.size()); + } + + public void testListBindings_ContextMapper_MapToPersons() { + DistinguishedName dn = new DistinguishedName("ou=company1,c=Sweden"); + dn.append(BASE_NAME); + List list = tested.listBindings(dn, new PersonContextMapper()); + assertEquals(3, list.size()); + String personClass = "org.springframework.ldap.Person"; + assertEquals(personClass, list.get(0).getClass().getName()); + assertEquals(personClass, list.get(1).getClass().getName()); + assertEquals(personClass, list.get(2).getClass().getName()); + } + + public void testList() { + List list = tested.list(BASE_STRING); + assertEquals(3, list.size()); + assertEquals("ou=groups", list.get(0)); + assertEquals("c=Sweden", list.get(1)); + assertEquals("c=Norway", list.get(2)); + } + + public void testList_Name() { + List list = tested.list(BASE_NAME); + assertEquals(3, list.size()); + assertEquals("ou=groups", list.get(0)); + assertEquals("c=Sweden", list.get(1)); + assertEquals("c=Norway", list.get(2)); + } + + public void testList_Handler() throws Exception { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.list(BASE_STRING, handler); + assertEquals(3, handler.getNoOfRows()); + } + + public void testList_Name_Handler() throws Exception { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.list(BASE_NAME, handler); + assertEquals(3, handler.getNoOfRows()); + } + + public void testListBindings() { + List list = tested.listBindings(BASE_STRING); + assertEquals(3, list.size()); + assertEquals("ou=groups", list.get(0)); + assertEquals("c=Sweden", list.get(1)); + assertEquals("c=Norway", list.get(2)); + } + + public void testListBindings_Name() { + List list = tested.listBindings(BASE_NAME); + assertEquals(3, list.size()); + assertEquals("ou=groups", list.get(0)); + assertEquals("c=Sweden", list.get(1)); + assertEquals("c=Norway", list.get(2)); + } + + public void testListBindings_Handler() throws Exception { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.listBindings(BASE_STRING, handler); + assertEquals(3, handler.getNoOfRows()); + } + + public void testListBindings_Name_Handler() throws Exception { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.listBindings(BASE_NAME, handler); + assertEquals(3, handler.getNoOfRows()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateLookupITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateLookupITest.java new file mode 100644 index 00000000..ebbd224a --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateLookupITest.java @@ -0,0 +1,220 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the lookup methods of LdapTemplate. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplateLookupITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + /** + * This method depends on a DirObjectFactory ({@link org.springframework.ldap.support.DefaultDirObjectFactory}) + * being set in the ContextSource. + */ + public void testLookup_Plain() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person2, ou=company1,c=Sweden"); + + assertEquals("Some Person2", result.getStringAttribute("cn")); + assertEquals("Person2", result.getStringAttribute("sn")); + assertEquals("Sweden, Company1, Some Person2", result + .getStringAttribute("description")); + } + + public void testLookup_AttributesMapper() { + AttributesMapper mapper = new PersonAttributesMapper(); + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", mapper); + + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + public void testLookup_AttributesMapper_DistinguishedName() { + AttributesMapper mapper = new PersonAttributesMapper(); + Person person = (Person) tested.lookup(new DistinguishedName( + "cn=Some Person2, ou=company1,c=Sweden"), mapper); + + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + /** + * An {@link AttributesMapper} that only maps a subset of the full + * attributes list. Used in tests where the return attributes list has been + * limited. + * + * @author Ulrik Sandberg + */ + private final class SubsetPersonAttributesMapper implements + AttributesMapper { + /** + * Maps the cn attribute into a {@link Person} object. + * Also verifies that the other attributes haven't been set. + * + * @see org.springframework.ldap.AttributesMapper#mapFromAttributes(javax.naming.directory.Attributes) + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException { + Person person = new Person(); + person.setFullname((String) attributes.get("cn").get()); + assertNull("sn should be null", attributes.get("sn")); + assertNull("description should be null", attributes + .get("description")); + return person; + } + } + + /** + * Verifies that only the subset is used when specifying a subset of the + * available attributes as return attributes. + */ + public void testLookup_ReturnAttributes_AttributesMapper() { + AttributesMapper mapper = new SubsetPersonAttributesMapper(); + + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", new String[] { "cn" }, + mapper); + + assertEquals("Some Person2", person.getFullname()); + assertNull("lastName should not be set", person.getLastname()); + assertNull("description should not be set", person.getDescription()); + } + + /** + * Verifies that only the subset is used when specifying a subset of the + * available attributes as return attributes. Uses DistinguishedName instead + * of plain string as name. + */ + public void testLookup_ReturnAttributes_AttributesMapper_DistinguishedName() { + AttributesMapper mapper = new SubsetPersonAttributesMapper(); + Person person = (Person) tested.lookup(new DistinguishedName( + "cn=Some Person2, ou=company1,c=Sweden"), + new String[] { "cn" }, mapper); + + assertEquals("Some Person2", person.getFullname()); + assertNull("lastName should not be set", person.getLastname()); + assertNull("description should not be set", person.getDescription()); + } + + /** + * This method depends on a DirObjectFactory ({@link org.springframework.ldap.support.DefaultDirObjectFactory}) + * being set in the ContextSource. + */ + public void testLookup_ContextMapper() { + ContextMapper mapper = new PersonContextMapper(); + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", mapper); + + assertEquals("Some Person2", person.getFullname()); + assertEquals("Person2", person.getLastname()); + assertEquals("Sweden, Company1, Some Person2", person.getDescription()); + } + + /** + * Verifies that only the subset is used when specifying a subset of the + * available attributes as return attributes. + */ + public void testLookup_ReturnAttributes_ContextMapper() { + ContextMapper mapper = new PersonContextMapper(); + + Person person = (Person) tested.lookup( + "cn=Some Person2, ou=company1,c=Sweden", new String[] { "cn" }, + mapper); + + assertEquals("Some Person2", person.getFullname()); + assertNull("lastName should not be set", person.getLastname()); + assertNull("description should not be set", person.getDescription()); + } + + /** + * Verifies that we can lookup an entry that has a multi-valued rdn, which + * means more than one attribute is part of the relative DN for the entry. + * + * TODO Enable test when ApacheDS supports multi-valued rdns. + */ + public void DISABLED_testLookup_MultiValuedRdn() { + AttributesMapper mapper = new PersonAttributesMapper(); + Person person = (Person) tested.lookup( + "cn=Some Person+sn=Person, ou=company1,c=Norway", mapper); + + assertEquals("Some Person", person.getFullname()); + assertEquals("Person", person.getLastname()); + assertEquals("Norway, Company1, Some Person2", person.getDescription()); + } + + /** + * Verifies that we can lookup an entry that has a multi-valued rdn, which + * means more than one attribute is part of the relative DN for the entry. + * + * TODO Enable test when ApacheDS supports multi-valued rdns. + */ + public void DISABLED_testLookup_MultiValuedRdn_DirContextAdapter() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person+sn=Person, ou=company1,c=Norway"); + + assertEquals("Some Person", result.getStringAttribute("cn")); + assertEquals("Person", result.getStringAttribute("sn")); + assertEquals("Norway, Company1, Some Person", result + .getStringAttribute("description")); + } + + public void testLookup_GetNameInNamespace_Plain() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person2, ou=company1,c=Sweden"); + + assertEquals("cn=Some Person2, ou=company1, c=Sweden", result.getDn() + .toString()); + assertEquals( + "cn=Some Person2, ou=company1, c=Sweden, dc=jayway, dc=se", + result.getNameInNamespace()); + } + + public void testLookup_GetNameInNamespace_MultiRdn() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person+sn=Person, ou=company1,c=Norway"); + + assertEquals("cn=Some Person+sn=Person, ou=company1, c=Norway", result + .getDn().toString()); + assertEquals( + "cn=Some Person+sn=Person, ou=company1, c=Norway, dc=jayway, dc=se", + result.getNameInNamespace()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateModifyITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateModifyITest.java new file mode 100644 index 00000000..0e511e3f --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateModifyITest.java @@ -0,0 +1,251 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; + + +import org.springframework.dao.DataAccessException; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.UncategorizedLdapException; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the modification methods (rebind and modifyAttributes) of LdapTemplate. + * It also illustrates the use of DirContextAdapter as a means of getting + * ModificationItems, in order to avoid doing a full rebind and use + * modifyAttributes() instead. We rely on that the bind, unbind and lookup + * methods work as they should - that should be ok, since that is verified in a + * separate test class. NOTE: if any of the tests in this class fails, it may be + * necessary to run the cleanup script as described in README.txt under + * /src/iutest/. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplateModifyITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + private static String PERSON4_DN = "cn=Some Person4,ou=company1,c=Sweden"; + private static String PERSON5_DN = "cn=Some Person5,ou=company1,c=Sweden"; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + protected void onSetUp() throws Exception { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person4"); + adapter.setAttributeValue("sn", "Person4"); + adapter.setAttributeValue("description", "Some description"); + + tested.bind(PERSON4_DN, adapter, null); + + adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person5"); + adapter.setAttributeValue("sn", "Person5"); + adapter.setAttributeValues("description", new String[]{"qwe", "123", "rty", "uio"}); + + tested.bind(PERSON5_DN, adapter, null); + + } + + protected void onTearDown() throws Exception { + tested.unbind(PERSON4_DN); + tested.unbind(PERSON5_DN); + } + + public void testRebind_Attributes_Plain() { + Attributes attributes = setupAttributes(); + + tested.rebind(PERSON4_DN, null, attributes); + + verifyBoundCorrectData(); + } + + public void testRebind_Attributes_DistinguishedName() { + Attributes attributes = setupAttributes(); + + tested.rebind(new DistinguishedName(PERSON4_DN), null, attributes); + + verifyBoundCorrectData(); + } + + public void testModifyAttributes_MultiValueReplace() { + BasicAttribute attr = new BasicAttribute("description", + "Some other description"); + attr.add("Another description"); + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr); + + tested.modifyAttributes(PERSON4_DN, mods); + + DirContextAdapter result = (DirContextAdapter) tested.lookup(PERSON4_DN); + String[] attributes = result.getStringAttributes("description"); + assertEquals(2, attributes.length); + assertEquals("Some other description", attributes[0]); + assertEquals("Another description", attributes[1]); + } + + public void testModifyAttributes_MultiValueAdd() { + BasicAttribute attr = new BasicAttribute("description", + "Some other description"); + attr.add("Another description"); + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr); + + tested.modifyAttributes(PERSON4_DN, mods); + + DirContextAdapter result = (DirContextAdapter) tested.lookup(PERSON4_DN); + String[] attributes = result.getStringAttributes("description"); + assertEquals(3, attributes.length); + assertEquals("Some description", attributes[0]); + assertEquals("Some other description", attributes[1]); + assertEquals("Another description", attributes[2]); + } + + public void testModifyAttributes_MultiValueAddDuplicateToUnordered() { + BasicAttribute attr = new BasicAttribute("description", + "Some description"); + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr); + + try { + tested.modifyAttributes(PERSON4_DN, mods); + fail("UncategorizedLdapException expected"); + } catch (UncategorizedLdapException expected) { + // expected + } + } + + /** + * Test written originally to verify that duplicates are allowed on ordered + * attributes, but had to be changed since Apache DS seems to disallow + * duplicates even for ordered attributes. + */ + public void testModifyAttributes_MultiValueAddDuplicateToOrdered() { + BasicAttribute attr = new BasicAttribute("description", + "Some other description", true); // ordered + attr.add("Another description"); + // Commented out duplicate to make test work for Apache DS + //attr.add("Some description"); + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr); + + tested.modifyAttributes(PERSON4_DN, mods); + + DirContextAdapter result = (DirContextAdapter) tested.lookup(PERSON4_DN); + String[] attributes = result.getStringAttributes("description"); + assertEquals(3, attributes.length); + assertEquals("Some description", attributes[0]); + assertEquals("Some other description", attributes[1]); + assertEquals("Another description", attributes[2]); + } + + public void testModifyAttributes_Plain() { + ModificationItem item = new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("description", + "Some other description")); + + tested.modifyAttributes(PERSON4_DN, new ModificationItem[] { item }); + + verifyBoundCorrectData(); + } + + public void testModifyAttributes_DistinguishedName() { + ModificationItem item = new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("description", + "Some other description")); + + tested.modifyAttributes(new DistinguishedName(PERSON4_DN), + new ModificationItem[] { item }); + + verifyBoundCorrectData(); + } + + public void testModifyAttributes_DirContextAdapter_MultiAttributes(){ + DirContextAdapter adapter = (DirContextAdapter) tested.lookup(PERSON5_DN); + adapter.setAttributeValues("description", new String[]{"qwe", "123", "klytt", "kalle"}); + + tested.modifyAttributes(PERSON5_DN, adapter.getModificationItems()); + + // Verify + adapter = (DirContextAdapter) tested.lookup(PERSON5_DN); + String[] attributes = adapter.getStringAttributes("description"); + assertEquals(4, attributes.length); + assertEquals("qwe", attributes[0]); + assertEquals("123", attributes[1]); + assertEquals("klytt", attributes[2]); + assertEquals("kalle", attributes[3]); + } + + /** + * Demonstrates how the DirContextAdapter can be used to automatically keep + * track of changes of the attributes and deliver ModificationItems to use + * in moifyAttributes(). + * + * @throws NamingException + * @throws DataAccessException + */ + public void testModifyAttributes_DirContextAdapter() + throws DataAccessException, NamingException { + DirContextAdapter adapter = (DirContextAdapter) tested.lookup(PERSON4_DN); + + adapter.setAttributeValue("description", "Some other description"); + + ModificationItem[] modificationItems = adapter.getModificationItems(); + tested.modifyAttributes(PERSON4_DN, modificationItems); + + verifyBoundCorrectData(); + } + + private Attributes setupAttributes() { + Attributes attributes = new BasicAttributes(); + BasicAttribute ocattr = new BasicAttribute("objectclass"); + ocattr.add("top"); + ocattr.add("person"); + attributes.put(ocattr); + attributes.put("cn", "Some Person4"); + attributes.put("sn", "Person4"); + attributes.put("description", "Some other description"); + return attributes; + } + + private void verifyBoundCorrectData() { + DirContextAdapter result = (DirContextAdapter) tested.lookup(PERSON4_DN); + assertEquals("Some Person4", result.getStringAttribute("cn")); + assertEquals("Person4", result.getStringAttribute("sn")); + assertEquals("Some other description", result + .getStringAttribute("description")); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateNoBaseSuffixITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateNoBaseSuffixITest.java new file mode 100644 index 00000000..98e1076d --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateNoBaseSuffixITest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.ldap.EntryNotFoundException; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.CountNameClassPairCallbackHandler; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests to verify that not setting a base suffix on the ContextSource (as + * defined in ldapTemplateNoBaseSuffixTestContext.xml) works as expected. + * + * NOTE: This test will not work under Java 1.4.1 or earlier. + * + * @author Mattias Arthursson + */ +public class LdapTemplateNoBaseSuffixITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateNoBaseSuffixTestContext.xml" }; + } + + /** + * This method depends on a DirObjectFactory ({@link org.springframework.ldap.support.DefaultDirObjectFactory}) + * being set in the ContextSource. + */ + public void testLookup_Plain() { + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person2, ou=company1, c=Sweden, dc=jayway, dc=se"); + + assertEquals("Some Person2", result.getStringAttribute("cn")); + assertEquals("Person2", result.getStringAttribute("sn")); + assertEquals("Sweden, Company1, Some Person2", result + .getStringAttribute("description")); + assertEquals( + "cn=Some Person2, ou=company1, c=Sweden, dc=jayway, dc=se", + result.getDn().toString()); + assertEquals( + "cn=Some Person2, ou=company1, c=Sweden, dc=jayway, dc=se", + result.getNameInNamespace()); + } + + public void testSearch_Plain() { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + + tested.search("dc=jayway, dc=se", "(objectclass=person)", handler); + assertEquals(5, handler.getNoOfRows()); + } + + public void testBindAndUnbind_Plain() { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person4"); + adapter.setAttributeValue("sn", "Person4"); + tested.bind("cn=Some Person4, ou=company1, c=Sweden, dc=jayway, dc=se", + adapter, null); + + DirContextAdapter result = (DirContextAdapter) tested + .lookup("cn=Some Person4, ou=company1, c=Sweden, dc=jayway, dc=se"); + + assertEquals("Some Person4", result.getStringAttribute("cn")); + assertEquals("Person4", result.getStringAttribute("sn")); + assertEquals( + "cn=Some Person4, ou=company1, c=Sweden, dc=jayway, dc=se", + result.getDn().toString()); + + tested + .unbind("cn=Some Person4, ou=company1, c=Sweden, dc=jayway, dc=se"); + try { + tested + .lookup("cn=Some Person4, ou=company1, c=Sweden, dc=jayway, dc=se"); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRecursiveDeleteITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRecursiveDeleteITest.java new file mode 100644 index 00000000..a793ffb1 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRecursiveDeleteITest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Name; + +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the recursive modification methods (unbind and the protected delete + * methods) of LdapTemplate. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplateRecursiveDeleteITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + private static DistinguishedName DN = new DistinguishedName( + "cn=Some Person5,ou=company1,c=Sweden"); + + private DistinguishedName firstSubDn; + + private DistinguishedName secondSubDn; + + private DistinguishedName leafDn; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + protected void onSetUp() throws Exception { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person5"); + adapter.setAttributeValue("sn", "Person5"); + adapter.setAttributeValue("description", "Some description"); + tested.bind(DN, adapter, null); + + firstSubDn = new DistinguishedName("cn=subPerson"); + firstSubDn.prepend(DN); + adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "subPerson"); + adapter.setAttributeValue("sn", "subPerson"); + adapter.setAttributeValue("description", + "Should be recursively deleted"); + tested.bind(firstSubDn, adapter, null); + secondSubDn = new DistinguishedName("cn=subPerson2"); + secondSubDn.prepend(DN); + adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "subPerson2"); + adapter.setAttributeValue("sn", "subPerson2"); + adapter.setAttributeValue("description", + "Should be recursively deleted"); + tested.bind(secondSubDn, adapter, null); + + leafDn = new DistinguishedName("cn=subSubPerson"); + leafDn.prepend(firstSubDn); + adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "subSubPerson"); + adapter.setAttributeValue("sn", "subSubPerson"); + adapter.setAttributeValue("description", + "Should be recursively deleted"); + tested.bind(leafDn, adapter, null); + } + + protected void onTearDown() throws Exception { + try { + tested.unbind(DN, true); + } catch (EntryNotFoundException ignore) { + // ignore + } + } + + public void testRecursiveUnbind() { + tested.unbind(DN, true); + + verifyDeleted(DN); + verifyDeleted(firstSubDn); + verifyDeleted(secondSubDn); + verifyDeleted(leafDn); + } + + public void testRecursiveUnbindOnLeaf() { + tested.unbind(leafDn, true); + verifyDeleted(leafDn); + } + + private void verifyDeleted(Name dn) { + try { + tested.lookup(dn); + fail("Expected entry '" + dn + "' to be non-existent"); + } catch (EntryNotFoundException expected) { + // expected + } + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRenameITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRenameITest.java new file mode 100644 index 00000000..cb871519 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateRenameITest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Name; + + +import org.springframework.ldap.EntryNotFoundException; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests the rename methods of LdapTemplate. + * + * We rely on that the bind, unbind and lookup methods work as they should - + * that should be ok, since that is verified in a separate test class. * + * + * @author Ulrik Sandberg + */ +public class LdapTemplateRenameITest extends + AbstractDependencyInjectionSpringContextTests { + private LdapTemplate tested; + + private static String DN = "cn=Some Person6,ou=company1,c=Sweden"; + + private static String NEWDN = "cn=Some Person6,ou=company2,c=Sweden"; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + protected void onSetUp() throws Exception { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", + "person" }); + adapter.setAttributeValue("cn", "Some Person6"); + adapter.setAttributeValue("sn", "Person6"); + adapter.setAttributeValue("description", "Some description"); + + tested.bind(DN, adapter, null); + } + + protected void onTearDown() throws Exception { + tested.unbind(NEWDN); + tested.unbind(DN); + } + + public void testRename() { + tested.rename(DN, NEWDN); + + verifyDeleted(new DistinguishedName(DN)); + verifyBoundCorrectData(); + } + + public void testRename_DistinguishedName() throws Exception { + Name oldDn = new DistinguishedName(DN); + Name newDn = new DistinguishedName(NEWDN); + tested.rename(oldDn, newDn); + + + verifyDeleted(oldDn); + verifyBoundCorrectData(); + } + + private void verifyDeleted(Name dn) { + try { + tested.lookup(dn); + fail("Expected entry '" + dn + "' to be non-existent"); + } catch (EntryNotFoundException expected) { + // expected + } + } + + private void verifyBoundCorrectData() { + DirContextAdapter result = (DirContextAdapter) tested.lookup(NEWDN); + assertEquals("Some Person6", result.getStringAttribute("cn")); + assertEquals("Person6", result.getStringAttribute("sn")); + assertEquals("Some description", result + .getStringAttribute("description")); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.java new file mode 100644 index 00000000..b631d071 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + + +import org.ddsteps.spring.DDStepsSpringTestCase; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.CountNameClassPairCallbackHandler; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Tests for LdapTemplate's search methods. This test class tests the generic + * search methods - the ones that take a SearchResultCallbackHandler. + * + * NOTE: The tests in this class expects an LDAP Server to be running with + * correct data in it. See Readme.TXT under /src/iutest/ for information on how + * to set up LDAP Server and data. + * + * Use DDSteps in order to get data-driven tests - use the same method over and + * over with data from Excel. The instance variables base, filter and + * expectedResults are automatically filled with new data for each row specified + * in LdapTemplateSearchCountITest.xls. See ddsteps.org for more information. + * + * @author Mattias Arthursson + */ +public class LdapTemplateSearchCountITest extends DDStepsSpringTestCase { + + private static final boolean DONT_RETURN_OBJECTS = false; + + private String base; + + private String filter; + + private int expectedResults; + + private int searchScope; + + private LdapTemplate tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateNoBaseSuffixTestContext.xml" }; + } + + public void testSearch_Count() { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.search(base, filter, handler); + assertEquals(expectedResults, handler.getNoOfRows()); + } + + public void testSearch_Count_DN() { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.search(new DistinguishedName(base), filter, handler); + assertEquals(expectedResults, handler.getNoOfRows()); + } + + public void testSearch_Count_SearchScope() { + CountNameClassPairCallbackHandler handler = new CountNameClassPairCallbackHandler(); + tested.search(base, filter, searchScope, DONT_RETURN_OBJECTS, handler); + assertEquals(expectedResults, handler.getNoOfRows()); + } + + public void setBase(String base) { + this.base = base; + } + + public void setExpectedResults(int expectedResults) { + this.expectedResults = expectedResults; + } + + public void setFilter(String filter) { + this.filter = filter; + } + + public void setSearchScope(int searchScope) { + this.searchScope = searchScope; + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.xls b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchCountITest.xls new file mode 100644 index 0000000000000000000000000000000000000000..576261b9e394b4ea955d48d43c1e7fae5ff8456e GIT binary patch literal 17408 zcmeHPeQaA-6+h2;X`Hl;lk{_4Ym5`t*iA}SHd=^MyIWT=K}*#zZPGHij`K>oq;X_B zYAf-P!7BKpNWhTbk4e+CF_v|78-s0VLuw@?hQtH{O%q>IJNOF;ZJ;4BX>0iX&h@k3 zd$CJe*kJIkb?<%m-1BwMz4zP?Kl>Ly@4oQhQ=2YIAncYFxwP0WD?D%u&k48OC8%Fq zWYNvvhi8Do@E)>2dlVhHqE#+!eyQ!J=kSP5z9=n?2rSLM5;D%MLEmxpO8ZQ58OIaNxcd7ctY^=+EU z0~@ZI$^(kqee#IFAu0^g{Jd&_xSf*kNZ%4XFGmmZZh2Hb;%SxPs%EJ+tOlu?)Kk`u z*eweI4!NmZ$4mBT)HO!jzmsHx{=;ssXuWHLcr_Q{#0oPz2or8|Ay0Fb&Y}ltbdkgxuAHaHpKb=vYFy z9kQB9Gj(x$k34~4)0Fh`l3gZ_JPAQouGXrwBs}dU+}q|xwSL;9ax!#Gv%)lP&&gAm ze@z7$eGFOM#C~yJ9AcVoAdV55k&Fr(*3=ceS-vM5;E4K+pUb6&$NJsESSoJ6U!IoD zzIroNd`L<8zHF%@VF>y7a7cmGR`~%`sfjXJ0d7^)o$`$Az?i2L*Mp^otHrT?Gx2Kx zdNLNWIY`+q&%*bC)JvC6c!`Yft5Ia+Ir*qxn9f}p>$=uDwxtYo-xmG6Ev2M+h zy4>Car?7TDkM&yM6oRBV!)LTmoOMp4RTkET^Hvm5WPX<=Z^?p{RmR%p@qF3AY3In% z>55Z|i8v=_okGQ#IOLS)rYmJkjQ-;I-2fG)^X2l$tWzo%XHqR9gM)+ELw_ouICeYz z*EOQ(FU*XL7LPfJgN8$@w<%_MX2c-vNG%8JhExij)n6D%r#dtrJ?>06Gb#AX%h_h7 zNLekemO{&YTBlRkb}k{`djNP7g^|1SCy(b(4&bTmU<+CpF(L_AQgxtMs^WU9u=gp> zjTDN4wMDtXOVv#g@fqMLUbJ>0M(!a2G3uH9mE`Qx_n2R zl@a6Uh>y;bi`^otLA6>qAXg!skeEJqBPC8$-dgy}FZYih%;XfFR`@nezo3wL;JD!f zm;g9L$UUezZ&Mak`l4drtLc8(4U~O2R-AB&t|GT=v41CrTUxHOptmJ|>L^Ahz{kQN zhGnKApTMT3f{%lP%)1x%9?5Ids6iM)3xpQ<_gdgV>|QPSDKqmUnCrZ_V7QQ}=eNPz zMCG&UHbrht$8cE?(K6|NyWNx}f(sr5`a;1ai%2x$KI8o=mBgLv%?VD#=mJgf{$U|ceSc&i)0XoDag);S;SZJ|`b>cAGVM2oD` zT@y>R#d<_j$6d#IM7I<{iR%e5NnfX9+%Q|MKVp4Zv z^4gD>rtN&%p#AoWB;*Zrk8O1VC#^A!-22%b>A_);A*-oLwt!!YnL-xG`1BgOO=Kq` z#V%(P(uZ+#7@OI5Zxccn!flFiAso7H_-8J}uDKBT5M78VM_|~m$4ohNDRiM%=2D2w z=@`0{(53v#E`@IA_$HA#od5p2UCJ|C>Mn$?sIRA9rb}TtQgtycm>fYD!Z>4wv6caQ{Y3 zvzOq?`6I0G-2LH#6~U~4EsE1;GiG%)6lQPX$}oEimx6l>m60XI=B%Nh zEzExB6@03xpO3Ef88Dv_NQq&;p?aLJNcz2rUp= zAhf{$y9F+H{*S!;(#!X6zqaeXZ{qwv@a9>b|D!ng^Dc(x|AUA;qu+tZ>z)ZjUTaMw z@{C?VQGya*vrhF~6t5T5V(1y}G5 z6@8H{2*e9Rd@pbbviD6PSp}}tiZ>0EczdxlRi1R5N?C=47YeXR7(xq#76>g6S|GGQ zXo1iIp#?$hTIUUrUu0I12Q z9?K>CF$W_;tBlH=9K$ECZNC*(IHEccQo-;3i-0r_{gBT&#QC#a`T80aCl5la?1hAa W>fmS(T$w)jcY`Z#zrLDPmH!XW)o2I+ literal 0 HcmV?d00001 diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchResultITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchResultITest.java new file mode 100644 index 00000000..f450ae9a --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/LdapTemplateSearchResultITest.java @@ -0,0 +1,178 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Name; +import javax.naming.directory.SearchControls; + +import org.springframework.ldap.support.DistinguishedName; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests for LdapTemplate's search methods. This test class tests all the + * different versions of the search methods except the generic ones covered in + * other tests. + * + * @author Mattias Arthursson + */ +public class LdapTemplateSearchResultITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapTemplate tested; + + private AttributeCheckAttributesMapper attributesMapper; + + private AttributeCheckContextMapper contextMapper; + + private static final String[] ALL_ATTRIBUTES = { "cn", "sn", "description", + "telephoneNumber" }; + + private static final String[] CN_SN_ATTRS = { "cn", "sn" }; + + private static final String[] ABSENT_ATTRIBUTES = { "description", + "telephoneNumber" }; + + private static final String[] CN_SN_VALUES = { "Some Person2", "Person2" }; + + private static final String[] ALL_VALUES = { "Some Person2", "Person2", + "Sweden, Company1, Some Person2", "+46 555-654321" }; + + private static final String BASE_STRING = ""; + + private static final String FILTER_STRING = "(&(objectclass=person)(sn=Person2))"; + + private static final Name BASE_NAME = new DistinguishedName(BASE_STRING); + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + protected void onSetUp() throws Exception { + super.onSetUp(); + + attributesMapper = new AttributeCheckAttributesMapper(); + contextMapper = new AttributeCheckContextMapper(); + } + + protected void onTearDown() throws Exception { + super.onTearDown(); + + attributesMapper = null; + contextMapper = null; + } + + public void testSearch_AttributesMapper() { + attributesMapper.setExpectedAttributes(ALL_ATTRIBUTES); + attributesMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_STRING, FILTER_STRING, attributesMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_AttributesMapper() { + attributesMapper.setExpectedAttributes(ALL_ATTRIBUTES); + attributesMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_STRING, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, attributesMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_LimitedAttrs_AttributesMapper() { + attributesMapper.setExpectedAttributes(CN_SN_ATTRS); + attributesMapper.setExpectedValues(CN_SN_VALUES); + attributesMapper.setAbsentAttributes(ABSENT_ATTRIBUTES); + List list = tested.search(BASE_STRING, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, CN_SN_ATTRS, attributesMapper); + assertEquals(1, list.size()); + } + + public void testSearch_AttributesMapper_Name() { + attributesMapper.setExpectedAttributes(ALL_ATTRIBUTES); + attributesMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_NAME, FILTER_STRING, attributesMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_AttributesMapper_Name() { + attributesMapper.setExpectedAttributes(ALL_ATTRIBUTES); + attributesMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_NAME, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, attributesMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_LimitedAttrs_AttributesMapper_Name() { + attributesMapper.setExpectedAttributes(CN_SN_ATTRS); + attributesMapper.setExpectedValues(CN_SN_VALUES); + attributesMapper.setAbsentAttributes(ABSENT_ATTRIBUTES); + List list = tested.search(BASE_NAME, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, CN_SN_ATTRS, attributesMapper); + assertEquals(1, list.size()); + } + + public void testSearch_ContextMapper() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_STRING, FILTER_STRING, contextMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_ContextMapper() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_STRING, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, contextMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_LimitedAttrs_ContextMapper() { + contextMapper.setExpectedAttributes(CN_SN_ATTRS); + contextMapper.setExpectedValues(CN_SN_VALUES); + contextMapper.setAbsentAttributes(ABSENT_ATTRIBUTES); + List list = tested.search(BASE_STRING, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, CN_SN_ATTRS, contextMapper); + assertEquals(1, list.size()); + } + + public void testSearch_ContextMapper_Name() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_NAME, FILTER_STRING, contextMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_ContextMapper_Name() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + List list = tested.search(BASE_NAME, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, contextMapper); + assertEquals(1, list.size()); + } + + public void testSearch_SearchScope_LimitedAttrs_ContextMapper_Name() { + contextMapper.setExpectedAttributes(CN_SN_ATTRS); + contextMapper.setExpectedValues(CN_SN_VALUES); + contextMapper.setAbsentAttributes(ABSENT_ATTRIBUTES); + List list = tested.search(BASE_NAME, FILTER_STRING, + SearchControls.SUBTREE_SCOPE, CN_SN_ATTRS, contextMapper); + assertEquals(1, list.size()); + } + + public void setTested(LdapTemplate tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/Person.java b/spring-ldap/src/itest/java/org/springframework/ldap/Person.java new file mode 100644 index 00000000..bfe7b75f --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/Person.java @@ -0,0 +1,64 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * Dummy bean to be used in the LdapTemplate integration tests. + * + * @author Mattias Arthursson + */ +public class Person { + private String fullname; + + private String lastname; + + private String description; + + private String phone; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getFullname() { + return fullname; + } + + public void setFullname(String fullname) { + this.fullname = fullname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/PersonAttributesMapper.java b/spring-ldap/src/itest/java/org/springframework/ldap/PersonAttributesMapper.java new file mode 100644 index 00000000..caa58e51 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/PersonAttributesMapper.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.springframework.ldap.AttributesMapper; + + +/** + * Dummy implementation of AttributesMapper for use in integration tests. + * + * @author Mattias Arthursson + * + */ +public class PersonAttributesMapper implements AttributesMapper { + + /** + * Maps the given attributes into a {@link Person} object. + * + * @see org.springframework.ldap.AttributesMapper#mapFromAttributes(javax.naming.directory.Attributes) + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException { + Person person = new Person(); + person.setFullname((String) attributes.get("cn").get()); + person.setLastname((String) attributes.get("sn").get()); + person.setPhone((String) attributes.get("telephoneNumber").get()); + person.setDescription((String) attributes.get("description").get()); + return person; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/PersonContextMapper.java b/spring-ldap/src/itest/java/org/springframework/ldap/PersonContextMapper.java new file mode 100644 index 00000000..f93c726a --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/PersonContextMapper.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.ldap.ContextMapper; +import org.springframework.ldap.support.DirContextAdapter; + +/** + * Dummy implemention of ContextMapper for use in the integration tests and for + * illustration purposes. + * + * @author Mattias Arthursson + */ +public class PersonContextMapper implements ContextMapper { + + /* (non-Javadoc) + * @see org.springframework.ldap.ContextMapper#mapFromContext(java.lang.Object) + */ + public Object mapFromContext(Object ctx) { + DirContextAdapter adapter = (DirContextAdapter) ctx; + Person person = new Person(); + person.setFullname(adapter.getStringAttribute("cn")); + person.setLastname(adapter.getStringAttribute("sn")); + person.setPhone(adapter.getStringAttribute("telephoneNumber")); + person.setDescription(adapter.getStringAttribute("description")); + return person; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/support/DnParsePerformanceITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/support/DnParsePerformanceITest.java new file mode 100644 index 00000000..c9a69dd9 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/support/DnParsePerformanceITest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import junit.framework.Test; +import junit.framework.TestCase; + +import com.clarkware.junitperf.LoadTest; + +/** + * Performance test for the {@link DistinguishedName} class. + * + * @author Ulrik Sandberg + */ +public class DnParsePerformanceITest extends TestCase { + + public DnParsePerformanceITest(String name) { + super(name); + } + + /** + * Tests parsing and toString. + */ + public void testContains() { + + DistinguishedName migpath = new DistinguishedName("OU=G,OU=I,OU=M"); + DistinguishedName path1 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE,OU=G,OU=I,OU=M"); + DistinguishedName path2 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE,ou=G,OU=i,OU=M, ou=foo"); + DistinguishedName path3 = new DistinguishedName( + "ou=G,OU=i,OU=M, ou=foo"); + DistinguishedName path4 = new DistinguishedName("ou=G,OU=i,ou=m"); + + DistinguishedName pathE1 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE,ou=G,OU=L,OU=M, ou=foo"); + DistinguishedName pathE2 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE"); + + assertTrue("Contains MIG", path1.contains(migpath)); + assertTrue("Contains MIG", path2.contains(migpath)); + assertTrue("Contains MIG", path3.contains(migpath)); + assertTrue("Contains MIG", path4.contains(migpath)); + + assertFalse("Does not contain MIG", pathE1.contains(migpath)); + assertFalse("Does not contain MIG", pathE2.contains(migpath)); + } + + public static Test suite() { + int users = 2000; + Test testCase = new DnParsePerformanceITest("testContains"); + Test loadTest = new LoadTest(testCase, users); + return loadTest; + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } +} \ No newline at end of file diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelITest.java new file mode 100644 index 00000000..10fb775c --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelITest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.support.LdapContextSource; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Integration tests for ContextSourceImpl. + * + * @author Mattias Arthursson + */ +public class LdapContextSourcelITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapContextSource tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateTestContext.xml" }; + } + + public void testGetReadOnlyContext() throws NamingException { + DirContext ctx = null; + + try { + ctx = tested.getReadOnlyContext(); + assertNotNull(ctx); + Hashtable environment = ctx.getEnvironment(); + assertTrue(environment + .containsKey(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertTrue(environment.containsKey(Context.SECURITY_PRINCIPAL)); + assertTrue(environment.containsKey(Context.SECURITY_CREDENTIALS)); + } finally { + // Always clean up. + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this + } + } + } + } + + public void testGetReadWriteContext() throws NamingException { + DirContext ctx = null; + + try { + ctx = tested.getReadWriteContext(); + assertNotNull(ctx); + // Double check to see that we are authenticated. + Hashtable environment = ctx.getEnvironment(); + assertTrue(environment.containsKey(Context.SECURITY_PRINCIPAL)); + assertTrue(environment.containsKey(Context.SECURITY_CREDENTIALS)); + } finally { + // Always clean up. + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this + } + } + } + } + + public void setTested(LdapContextSource tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelMultiServerITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelMultiServerITest.java new file mode 100644 index 00000000..743d1174 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/support/LdapContextSourcelMultiServerITest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.NamingException; + +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Integration tests for ContextSourceImpl. + * + * @author Mattias Arthursson + */ +public class LdapContextSourcelMultiServerITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapContextSource tested; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapContextSourceTestContext.xml" }; + } + + public void testUrls() throws NamingException { + String[] urls = tested.getUrls(); + String string = tested.assembleProviderUrlString(urls); + + assertEquals("ldap://127.0.0.1:389 ldap://127.0.0.2:389", string); + } + + public void setTested(LdapContextSource tested) { + this.tested = tested; + } +} diff --git a/spring-ldap/src/itest/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceITest.java b/spring-ldap/src/itest/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceITest.java new file mode 100644 index 00000000..a11a4a74 --- /dev/null +++ b/spring-ldap/src/itest/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceITest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import java.util.List; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + + +import org.acegisecurity.Authentication; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.acegisecurity.providers.ldap.LdapAuthenticationProvider; +import org.springframework.ldap.AttributesMapper; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.support.authentication.AcegiAuthenticationSource; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +public class AcegiAuthenticationSourceITest extends + AbstractDependencyInjectionSpringContextTests { + + private LdapAuthenticationProvider ldapAuthProvider; + + private LdapTemplate ldapTemplate; + + protected String[] getConfigLocations() { + return new String[] { "/conf/ldapTemplateAcegiTestContext.xml" }; + } + + public void setLdapAuthProvider(LdapAuthenticationProvider ldapAuthProvider) { + this.ldapAuthProvider = ldapAuthProvider; + } + + public void setLdapTemplate(LdapTemplate ldapTemplate) { + this.ldapTemplate = ldapTemplate; + } + + public void testGetPrincipalAndCredentials() { + Authentication authentication = ldapAuthProvider + .authenticate(new UsernamePasswordAuthenticationToken( + "Some Person3", "password")); + SecurityContextHolder.getContext().setAuthentication(authentication); + + AcegiAuthenticationSource tested = new AcegiAuthenticationSource(); + assertEquals("cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se", + tested.getPrincipal()); + assertEquals("password", tested.getCredentials()); + } + + public void testSearchIndiviualAuthentication() { + Authentication authentication = ldapAuthProvider + .authenticate(new UsernamePasswordAuthenticationToken( + "Some Person3", "password")); + SecurityContextHolder.getContext().setAuthentication(authentication); + + List result = ldapTemplate.search("dc=jayway,dc=se", + "(objectclass=person)", new AttributesMapper() { + public Object mapFromAttributes(Attributes attributes) + throws NamingException { + return attributes.get("cn"); + } + }); + assertEquals(5, result.size()); + } + +} diff --git a/spring-ldap/src/itest/java/setup_data.ldif b/spring-ldap/src/itest/java/setup_data.ldif new file mode 100644 index 00000000..885a8ca4 --- /dev/null +++ b/spring-ldap/src/itest/java/setup_data.ldif @@ -0,0 +1,110 @@ +dn: ou=groups,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: cn=ROLE_USER,ou=groups,dc=jayway,dc=se +objectclass: top +objectclass: groupOfUniqueNames +cn: ROLE_USER +uniqueMember: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +uniqueMember: cn=Some Person,ou=company1,c=Norway,dc=jayway,dc=se +uniqueMember: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +uniqueMember: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se + +dn: cn=ROLE_ADMIN,ou=groups,dc=jayway,dc=se +objectclass: top +objectclass: groupOfUniqueNames +cn: ROLE_ADMIN +uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se + +dn: c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Sweden +description: The country of Sweden + +dn: c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: country +c: Norway +description: The country of Norway + +dn: ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Sweden + +dn: ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company2 +description: Second company in Sweden + +dn: ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: organizationalUnit +ou: company1 +description: First company in Norway + +dn: cn=Some Person,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person +userPassword: password +cn: Some Person +sn: Person +description: Sweden, Company1, Some Person +telephoneNumber: +46 555-123456 + +dn: cn=Some Person2,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person2 +userPassword: password +cn: Some Person2 +sn: Person2 +description: Sweden, Company1, Some Person2 +telephoneNumber: +46 555-654321 + +dn: cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person3 +userPassword: password +cn: Some Person3 +sn: Person3 +description: Sweden, Company1, Some Person3 +telephoneNumber: +46 555-123654 + +dn: cn=Some Person,ou=company2,c=Sweden,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.person4 +userPassword: password +cn: Some Person +sn: Person +description: Sweden, Company2, Some Person +telephoneNumber: +46 555-456321 + +dn: cn=Some Person+sn=Person,ou=company1,c=Norway,dc=jayway,dc=se +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: some.norwegian +userPassword: password +cn: Some Person +sn: Person +description: Norway, Company1, Some Person+Person +telephoneNumber: +45 555-654123 diff --git a/spring-ldap/src/itest/java/teardown_data.ldif b/spring-ldap/src/itest/java/teardown_data.ldif new file mode 100644 index 00000000..f6ada1b2 --- /dev/null +++ b/spring-ldap/src/itest/java/teardown_data.ldif @@ -0,0 +1,5 @@ +ou=groups,dc=jayway,dc=se + +c=Sweden,dc=jayway,dc=se + +c=Norway,dc=jayway,dc=se diff --git a/spring-ldap/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java b/spring-ldap/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java new file mode 100644 index 00000000..10089337 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/AttributesIntegrityViolationException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataIntegrityViolationException; + +/** + * Exception that indicates that an invalid or missing Attribute has been + * supplied to an LDAP operation. + * + * @author Mattias Arthursson + * + */ +public class AttributesIntegrityViolationException extends + DataIntegrityViolationException { + + private static final long serialVersionUID = -6368616096960202571L; + + public AttributesIntegrityViolationException(String msg) { + super(msg); + } + + public AttributesIntegrityViolationException(String msg, Throwable t) { + super(msg, t); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/AttributesMapper.java b/spring-ldap/src/main/java/org/springframework/ldap/AttributesMapper.java new file mode 100644 index 00000000..bc6af080 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/AttributesMapper.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Name; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +/** + * An interface used by LdapTemplate for mapping LDAP Attributes to beans. + * Implementions of this interface perform the actual work of extracting + * results, but need not worry about exception handling. NamingExceptions will + * be caught and handled correctly by the LdapTemplate class. + *

+ * Typically used in LdapTemplate's search methods. AttributeMapper objects are + * typically stateless and thus reusable; they are ideal for implementing + * attribute-mapping logic in one place. + *

+ * Alternatively, consider using a {@link ContextMapper} in stead. + * + * @see org.springframework.ldap.LdapTemplate#search(Name, String, + * AttributesMapper) + * @see ContextMapper + * + * @author Mattias Arthursson + */ +public interface AttributesMapper { + /** + * Map Attributes to an object. The supplied attributes are the attributes + * from a single SearchResult. + * + * @param attributes + * attributes from a SearchResult. + * @return an object built from the attributes. + * @throws NamingException if any error occurs mapping the attributes + */ + public Object mapFromAttributes(Attributes attributes) + throws NamingException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/AuthenticationSource.java b/spring-ldap/src/main/java/org/springframework/ldap/AuthenticationSource.java new file mode 100644 index 00000000..7a8874c1 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/AuthenticationSource.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * An AuthenticationSource is responsible for providing the principal and + * credentials to be used when creating a new context. + * + * @author Mattias Arthursson + * + */ +public interface AuthenticationSource { + /** + * Get the principal to use when creating an authenticated context. + * + * @return the principal (userName). + */ + public String getPrincipal(); + + /** + * Get the credentials to use when creating an authenticated context. + * + * @return the credentials (userName). + */ + public String getCredentials(); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/BadLdapGrammarException.java b/spring-ldap/src/main/java/org/springframework/ldap/BadLdapGrammarException.java new file mode 100644 index 00000000..a7d55dbd --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/BadLdapGrammarException.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.InvalidDataAccessResourceUsageException; + +/** + * Thrown to indicate that an invalid value has been supplied to an LDAP + * operation. This could be an invalid filter or dn. + * + * @author Mattias Arthursson + */ +public class BadLdapGrammarException extends + InvalidDataAccessResourceUsageException { + + private static final long serialVersionUID = 961612585331409470L; + + public BadLdapGrammarException(String message) { + super(message); + } + + public BadLdapGrammarException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java b/spring-ldap/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java new file mode 100644 index 00000000..6f42103d --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/CollectingNameClassPairCallbackHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.LinkedList; +import java.util.List; + +import javax.naming.NameClassPair; + +/** + * A NameClassPairCallbackHandler to collect all results in an internal List. + * + * @see org.springframework.ldap.LdapTemplate + * + * @author Mattias Arthursson + */ +public abstract class CollectingNameClassPairCallbackHandler implements + NameClassPairCallbackHandler { + + private List list = new LinkedList(); + + /** + * Get the assembled list. + * + * @return the list of all assembled objects. + */ + public List getList() { + return list; + } + + /** + * Pass on the supplied NameClassPair to + * {@link #getObjectFromNameClassPair(NameClassPair)} and add the result to + * the internal list. + */ + public void handleNameClassPair(NameClassPair nameClassPair) { + list.add(getObjectFromNameClassPair(nameClassPair)); + } + + /** + * Handle a NameClassPair and transform it to an Object of the desired type + * and with data from the NameClassPair. + * + * @param nameClassPair + * a NameClassPair from a search operation. + * @return an object constructed from the data in the NameClassPair. + */ + public abstract Object getObjectFromNameClassPair( + NameClassPair nameClassPair); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/ContextAssembler.java b/spring-ldap/src/main/java/org/springframework/ldap/ContextAssembler.java new file mode 100644 index 00000000..da2ef350 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/ContextAssembler.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +/** + * Helper interface to be used by Dao implementations for assembling to and from + * context. Useful if we have assembler classes responsible for mapping to and + * from a specific entry. + * + * @author Mattias Arthursson + */ +public interface ContextAssembler extends ContextMapper { + /** + * Map the supplied object to the specified context. + * + * @param obj + * the object to read data from. + * @param ctx + * the context to map to. + */ + public void mapToContext(Object obj, Object ctx); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/ContextExecutor.java b/spring-ldap/src/main/java/org/springframework/ldap/ContextExecutor.java new file mode 100644 index 00000000..70ac8790 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/ContextExecutor.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface for delegating an actual operation to be performed on an + * DirContext. For searches, use {@link org.springframework.ldap.SearchExecutor} in + * stead. A typical usage of this interface could be e.g.: + * + *

+ * ContextExecutor executor = new ContextExecutor(){
+ *   public Object executeWithContext(DirContext ctx) throws NamingException{
+ *     return ctx.lookup(dn);
+ *   }
+ * };
+ * 
+ * + * @see org.springframework.ldap.LdapTemplate#executeReadOnly(ContextExecutor) + * @see org.springframework.ldap.LdapTemplate#executeReadWrite(ContextExecutor) + * + * @author Mattias Arthursson + */ +public interface ContextExecutor { + /** + * Perform any operation on the context. + * + * @param ctx + * the DirContext to perform the operation on. + * @return any object resulting from the operation - might be null. + * @throws NamingException + * if the operation resulted in one. + */ + public Object executeWithContext(DirContext ctx) throws NamingException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/ContextMapper.java b/spring-ldap/src/main/java/org/springframework/ldap/ContextMapper.java new file mode 100644 index 00000000..a9effe00 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/ContextMapper.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.directory.SearchResult; + +import org.springframework.ldap.support.DefaultDirObjectFactory; +import org.springframework.ldap.support.DirContextAdapter; + +/** + * An interface used by LdapTemplate to map LDAP Contexts to beans. Responsible + * for mapping from LDAP Contexts to beans. When a DirObjectFactory is set on + * the ContextSource, the objects returned from search and + * listBindings operations are automatically transformed to + * DirContext objects (when using the {@link DefaultDirObjectFactory}, you get + * a {@link DirContextAdapter} object). This object will then be passed to the + * ContextMapper implementation for transformation to the desired bean. + *

+ * ContextMapper implementations are typically stateless and thus reusable; they + * are ideal for implementing mapping logic in one place. + *

+ * Alternatively, consider using an {@link AttributesMapper} in stead. + * + * @see LdapTemplate#search(Name, String, + * ContextMapper) + * @see LdapTemplate#listBindings(Name, ContextMapper) + * @see LdapTemplate#lookup(Name, ContextMapper) + * @see AttributesMapper + * @see DefaultDirObjectFactory + * @see DirContextAdapter + * + * @author Mattias Arthursson + */ +public interface ContextMapper { + /** + * Map a single LDAP Context to an object. The supplied Object + * ctx is the object from a single {@link SearchResult}, + * {@link Binding}, or a lookup operation. + * + * @param ctx + * the context to map to an object. + * @return an object built from the data in the context. + */ + public Object mapFromContext(Object ctx); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/ContextSource.java b/spring-ldap/src/main/java/org/springframework/ldap/ContextSource.java new file mode 100644 index 00000000..fa104841 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/ContextSource.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.directory.DirContext; + +import org.springframework.dao.DataAccessException; + +/** + * Interface used to retrieve and authenticate LDAP contexts. + * + * @see org.springframework.ldap.LdapTemplate + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public interface ContextSource { + + /** + * Gets a read-only DirContext. The returned DirContext must be possible to + * perform read-only operations on. + * + * @return A DirContext instance, never null. + * @throws DataAccessException + * if some error occurs creating an DirContext. + */ + public DirContext getReadOnlyContext() throws DataAccessException; + + /** + * Gets a read-write DirContext. + * + * @return A DirContext instance, never null. + * @throws DataAccessException + * if some error occurs creating an DirContext. + */ + public DirContext getReadWriteContext() throws DataAccessException; +} \ No newline at end of file diff --git a/spring-ldap/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java b/spring-ldap/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java new file mode 100644 index 00000000..a7eba9e5 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/DefaultNameClassPairMapper.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; +import javax.naming.NamingException; + +/** + * The default NameClassPairMapper implementation. This implementation simply + * takes the Name string from the supplied NameClassPair and returns it as + * result. + * + * @author Mattias Arthursson + * + */ +public class DefaultNameClassPairMapper implements NameClassPairMapper { + + /** + * Gets the Name from the supplied NameClassPair and returns it as the + * result. + * + * @param nameClassPair + * the NameClassPair to transform. + * @return the Name string from the NameClassPair. + */ + public Object mapFromNameClassPair(NameClassPair nameClassPair) + throws NamingException { + + return nameClassPair.getName(); + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java b/spring-ldap/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java new file mode 100644 index 00000000..6c27b5c7 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/DefaultNamingExceptionTranslator.java @@ -0,0 +1,96 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.CommunicationException; +import javax.naming.ContextNotEmptyException; +import javax.naming.LimitExceededException; +import javax.naming.NameAlreadyBoundException; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import javax.naming.directory.InvalidAttributesException; +import javax.naming.directory.InvalidSearchControlsException; +import javax.naming.directory.InvalidSearchFilterException; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * The default implementation of NamingExceptionTranslator. + * + * @author Mattias Arthursson + */ +public class DefaultNamingExceptionTranslator implements + NamingExceptionTranslator { + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.NamingExceptionTranslator#translate(java.lang.String, + * java.lang.String, java.lang.String, javax.naming.NamingException) + */ + public DataAccessException translate(NamingException namingException) { + + if (namingException instanceof NameNotFoundException) { + return new EntryNotFoundException("Entry not found", + namingException); + } + + if (namingException instanceof InvalidSearchFilterException) { + return new BadLdapGrammarException("Invalid search filter", + namingException); + } + + if (namingException instanceof InvalidSearchControlsException) { + return new InvalidDataAccessApiUsageException( + "Invalid search controls supplied by internal API", + namingException); + } + + if (namingException instanceof NameAlreadyBoundException) { + return new DataIntegrityViolationException("Name already bound", + namingException); + } + + if (namingException instanceof ContextNotEmptyException) { + return new DataIntegrityViolationException( + "The context needs to be empty in order to be removed", + namingException); + } + + if (namingException instanceof InvalidAttributesException) { + return new AttributesIntegrityViolationException( + "Invalid attributes", namingException); + } + + if (namingException instanceof LimitExceededException) { + return new SearchLimitExceededException("Too many objects found", + namingException); + } + + if (namingException instanceof CommunicationException) { + throw new DataRetrievalFailureException( + "Unable to communicate with LDAP server", namingException); + } + + // Fallback - other type of NamingException encountered. + return new UncategorizedLdapException("Operation failed", + namingException); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/DirContextProcessor.java b/spring-ldap/src/main/java/org/springframework/ldap/DirContextProcessor.java new file mode 100644 index 00000000..59f873f5 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/DirContextProcessor.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface to be called in search by LdapTemplate before and after the actual + * search and enumeration traversal. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface DirContextProcessor { + /** + * Perform pre-processing on the supplied DirContext. + * + * @param ctx + * the DirContext instance. + * @throws NamingException + * if thrown by the underlying operation. + */ + public void preProcess(DirContext ctx) throws NamingException; + + /** + * Perform post-processing on the supplied DirContext. + * + * @param ctx + * the DirContext instance. + * @throws NamingException + * if thrown by the underlying operation. + */ + public void postProcess(DirContext ctx) throws NamingException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/EntryNotFoundException.java b/spring-ldap/src/main/java/org/springframework/ldap/EntryNotFoundException.java new file mode 100644 index 00000000..9bd81eb9 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/EntryNotFoundException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataRetrievalFailureException; + +/** + * Represents that an entry could not be found. + * + * @author Mattias Arthursson + */ +public class EntryNotFoundException extends DataRetrievalFailureException { + + private static final long serialVersionUID = -1268390922996332424L; + + public EntryNotFoundException(String msg) { + super(msg); + } + + public EntryNotFoundException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/LdapOperations.java b/spring-ldap/src/main/java/org/springframework/ldap/LdapOperations.java new file mode 100644 index 00000000..8cdc0829 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/LdapOperations.java @@ -0,0 +1,1350 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.directory.Attributes; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; + +/** + * Interface that specifies a basic set of LDAP operations. Implemented by + * LdapTemplate, but it might be a useful option to use this interface in order + * to enhance testability. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public interface LdapOperations { + /** + * Perform a search using a custom context processor. Use this method only + * if especially needed - for the most cases there is an overloaded + * convenience method which calls this one with suitable argments. This + * method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. + * The actual search is delegated to the SearchExecutor and each found + * SearchResult is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * The SearchExecutor to use for performing the actual search. + * @param handler + * The NameClassPairCallbackHandler to which each found entry + * will be passed. + * @param processor + * DirContextProcessor for custom pre- and post-processing. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted as no entries being + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler, + DirContextProcessor processor) throws DataAccessException; + + /** + * Perform a search. Use this method only if especially needed - for the + * most cases there is an overloaded convenience method which calls this one + * with suitable argments. This method handles all the plumbing; getting a + * readonly context; looping through the NamingEnumeration and closing the + * context and enumeration. The actual search is delegated to the + * SearchExecutor and each found SearchResult is passed to the + * CallbackHandler. Any encountered NamingException will be translated using + * the NamingExceptionTranslator. + * + * @param se + * The SearchExecutor to use for performing the actual search. + * @param handler + * The NameClassPairCallbackHandler to which each found entry + * will be passed. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted as no entries being + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform an operation (or series of operations) on a read-only context. + * This method handles the plumbing - getting a DirContext, translating any + * Exceptions and closing the context afterwards. This method is not + * intended for searches; use + * {@link #search(SearchExecutor, NameClassPairCallbackHandler)} or any of + * the overloaded search methods for this. + * + * @param ce + * The ContextExecutor to which the actual operation on the + * DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws DataAccessException + * if the operation resulted in a NamingException. + */ + public Object executeReadOnly(ContextExecutor ce) + throws DataAccessException; + + /** + * Perform an operation (or series of operations) on a read-write context. + * This method handles the plumbing - getting a DirContext, translating any + * exceptions and closing the context afterwards. + * + * @param ce + * The ContextExecutor to which the actual operation on the + * DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws DataAccessException + * if the operation resulted in a NamingException. + */ + public Object executeReadWrite(ContextExecutor ce) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the search. Note + * that if you are using a ContextMapper, the returningObjFlag needs to be + * set to true in the SearchControls. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + */ + public void search(Name base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler); + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler)} + * for details. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + */ + public void search(String base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler); + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the search. Note + * that if you are using a ContextMapper, the returningObjFlag needs to be + * set to true in the SearchControls. The given DirContextProcessor will be + * called before and after the search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @param processor + * The DirContextProcessor to use before and after the search. + */ + public void search(Name base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * SearchScope specified in the supplied SearchControls will be used in the + * search. The given DirContextProcessor will be called before and after the + * search. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @param processor + * The DirContextProcessor to use before and after the search. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler, DirContextProcessor)} + * for details. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @param processor + * The DirContextProcessor to use before and after the search. + */ + public void search(String base, String filter, SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor); + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. Use the specified + * values for search scope and return objects flag. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param returningObjFlag + * Whether the bound object should be returned in search results. + * Must be set to true if a ContextMapper is used. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(Name base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. Use the specified + * search scope and return objects flag in search controls. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param returningObjFlag + * whether the bound object should be returned in search results. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(String base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The default + * Search scope (SearchControls.SUBTREE_SCOPE) will be used and the + * returnObjects flag will be set to false. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(Name base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Each SearchResult is + * supplied to the specified NameClassPairCallbackHandler. The default + * Search scope (SearchControls.SUBTREE_SCOPE) will be used and no the + * returnObjects will be set to false. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param handler + * The NameClassPairCallbackHandler to supply the SearchResults + * to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(String base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Only search for the + * specified attributes. The Attributes in each SearchResult is supplied to + * the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means returning all attributes. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. Only search for the + * specified attributes. The Attributes in each SearchResult is supplied to + * the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means returning all attributes. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * default seach scope will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, AttributesMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified AttributesMapper. The + * default seach scope will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the AttributesMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, AttributesMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. Only + * look for the supplied attributes. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means all attributes. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. Only + * look for the supplied attributes. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param attrs + * The attributes to return, null means all attributes. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param searchScope + * The search scope to set in SearchControls. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * default search scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, ContextMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. The + * default search scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, ContextMapper mapper) + throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified ContextMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. If the returnObjFlag + * is not set in the SearchControls, this method will set it + * automatically, as this is required for the ContextMapper to + * work. + * @param mapper + * The ContextMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper) throws DataAccessException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified AttributesMapper. + * + * @param base + * The base DN where the search should begin. + * @param filter + * The filter to use in the search. + * @param controls + * The SearchControls to use in the search. + * @param mapper + * The AttributesMapper to use for translating each entry. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link NameClassPair} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void list(String base, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link NameClassPair} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void list(Name base, NameClassPairCallbackHandler handler) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects to the + * supplied NameClassPairMapper and return all the returned values as a + * List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link NameClassPair} + * to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(String base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects to the + * supplied NameClassPairMapper and return all the returned values as a + * List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link NameClassPair} + * to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(Name base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(String base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the contexts bound to the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List list(Name base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the specified + * NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link Binding} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void listBindings(final String base, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the specified + * NameClassPairCallbackHandler. + * + * @param base + * The base DN where the list should be performed. + * @param handler + * The NameClassPairCallbackHandler to supply each + * {@link Binding} to. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void listBindings(final Name base, + NameClassPairCallbackHandler handler) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the supplied + * NameClassPairMapper and return all the returned values as a List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link Binding} to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(String base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the supplied + * NameClassPairMapper and return all the returned values as a List. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The NameClassPairMapper to supply each {@link Binding} to. + * @return a List containing the Objects returned from the Mapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(Name base, NameClassPairMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(final String base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base + * The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(final Name base) throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(String base, ContextMapper mapper) + throws DataAccessException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base + * The base DN where the list should be performed. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return a List containing all entries received from the ContextMapper. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public List listBindings(Name base, ContextMapper mapper) + throws DataAccessException; + + /** + * Lookup the supplied DN and return the found object. WARNING: This + * method should only be used if a DirObjectFactory has been specified on + * the ContextFactory. If this is not the case, you will get a new instance + * of the actual DirContext, which is probably not what you want. If, + * however this is what you want, be careful to close the context + * after you finished working with it. + * + * @param dn + * The distinguished name of the object to find. + * @return the found object. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn) throws DataAccessException; + + /** + * Lookup the supplied DN and return the found object. WARNING: This + * method should only be used if a DirObjectFactory has been specified on + * the ContextFactory. If this is not the case, you will get a new instance + * of the actual DirContext, which is probably not what you want. If, + * however this is what you want, be careful to close the context + * after you finished working with it. + * + * @param dn + * The distinguished name of the object to find. + * @return the found object. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn) throws DataAccessException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, String[] attributes, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The AttributesMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, String[] attributes, AttributesMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(Name dn, String[] attributes, ContextMapper mapper) + throws DataAccessException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to a ContextMapper. + * + * @param dn + * The distinguished name to find. + * @param attributes + * The names of the attributes to pass to the mapper. + * @param mapper + * The ContextMapper to use for mapping the found object. + * @return the object returned from the mapper. + * @throws DataAccessException + * if any error occurs. + */ + public Object lookup(String dn, String[] attributes, ContextMapper mapper) + throws DataAccessException; + + /** + * Modify an entry in the LDAP tree using the supplied ModificationItems. + * + * @param dn + * The distinguished name of the node to modify. + * @param mods + * The modifications to perform. + * @throws DataAccessException + * if any error occurs. + */ + public void modifyAttributes(Name dn, ModificationItem[] mods) + throws DataAccessException; + + /** + * Modify an entry in the LDAP tree using the supplied ModificationItems. + * + * @param dn + * The distinguished name of the node to modify. + * @param mods + * The modifications to perform. + * @throws DataAccessException + * if any error occurs. + */ + public void modifyAttributes(String dn, ModificationItem[] mods) + throws DataAccessException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters + * may be null but not both. + * + * @param dn + * The distinguished name to bind the object and attributes to. + * @param obj + * The object to bind, may be null. Typically a DirContext + * implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void bind(Name dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters + * may be null but not both. + * + * @param dn + * The distinguished name to bind the object and attributes to. + * @param obj + * The object to bind, may be null. Typically a DirContext + * implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void bind(String dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children - + * if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn + * The distinguished name of the entry to remove. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(Name dn) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children - + * if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn + * The distinguished name to unbind. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(String dn) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn + * The distinguished name to unbind. + * @param recursive + * Whether to unbind all subcontexts as well. If this parameter + * is false and the entry has children, the + * operation will fail. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(Name dn, boolean recursive) throws DataAccessException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn + * The distinguished name to unbind. + * @param recursive + * Whether to unbind all subcontexts as well. If this parameter + * is false and the entry has children, the + * operation will fail. + * @throws DataAccessException + * if any error occurs. + */ + public void unbind(String dn, boolean recursive) throws DataAccessException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj + * parameter or the attributes parameter (or both). One of + * these parameters may be null but not both. This method assumes that the + * specified context already exists - if not it will fail. + * + * @param dn + * The distinguished name to rebind. + * @param obj + * The object to bind to the DN, may be null. Typically a + * DirContext implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void rebind(Name dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj + * parameter or the attributes parameter (or both). One of + * these parameters may be null but not both. This method assumes that the + * specified context already exists - if not it will fail. + * + * @param dn + * The distinguished name to rebind. + * @param obj + * The object to bind to the DN, may be null. Typically a + * DirContext implementation. + * @param attributes + * The attributes to bind, may be null. + * @throws DataAccessException + * if any error occurs. + */ + public void rebind(String dn, Object obj, Attributes attributes) + throws DataAccessException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn + * The distinguished name of the entry to move; may not be null + * or empty. + * @param newDn + * The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws DataIntegrityViolationException + * if newDn is already bound + * @throws DataAccessException + * if any other error occurs. + */ + public void rename(final Name oldDn, final Name newDn) + throws DataAccessException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn + * The distinguished name of the entry to move; may not be null + * or empty. + * @param newDn + * The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws DataIntegrityViolationException + * if newDn is already bound + * @throws DataAccessException + * if any other error occurs. + */ + public void rename(final String oldDn, final String newDn) + throws DataAccessException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/LdapTemplate.java b/spring-ldap/src/main/java/org/springframework/ldap/LdapTemplate.java new file mode 100644 index 00000000..6c462737 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/LdapTemplate.java @@ -0,0 +1,1379 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.PartialResultException; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import org.apache.commons.lang.Validate; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; + +/** + * Executes core LDAP functionality and helps to avoid common errors, relieving + * the user of the burden of looking up contexts, looping through + * NamingEnumerations and closing contexts. + *

+ * Note for Active Directory (AD) users: AD servers are apparently + * unable to handle referrals automatically, which causes a + * PartialResultException to be thrown whenever a referral is + * encountered in a search. To avoid this, set the + * ignorePartialResultException property to true. + * There is currently no way of manually handling these referrals in the form of + * ReferralException, i.e. either you get the exception (and + * your results are lost) or all referrals are ignored (if the server is unable + * to handle them properly. Neither is there any simple way to get notified that + * a PartialResultException has been ignored (other than in the + * log). + * + * @see org.springframework.ldap.ContextSource + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapTemplate implements LdapOperations, InitializingBean { + + private static final Log log = LogFactory.getLog(LdapTemplate.class); + + private static final int DEFAULT_SEARCH_SCOPE = SearchControls.SUBTREE_SCOPE; + + private static final boolean DONT_RETURN_OBJ_FLAG = false; + + private static final boolean RETURN_OBJ_FLAG = true; + + private static final String[] ALL_ATTRIBUTES = null; + + private ContextSource contextSource; + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + private boolean ignorePartialResultException = false; + + /** + * Constructor for bean usage. + */ + public LdapTemplate() { + } + + /** + * Constructor to setup instance directly. + * + * @param contextSource + * the ContextSource to use. + */ + public LdapTemplate(ContextSource contextSource) { + this.contextSource = contextSource; + } + + /** + * Set the ContextSource. Call this method when the default constructor has + * been used. + * + * @param contextSource + * the ContextSource. + */ + public void setContextSource(ContextSource contextSource) { + this.contextSource = contextSource; + } + + /** + * Specify whether PartialResultException should be ignored + * in searches. AD servers typically have a problem with referrals. Normally + * a referral should be followed automatically, but this does not seem to + * work with AD servers. The problem manifests itself with a a + * PartialResultException being thrown when a referral is + * encountered by the server. Setting this property to true + * presents a workaround to this problem by causing + * PartialResultException to be ignored, so that the search + * method returns normally. Default value of this parameter is + * false. + * + * @param ignore + * true if PartialResultException + * should be ignored in searches, false otherwise. + * Default is false. + */ + public void setIgnorePartialResultException(boolean ignore) { + this.ignorePartialResultException = ignore; + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, boolean, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(Name base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) { + + search(base, filter, getDefaultSearchControls(searchScope, + returningObjFlag, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, boolean, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(String base, String filter, int searchScope, + boolean returningObjFlag, NameClassPairCallbackHandler handler) + throws DataAccessException { + + search(base, filter, getDefaultSearchControls(searchScope, + returningObjFlag, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(final Name base, final String filter, + final SearchControls controls, NameClassPairCallbackHandler handler) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(final String base, final String filter, + final SearchControls controls, NameClassPairCallbackHandler handler) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler, + * org.springframework.ldap.DirContextProcessor) + */ + public void search(final Name base, final String filter, + final SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler, processor); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.NameClassPairCallbackHandler, + * org.springframework.ldap.DirContextProcessor) + */ + public void search(final String base, final String filter, + final SearchControls controls, + NameClassPairCallbackHandler handler, DirContextProcessor processor) { + + // Create a SearchExecutor to perform the search. + SearchExecutor se = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.search(base, filter, controls); + } + }; + + search(se, handler, processor); + } + + /** + * Perform a search operation, such as a search(), list() or listBindings(). + * This method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. It + * also calls the supplied DirContextProcessor before and after the search, + * respectively. This enables custom pre-processing and post-processing, + * like for example when handling paged results or other search controls. + *

+ * The actual list is delegated to the {@link SearchExecutor} and each + * {@link NameClassPair} (this might be a NameClassPair or a subclass + * thereof) is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * the SearchExecutor to use for performing the actual list. + * @param handler + * the NameClassPairCallbackHandler to which each found entry + * will be passed. + * @param processor + * DirContextProcessor for custom pre- and post-processing. May + * be null if no custom processing should take + * place. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler, + DirContextProcessor processor) { + DirContext ctx = contextSource.getReadOnlyContext(); + + NamingEnumeration results = null; + try { + processor.preProcess(ctx); + results = se.executeSearch(ctx); + + while (results.hasMore()) { + NameClassPair result = (NameClassPair) results.next(); + handler.handleNameClassPair(result); + } + processor.postProcess(ctx); + } catch (NameNotFoundException e) { + // The base context was not found, which basically means + // that the search did not return any results. Just clean up and + // exit. + } catch (PartialResultException e) { + // Workaround for AD servers not handling referrals correctly. + if (ignorePartialResultException) { + log.debug("PartialResultException encountered and ignored", e); + } else { + throw getExceptionTranslator().translate(e); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeContextAndNamingEnumeration(ctx, results); + } + } + + /** + * Perform a search operation, such as a search(), list() or listBindings(). + * This method handles all the plumbing; getting a readonly context; looping + * through the NamingEnumeration and closing the context and enumeration. + *

+ * The actual list is delegated to the {@link SearchExecutor} and each + * {@link NameClassPair} (this might be a NameClassPair or a subclass + * thereof) is passed to the CallbackHandler. Any encountered + * NamingException will be translated using the NamingExceptionTranslator. + * + * @param se + * the SearchExecutor to use for performing the actual list. + * @param handler + * the NameClassPairCallbackHandler to which each found entry + * will be passed. + * @throws DataAccessException + * if any error occurs. Note that a NameNotFoundException will + * be ignored. Instead this is interpreted that no entries were + * found. + */ + public void search(SearchExecutor se, NameClassPairCallbackHandler handler) { + search(se, handler, new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(Name base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException { + + search(base, filter, getDefaultSearchControls(DEFAULT_SEARCH_SCOPE, + DONT_RETURN_OBJ_FLAG, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void search(String base, String filter, + NameClassPairCallbackHandler handler) throws DataAccessException { + + search(base, filter, getDefaultSearchControls(DEFAULT_SEARCH_SCOPE, + DONT_RETURN_OBJ_FLAG, ALL_ATTRIBUTES), handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException { + return search(base, filter, getDefaultSearchControls(searchScope, + DONT_RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, int searchScope, + String[] attrs, AttributesMapper mapper) throws DataAccessException { + return search(base, filter, getDefaultSearchControls(searchScope, + DONT_RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, int searchScope, + AttributesMapper mapper) { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, int searchScope, + AttributesMapper mapper) throws DataAccessException { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, AttributesMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, AttributesMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException { + + return search(base, filter, getDefaultSearchControls(searchScope, + RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, java.lang.String[], + * org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, int searchScope, + String[] attrs, ContextMapper mapper) throws DataAccessException { + + return search(base, filter, getDefaultSearchControls(searchScope, + RETURN_OBJ_FLAG, attrs), mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, int, org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, int searchScope, + ContextMapper mapper) { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, int, org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, int searchScope, + ContextMapper mapper) throws DataAccessException { + + return search(base, filter, searchScope, ALL_ATTRIBUTES, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, ContextMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, ContextMapper mapper) + throws DataAccessException { + + return search(base, filter, DEFAULT_SEARCH_SCOPE, mapper); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper) + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper) { + + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper) + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper) { + + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper) + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper) { + + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper) + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper) { + return search(base, filter, controls, mapper, + new NullDirContextProcessor()); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(String base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor) { + AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.AttributesMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(Name base, String filter, SearchControls controls, + AttributesMapper mapper, DirContextProcessor processor) { + AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(java.lang.String, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(String base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor) { + assureReturnObjFlagSet(controls); + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.LdapOperations#search(javax.naming.Name, + * java.lang.String, javax.naming.directory.SearchControls, + * org.springframework.ldap.ContextMapper, + * org.springframework.ldap.DirContextProcessor) + */ + public List search(Name base, String filter, SearchControls controls, + ContextMapper mapper, DirContextProcessor processor) { + assureReturnObjFlagSet(controls); + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + search(base, filter, controls, handler, processor); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String, + * org.springframework.ldap.ListResultCallbackHandler) + */ + public void list(final String base, NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.list(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name, + * org.springframework.ldap.ListResultCallbackHandler) + */ + public void list(final Name base, NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.list(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String, + * org.springframework.ldap.NameClassPairMapper) + */ + public List list(String base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + list(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name, + * org.springframework.ldap.NameClassPairMapper) + */ + public List list(Name base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + list(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(javax.naming.Name) + */ + public List list(final Name base) { + return list(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#list(java.lang.String) + */ + public List list(final String base) { + return list(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void listBindings(final String base, + NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.listBindings(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.NameClassPairCallbackHandler) + */ + public void listBindings(final Name base, + NameClassPairCallbackHandler handler) { + SearchExecutor searchExecutor = new SearchExecutor() { + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException { + return ctx.listBindings(base); + } + }; + + search(searchExecutor, handler); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.NameClassPairMapper) + */ + public List listBindings(String base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + listBindings(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.NameClassPairMapper) + */ + public List listBindings(Name base, NameClassPairMapper mapper) { + CollectingNameClassPairCallbackHandler handler = new MappingCollectingNameClassPairCallbackHandler( + mapper); + listBindings(base, handler); + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String) + */ + public List listBindings(final String base) { + return listBindings(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name) + */ + public List listBindings(final Name base) { + return listBindings(base, new DefaultNameClassPairMapper()); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(java.lang.String, + * org.springframework.ldap.ContextMapper) + */ + public List listBindings(String base, ContextMapper mapper) { + + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + listBindings(base, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#listBindings(javax.naming.Name, + * org.springframework.ldap.ContextMapper) + */ + public List listBindings(Name base, ContextMapper mapper) { + + ContextMapperCallbackHandler handler = new ContextMapperCallbackHandler( + mapper); + listBindings(base, handler); + + return handler.getList(); + } + + /* + * @see org.springframework.ldap.LdapOperations#executeReadOnly(org.springframework.ldap.ContextExecutor) + */ + public Object executeReadOnly(ContextExecutor ce) { + DirContext ctx = contextSource.getReadOnlyContext(); + return executeWithContext(ce, ctx); + } + + /* + * @see org.springframework.ldap.LdapOperations#executeReadWrite(org.springframework.ldap.ContextExecutor) + */ + public Object executeReadWrite(ContextExecutor ce) { + DirContext ctx = contextSource.getReadWriteContext(); + return executeWithContext(ce, ctx); + } + + private Object executeWithContext(ContextExecutor ce, DirContext ctx) { + try { + return ce.executeWithContext(ctx); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeContext(ctx); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name) + */ + public Object lookup(final Name dn) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return ctx.lookup(dn); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String) + */ + public Object lookup(final String dn) throws DataAccessException { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + return ctx.lookup(dn); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final Name dn, final AttributesMapper mapper) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes attributes = ctx.getAttributes(dn); + return mapper.mapFromAttributes(attributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final String dn, final AttributesMapper mapper) + throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes attributes = ctx.getAttributes(dn); + return mapper.mapFromAttributes(attributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * org.springframework.ldap.ContextMapper) + */ + public Object lookup(final Name dn, final ContextMapper mapper) { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Object object = ctx.lookup(dn); + return mapper.mapFromContext(object); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * org.springframework.ldap.ContextMapper) + */ + public Object lookup(final String dn, final ContextMapper mapper) + throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Object object = ctx.lookup(dn); + return mapper.mapFromContext(object); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * java.lang.String[], org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final Name dn, final String[] attributes, + final AttributesMapper mapper) throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + return mapper.mapFromAttributes(filteredAttributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * java.lang.String[], org.springframework.ldap.AttributesMapper) + */ + public Object lookup(final String dn, final String[] attributes, + final AttributesMapper mapper) throws DataAccessException { + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + return mapper.mapFromAttributes(filteredAttributes); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(javax.naming.Name, + * java.lang.String[], org.springframework.ldap.ContextMapper) + */ + public Object lookup(final Name dn, final String[] attributes, + final ContextMapper mapper) throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + DirContextAdapter contextAdapter = new DirContextAdapter( + filteredAttributes, dn); + return mapper.mapFromContext(contextAdapter); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#lookup(java.lang.String, + * java.lang.String[], org.springframework.ldap.ContextMapper) + */ + public Object lookup(final String dn, final String[] attributes, + final ContextMapper mapper) throws DataAccessException { + + return executeReadOnly(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + Attributes filteredAttributes = ctx.getAttributes(dn, + attributes); + DistinguishedName name = new DistinguishedName(dn); + DirContextAdapter contextAdapter = new DirContextAdapter( + filteredAttributes, name); + return mapper.mapFromContext(contextAdapter); + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#modifyAttributes(javax.naming.Name, + * javax.naming.directory.ModificationItem[]) + */ + public void modifyAttributes(final Name dn, final ModificationItem[] mods) { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.modifyAttributes(dn, mods); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#modifyAttributes(java.lang.String, + * javax.naming.directory.ModificationItem[]) + */ + public void modifyAttributes(final String dn, final ModificationItem[] mods) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.modifyAttributes(dn, mods); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#bind(javax.naming.Name, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void bind(final Name dn, final Object obj, + final Attributes attributes) { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.bind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#bind(java.lang.String, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void bind(final String dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.bind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(javax.naming.Name) + */ + public void unbind(final Name dn) { + doUnbind(dn); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(java.lang.String) + */ + public void unbind(final String dn) throws DataAccessException { + doUnbind(dn); + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(javax.naming.Name, + * boolean) + */ + public void unbind(final Name dn, boolean recursive) + throws DataAccessException { + if (!recursive) { + doUnbind(dn); + } else { + doUnbindRecursively(dn); + } + } + + /* + * @see org.springframework.ldap.LdapOperations#unbind(java.lang.String, + * boolean) + */ + public void unbind(final String dn, boolean recursive) + throws DataAccessException { + if (!recursive) { + doUnbind(dn); + } else { + doUnbindRecursively(dn); + } + } + + private void doUnbind(final Name dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.unbind(dn); + return null; + } + }); + } + + private void doUnbind(final String dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.unbind(dn); + return null; + } + }); + } + + private void doUnbindRecursively(final Name dn) throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + deleteRecursively(ctx, new DistinguishedName(dn)); + return null; + } + }); + } + + private void doUnbindRecursively(final String dn) + throws DataAccessException { + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + deleteRecursively(ctx, new DistinguishedName(dn)); + return null; + } + }); + } + + /** + * Delete all subcontexts including the current one recursively. + * + * @param ctx + * The context to use for deleting. + * @param name + * The starting point to delete recursively. + * @throws DataAccessException + * if any error occurs + */ + protected void deleteRecursively(DirContext ctx, DistinguishedName name) + throws DataAccessException { + + NamingEnumeration enumeration = null; + try { + enumeration = ctx.listBindings(name); + while (enumeration.hasMore()) { + Binding binding = (Binding) enumeration.next(); + DistinguishedName childName = new DistinguishedName(binding + .getName()); + childName.prepend((DistinguishedName) name); + deleteRecursively(ctx, childName); + } + ctx.unbind(name); + if (log.isDebugEnabled()) { + log.debug("Entry " + name + " deleted"); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + try { + enumeration.close(); + } catch (Exception e) { + // Never mind this + } + } + } + + /* + * @see org.springframework.ldap.LdapOperations#rebind(javax.naming.Name, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void rebind(final Name dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rebind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rebind(java.lang.String, + * java.lang.Object, javax.naming.directory.Attributes) + */ + public void rebind(final String dn, final Object obj, + final Attributes attributes) throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rebind(dn, obj, attributes); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rename(javax.naming.Name, + * javax.naming.Name) + */ + public void rename(final Name oldDn, final Name newDn) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rename(oldDn, newDn); + return null; + } + }); + } + + /* + * @see org.springframework.ldap.LdapOperations#rename(java.lang.String, + * java.lang.String) + */ + public void rename(final String oldDn, final String newDn) + throws DataAccessException { + + executeReadWrite(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) + throws NamingException { + ctx.rename(oldDn, newDn); + return null; + } + }); + } + + /* + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + if (contextSource == null) { + throw new IllegalArgumentException( + "Property 'contextSource' must be set."); + } + } + + private void closeContextAndNamingEnumeration(DirContext ctx, + NamingEnumeration results) { + + closeNamingEnumeration(results); + closeContext(ctx); + } + + /** + * Close the supplied DirContext if it is not null. Swallow any exceptions, + * as this is only for cleanup. + * + * @param ctx + * the context to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + + /** + * Close the supplied NamingEnumeration if it is not null. Swallow any + * exceptions, as this is only for cleanup. + * + * @param results + * the NamingEnumeration to close. + */ + private void closeNamingEnumeration(NamingEnumeration results) { + if (results != null) { + try { + results.close(); + } catch (Exception e) { + // Never mind this. + } + } + } + + /** + * Get the NamingExceptionTranslator that will be used by this instance. If + * no exceptionTranslator has been set, a default instance will be created. + * + * @return the NamingExceptionTranslator to be used by this instance. + */ + public NamingExceptionTranslator getExceptionTranslator() { + return exceptionTranslator; + } + + /** + * Set the NamingExceptionTranslator to be used by this instance. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + + this.exceptionTranslator = exceptionTranslator; + } + + private SearchControls getDefaultSearchControls(int searchScope, + boolean returningObjFlag, String[] attrs) { + + SearchControls controls = new SearchControls(); + controls.setSearchScope(searchScope); + controls.setReturningObjFlag(returningObjFlag); + controls.setReturningAttributes(attrs); + return controls; + } + + /** + * Make sure the returnObjFlag is set in the supplied SearchControls. Set it + * and log if it's not set. + * + * @param controls + * the SearchControls to check. + */ + private void assureReturnObjFlagSet(SearchControls controls) { + Validate.notNull(controls); + if (!controls.getReturningObjFlag()) { + log.info("The returnObjFlag of supplied SearchControls is not set" + + " but a ContextMapper is used - setting flag to true"); + controls.setReturningObjFlag(true); + } + } + + private final class NullDirContextProcessor implements DirContextProcessor { + public void postProcess(DirContext ctx) throws NamingException { + // Do nothing + } + + public void preProcess(DirContext ctx) throws NamingException { + // Do nothing + } + } + + /** + * A {@link NameClassPairCallbackHandler} that passes the NameClassPairs + * found to a NameClassPairMapper and collects the results in a list. + * + * @author Mattias Arthursson + */ + public class MappingCollectingNameClassPairCallbackHandler extends + CollectingNameClassPairCallbackHandler { + + private NameClassPairMapper mapper; + + public MappingCollectingNameClassPairCallbackHandler( + NameClassPairMapper mapper) { + this.mapper = mapper; + } + + /* + * @see org.springframework.ldap.CollectingNameClassPairCallbackHandler#getObjectFromNameClassPair(javax.naming.NameClassPair) + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + try { + return mapper.mapFromNameClassPair(nameClassPair); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } + + /** + * A CollectingNameClassPairCallbackHandler to wrap an AttributesMapper. + * That is, the found object is extracted from the {@link Attributes} of + * each {@link SearchResult}, and then passed to the specified + * AttributesMapper for translation. This class needs to be nested, since we + * want to be able to get hold of the exception translator of this instance. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + public class AttributesMapperCallbackHandler extends + CollectingNameClassPairCallbackHandler { + private AttributesMapper mapper; + + public AttributesMapperCallbackHandler(AttributesMapper mapper) { + this.mapper = mapper; + } + + /** + * Cast the NameClassPair to a SearchResult and pass its attributes to + * the AttributesMapper. + * + * @param nameClassPair + * a SearchResult instance. + * @return the Object returned from the Mapper. + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + SearchResult searchResult = (SearchResult) nameClassPair; + Attributes attributes = searchResult.getAttributes(); + try { + return mapper.mapFromAttributes(attributes); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } + + /** + * A CollectingNameClassPairCallbackHandler to wrap a ContextMapper. That + * is, the found object is extracted from each {@link Binding}, and then + * passed to the specified ContextMapper for translation. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ + public class ContextMapperCallbackHandler extends + CollectingNameClassPairCallbackHandler { + private ContextMapper mapper; + + public ContextMapperCallbackHandler(ContextMapper mapper) { + this.mapper = mapper; + } + + /** + * Cast the NameClassPair to a {@link Binding} and pass its attributes + * to the ContextMapper. + * + * @param nameClassPair + * a SearchResult instance. + * @return the Object returned from the Mapper. + */ + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + Binding binding = (Binding) nameClassPair; + Object object = binding.getObject(); + if (object == null) { + throw new EntryNotFoundException( + "SearchResult did not contain any object."); + } + return mapper.mapFromContext(object); + } + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java b/spring-ldap/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java new file mode 100644 index 00000000..0698a9c6 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/NameClassPairCallbackHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; + +/** + * Callback interface used by LdapTemplate's search, list and listBindings + * methods. Implementations of this interface perform the actual work of + * extracting results from a single NameClassPair (a NameClassPair, + * Binding or SearchResult depending on the search operation) returned by an + * LDAP seach operation, such as search(), list(), and listBindings(). + * + * @author Mattias Arthursson + */ +public interface NameClassPairCallbackHandler { + /** + * Handle one entry. This method will be called once for each entry returned + * by a search or list. + * + * @param nameClassPair + * the NameClassPair returned from the NamingEnumeration. + */ + public void handleNameClassPair(NameClassPair nameClassPair); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/NameClassPairMapper.java b/spring-ldap/src/main/java/org/springframework/ldap/NameClassPairMapper.java new file mode 100644 index 00000000..acf8cd14 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/NameClassPairMapper.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NameClassPair; +import javax.naming.NamingException; + +/** + * Responsible for mapping NameClassPair objects to beans. + * + * @author Mattias Arthursson + */ +public interface NameClassPairMapper { + /** + * Map NameClassPair to an Object. The supplied NameClassPair is one of the + * results from a search operation (search, list or listBindings). Depending + * on which search operation is being performed, the NameClassPair might be + * a SearchResult, Binding or NameClassPair. + * + * @param nameClassPair + * NameClassPair from a search operation. + * @return and Object built from the NameClassPair. + * @throws NamingException + * if one is encountered in the operation. + */ + public Object mapFromNameClassPair(NameClassPair nameClassPair) + throws NamingException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java b/spring-ldap/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java new file mode 100644 index 00000000..cd6e7a4c --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/NamingExceptionTranslator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.NamingException; + +import org.springframework.dao.DataAccessException; + +/** + * Interface to be implemented by classes that can translate between + * NamingExceptions and DataAccessExceptions. + * + * @author Mattias Arthursson + * + */ +public interface NamingExceptionTranslator { + /** + * Translate the given NamingException into a generic data access exception. + * @param namingException + * the offending NamingException. + * + * @return the DataAccessException to throw. + */ + public DataAccessException translate(NamingException namingException); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/SearchExecutor.java b/spring-ldap/src/main/java/org/springframework/ldap/SearchExecutor.java new file mode 100644 index 00000000..34b474b5 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/SearchExecutor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap; + +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +/** + * Interface for delegating an actual search operation. The typical + * implementation of executeSearch would be something like: + * + *

+ * SearchExecutor executor = new SearchExecutor(){
+ *   public NamingEnumeration executeSearch(DirContext ctx) throws NamingException{
+ *     return ctx.search(dn, filter, searchControls);
+ *   }
+ * }
+ * 
+ * + * @see org.springframework.ldap.LdapTemplate#search(SearchExecutor, + * NameClassPairCallbackHandler) + * + * @author Mattias Arthursson + */ +public interface SearchExecutor { + /** + * Execute the actual search. + * + * @param ctx + * the DirContext on which to work. + * @return the NamingEnumeration resulting from the search operation. + * @throws NamingException + * if the search results in one. + */ + public NamingEnumeration executeSearch(DirContext ctx) + throws NamingException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/SearchLimitExceededException.java b/spring-ldap/src/main/java/org/springframework/ldap/SearchLimitExceededException.java new file mode 100644 index 00000000..49806334 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/SearchLimitExceededException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.DataRetrievalFailureException; + +/** + * Indicates that the search limit was exceeded in a search. + * + * @author Mattias Arthursson + * + */ +public class SearchLimitExceededException extends DataRetrievalFailureException { + private static final long serialVersionUID = 6899885947075235580L; + + public SearchLimitExceededException(String msg) { + super(msg); + } + + public SearchLimitExceededException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/UncategorizedLdapException.java b/spring-ldap/src/main/java/org/springframework/ldap/UncategorizedLdapException.java new file mode 100644 index 00000000..2423a3b7 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/UncategorizedLdapException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import org.springframework.dao.UncategorizedDataAccessException; + +/** + * Indicates that an unknown NamingException has occurred. + * + * @author Mattias Arthursson + */ +public class UncategorizedLdapException extends + UncategorizedDataAccessException { + + private static final long serialVersionUID = -3319936235493869823L; + + public UncategorizedLdapException(String msg, Throwable cause) { + super(msg, cause); + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/package.html b/spring-ldap/src/main/java/org/springframework/ldap/package.html new file mode 100644 index 00000000..f160a4a2 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/package.html @@ -0,0 +1,3 @@ + +The core package of the Spring-LDAP library. + \ No newline at end of file diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/AbstractContextSource.java b/spring-ldap/src/main/java/org/springframework/ldap/support/AbstractContextSource.java new file mode 100644 index 00000000..d972ebe1 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/AbstractContextSource.java @@ -0,0 +1,459 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.util.Hashtable; +import java.util.Map; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.JdkVersion; +import org.springframework.ldap.AuthenticationSource; +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; + +/** + * Abstract implementation of the ContextSource interface. By default, returns + * an authenticated DirContext implementation for both read-only and read-write + * operations. To have an anonymous environment created for read-only + * operations, set the anonymousReadOnly property to true. + *

+ * Implementing classes need to implement + * {@link #getDirContextInstance(Hashtable)} to create a DirContext instance of + * the desired type. + *

+ * If an AuthenticationSource is set, this will be used for getting user name + * and password for each new connection, otherwise a default one will be created + * using the specified userName and password. + *

+ * Note: When using implementations of this class outside of a Spring + * Context it is necessary to call {@link #afterPropertiesSet()} when all + * properties are set, in order to finish up initialization. + * + * @see org.springframework.ldap.LdapTemplate + * @see org.springframework.ldap.support.DefaultDirObjectFactory + * @see org.springframework.ldap.support.LdapContextSource + * @see org.springframework.ldap.support.DirContextSource + * + * @author Mattias Arthursson + * @author Adam Skogman + * @author Ulrik Sandberg + */ +public abstract class AbstractContextSource implements ContextSource, + InitializingBean { + + private static final Class DEFAULT_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory.class; + + private static final Class DEFAULT_DIR_OBJECT_FACTORY = DefaultDirObjectFactory.class; + + private Class dirObjectFactory = DEFAULT_DIR_OBJECT_FACTORY; + + private Class contextFactory = DEFAULT_CONTEXT_FACTORY; + + private DistinguishedName base; + + protected String userName = ""; + + protected String password = ""; + + private String[] urls; + + private boolean pooled = true; + + private Hashtable baseEnv = new Hashtable(); + + private Hashtable anonymousEnv; + + private AuthenticationSource authenticationSource; + + private boolean cacheEnvironmentProperties = true; + + private boolean anonymousReadOnly = false; + + private NamingExceptionTranslator exceptionTranslator = new DefaultNamingExceptionTranslator(); + + private static final Log log = LogFactory.getLog(LdapContextSource.class); + + public static final String SUN_LDAP_POOLING_FLAG = "com.sun.jndi.ldap.connect.pool"; + + private static final String JDK_142 = "1.4.2"; + + public DirContext getReadOnlyContext() { + if (!anonymousReadOnly) { + return createContext(getAuthenticatedEnv()); + } else { + return createContext(getAnonymousEnv()); + } + } + + public DirContext getReadWriteContext() { + return createContext(getAuthenticatedEnv()); + } + + /** + * Default implementation of setting the environment up to be authenticated. + * Override in subclass if necessary. This is needed for Active Directory + * connectivity, for example. + * + * @param env + * the environment to modify. + */ + protected void setupAuthenticatedEnvironment(Hashtable env) { + env + .put(Context.SECURITY_PRINCIPAL, authenticationSource + .getPrincipal()); + log.debug("Principal: '" + userName + "'"); + env.put(Context.SECURITY_CREDENTIALS, authenticationSource + .getCredentials()); + } + + /** + * Close the context and swallow any exceptions. + * + * @param ctx + * the DirContext to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + } + } + } + + /** + * Assemble a valid url String from all registered urls to add as + * PROVIDER_URL to the environment. + * + * @param ldapUrls + * all individual url Strings. + * @return the full url String + */ + protected String assembleProviderUrlString(String[] ldapUrls) { + StringBuffer providerUrlBuffer = new StringBuffer(1024); + for (int i = 0; i < ldapUrls.length; i++) { + providerUrlBuffer.append(ldapUrls[i]); + if (base != null) { + if (!ldapUrls[i].endsWith("/")) { + providerUrlBuffer.append("/"); + } + providerUrlBuffer.append(base.toUrl()); + } + providerUrlBuffer.append(' '); + } + return providerUrlBuffer.toString().trim(); + } + + /** + * Set the base suffix from which all operations should origin. If a base + * suffix is set, you will not have to (and, indeed, should not) specify the + * full distinguished names in the operations performed. + * + * @param base + * the base suffix. + */ + public void setBase(String base) { + this.base = new DistinguishedName(base); + } + + /** + * Create a DirContext using the supplied environment. + * + * @param environment + * the Ldap environment to use when creating the DirContext. + * @return a new DirContext implpementation initialized with the supplied + * environment. + */ + DirContext createContext(Hashtable environment) { + DirContext ctx = null; + + try { + ctx = getDirContextInstance(environment); + + if (log.isInfoEnabled()) { + Hashtable ctxEnv = ctx.getEnvironment(); + String ldapUrl = (String) ctxEnv.get(Context.PROVIDER_URL); + log.debug("Got Ldap context on server '" + ldapUrl + "'"); + } + + return ctx; + } catch (NamingException e) { + closeContext(ctx); + throw getExceptionTranslator().translate(e); + } + } + + /** + * Set the context factory. Default is com.sun.jndi.ldap.LdapCtxFactory. + * + * @param contextFactory + * the context factory used when creating Contexts. + */ + public void setContextFactory(Class contextFactory) { + this.contextFactory = contextFactory; + } + + /** + * Set the DirObjectFactory to use. Default is + * {@link DefaultDirObjectFactory}. The specified class needs to be an + * implementation of javax.naming.spi.DirObjectFactory. Note: Setting + * this value to null may have cause connection leaks when using + * ContextMapper methods in LdapTemplate. + * + * @param dirObjectFactory + * the DirObjectFactory to be used. Null means that no + * DirObjectFactory will be used. + */ + public void setDirObjectFactory(Class dirObjectFactory) { + this.dirObjectFactory = dirObjectFactory; + } + + /** + * Checks that all necessary data is set and that there is no compatibility + * issues, after which the instance is initialized. Note that you need to + * call this method explicitly after setting all desired properties if using + * the class outside of a Spring Context. + */ + public void afterPropertiesSet() throws Exception { + if (ArrayUtils.isEmpty(urls)) { + throw new IllegalArgumentException( + "At least one server url must be set"); + } + + if (base != null && getJdkVersion().compareTo(JDK_142) < 0) { + throw new IllegalArgumentException( + "Base path is not supported for JDK versions < 1.4.2"); + } + + if (authenticationSource == null) { + log.debug("AuthenticationSource not set - " + + "using default implementation"); + if (StringUtils.isBlank(userName)) { + log + .warn("Property 'userName' not set - " + + "anonymous context will be used for read-write operations"); + } else if (StringUtils.isBlank(password)) { + log.warn("Property 'password' not set - " + + "blank password will be used"); + } + authenticationSource = new SimpleAuthenticationSource(); + } + + if (cacheEnvironmentProperties) { + anonymousEnv = setupAnonymousEnv(); + } + } + + private Hashtable setupAnonymousEnv() { + if (pooled) { + baseEnv.put(SUN_LDAP_POOLING_FLAG, "true"); + log.debug("Using LDAP pooling."); + } else { + log.debug("Not using LDAP pooling"); + } + + Hashtable env = new Hashtable(baseEnv); + + env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory.getName()); + env.put(Context.PROVIDER_URL, assembleProviderUrlString(urls)); + + if (dirObjectFactory != null) { + env.put(Context.OBJECT_FACTORIES, dirObjectFactory.getName()); + } + + if (base != null) { + // Save the base path for use in the DefaultDirObjectFactory. + env.put(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY, base); + } + + log.debug("Trying provider Urls: " + assembleProviderUrlString(urls)); + + return env; + } + + /** + * Set the password (credentials) to use for getting authenticated contexts. + * + * @param password + * the password. + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Set the user name (principal) to use for getting authenticated contexts. + * + * @param userName + * the user name. + */ + public void setUserName(String userName) { + this.userName = userName; + } + + /** + * Set the urls of the LDAP servers. Use this method if several servers are + * required. + * + * @param urls + * the urls of all servers. + */ + public void setUrls(String[] urls) { + this.urls = urls; + } + + /** + * Set the url of the LDAP server. Utility method if only one server is + * used. + * + * @param url + * the url of the LDAP server. + */ + public void setUrl(String url) { + this.urls = new String[] { url }; + } + + /** + * Set whether the pooling flag should be set. Default is true. + * + * @param pooled + * whether Contexts should be pooled. + */ + public void setPooled(boolean pooled) { + this.pooled = pooled; + } + + /** + * If any custom environment properties are needed, these can be set using + * this method. + * + * @param baseEnvironmentProperties + */ + public void setBaseEnvironmentProperties(Map baseEnvironmentProperties) { + this.baseEnv = new Hashtable(baseEnvironmentProperties); + } + + String getJdkVersion() { + return JdkVersion.getJavaVersion(); + } + + protected Hashtable getAnonymousEnv() { + if (cacheEnvironmentProperties) { + return anonymousEnv; + } else { + return setupAnonymousEnv(); + } + } + + protected Hashtable getAuthenticatedEnv() { + // The authenticated environment should always be rebuilt. + Hashtable env = new Hashtable(getAnonymousEnv()); + setupAuthenticatedEnvironment(env); + return env; + } + + public void setAuthenticationSource( + AuthenticationSource authenticationProvider) { + this.authenticationSource = authenticationProvider; + } + + /** + * Set whether environment properties should be cached between requsts for + * anonymous environment. Default is true; setting this property to false + * causes the environment Hashmap to be rebuilt from the current property + * settings of this instance between each request for an anonymous + * environment. + * + * @param cacheEnvironmentProperties + * true causes that the anonymous environment properties should + * be cached, false causes the Hashmap to be rebuilt for each + * request. + */ + public void setCacheEnvironmentProperties(boolean cacheEnvironmentProperties) { + this.cacheEnvironmentProperties = cacheEnvironmentProperties; + } + + /** + * Set whether an anonymous environment should be used for read-only + * operations. Default is false. + * + * @param anonymousReadOnly + * true if and anonymous environment should be + * used for read-only operations, false otherwise. + */ + public void setAnonymousReadOnly(boolean anonymousReadOnly) { + this.anonymousReadOnly = anonymousReadOnly; + } + + /** + * Set the NamingExceptionTranslator to be used by this instance. By + * default, a {@link DefaultNamingExceptionTranslator} will be used. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } + + /** + * Get the NamingExceptionTranslator used by this instance. + * + * @return the NamingExceptionTranslator. + */ + public NamingExceptionTranslator getExceptionTranslator() { + return exceptionTranslator; + } + + /** + * Implement in subclass to create a DirContext of the desired type (e.g. + * InitialDirContext or InitialLdapContext). + * + * @param environment + * the environment to use when creating the instance. + * @return a new DirContext instance. + * @throws NamingException + * if one is encountered when creating the instance. + */ + protected abstract DirContext getDirContextInstance(Hashtable environment) + throws NamingException; + + class SimpleAuthenticationSource implements AuthenticationSource { + + public String getPrincipal() { + return userName; + } + + public String getCredentials() { + return password; + } + + } + + protected String[] getUrls() { + return urls; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java b/spring-ldap/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java new file mode 100644 index 00000000..e24a88bd --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/AggregateDirContextProcessor.java @@ -0,0 +1,72 @@ +package org.springframework.ldap.support; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.DirContextProcessor; + +/** + * Manages a sequence of DirContextProcessor instances. Applies + * {@link #preProcess(DirContext)} and {@link #postProcess(DirContext)} + * respectively in sequence on the managed objects. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class AggregateDirContextProcessor implements DirContextProcessor { + + private List dirContextProcessors = new LinkedList(); + + /** + * Add the supplied DirContextProcessor to the list of managed objects. + * + * @param processor + * the DirContextpProcessor to add. + */ + public void addDirContextProcessor(DirContextProcessor processor) { + dirContextProcessors.add(processor); + } + + /** + * Get the list of managed DirContextProcessors. + * + * @return the managed list of {@link DirContextProcessor} instances. + */ + public List getDirContextProcessors() { + return dirContextProcessors; + } + + /** + * Set the list of managed {@link DirContextProcessor} instances. + * + * @param dirContextProcessors + * the list of {@link DirContextProcessor} instances to set. + */ + public void setDirContextProcessors(List dirContextProcessors) { + this.dirContextProcessors = dirContextProcessors; + } + + /* + * @see org.springframework.ldap.DirContextProcessor#preProcess(javax.naming.directory.DirContext) + */ + public void preProcess(DirContext ctx) throws NamingException { + for (Iterator iter = dirContextProcessors.iterator(); iter.hasNext();) { + DirContextProcessor processor = (DirContextProcessor) iter.next(); + processor.preProcess(ctx); + } + } + + /* + * @see org.springframework.ldap.DirContextProcessor#postProcess(javax.naming.directory.DirContext) + */ + public void postProcess(DirContext ctx) throws NamingException { + for (Iterator iter = dirContextProcessors.iterator(); iter.hasNext();) { + DirContextProcessor processor = (DirContextProcessor) iter.next(); + processor.postProcess(ctx); + } + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java b/spring-ldap/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java new file mode 100644 index 00000000..9d0a7fa1 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/AttributeModificationsAware.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import javax.naming.directory.ModificationItem; + +/** + * Indicates that the implementor is capable of keeping track of any attribute + * modifications and return them as ModificationItems. + * + * @author Mattias Arthursson + * + */ +public interface AttributeModificationsAware { + + /** + * Creates an array of which attributes have been changed or added or removed. + * + * @return an array of modification items + */ + public ModificationItem[] getModificationItems(); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java b/spring-ldap/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java new file mode 100644 index 00000000..8f017beb --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/CountNameClassPairCallbackHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.NameClassPair; + +import org.springframework.ldap.NameClassPairCallbackHandler; + +/** + * A NameClassPairCallbackHandler for counting all returned entries. + * + * @author Mattias Arthursson + * + */ +public class CountNameClassPairCallbackHandler implements + NameClassPairCallbackHandler { + + private int noOfRows = 0; + + /** + * Get the number of rows that was returned by the search. + * + * @return the number of entries that have been handled. + */ + public int getNoOfRows() { + return noOfRows; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.SearchResultCallbackHandler#handleSearchResult(javax.naming.directory.SearchResult) + */ + public void handleNameClassPair(NameClassPair nameClassPair) { + noOfRows++; + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java new file mode 100644 index 00000000..f860cbfb --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDirObjectFactory.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.directory.Attributes; +import javax.naming.spi.DirObjectFactory; + +/** + * Default implementation of the DirObjectFactory interface. Creates a + * DirContextAdapter from the supplied arguments. + * + * @author Mattias Arthursson + */ +public class DefaultDirObjectFactory implements DirObjectFactory { + /** + * Key to use in the ContextSource implementation to store the value of the + * base path suffix, if any, in the Ldap Environment. + */ + public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path"; + + /* + * (non-Javadoc) + * + * @see javax.naming.spi.DirObjectFactory#getObjectInstance(java.lang.Object, + * javax.naming.Name, javax.naming.Context, java.util.Hashtable, + * javax.naming.directory.Attributes) + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, + Hashtable environment, Attributes attrs) throws Exception { + + try { + String nameInNamespace = null; + if (nameCtx != null) { + nameInNamespace = nameCtx.getNameInNamespace(); + } else { + nameInNamespace = ""; + } + DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, + name, new DistinguishedName(nameInNamespace)); + dirContextAdapter.setUpdateMode(true); + + return dirContextAdapter; + } finally { + // It seems that the object supplied to the obj parameter is a + // DirContext instance with reference to the same Ldap connection as + // the original context. Since it is not the same instance (that's + // the nameCtx parameter) this one really needs to be closed in + // order to correctly clean up and return the connection to the pool + // when we're finished with the surrounding operation. + if (obj instanceof Context) { + + Context ctx = (Context) obj; + try { + ctx.close(); + } catch (Exception e) { + // Never mind this + } + + } + } + } + + /* + * (non-Javadoc) + * + * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, + * javax.naming.Name, javax.naming.Context, java.util.Hashtable) + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, + Hashtable environment) throws Exception { + return null; + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java new file mode 100644 index 00000000..e0ccbdc7 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DefaultDnParserFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.io.StringReader; + +/** + * A factory for creating DnParser instances. The actual implementation of + * DnParser is generated using javacc and should not be constructed directly. + * + * @author Mattias Arthursson + * + */ +public class DefaultDnParserFactory { + /** + * Create a new DnParser instance. + * + * @param string + * the DN String to be parsed. + * @return a new DnParser instance for parsing the supplied DN string. + */ + public static DnParser createDnParser(String string) { + return new DnParserImpl(new StringReader(string)); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextAdapter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextAdapter.java new file mode 100644 index 00000000..f4fcd6f7 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextAdapter.java @@ -0,0 +1,1271 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.NameParser; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.DefaultNamingExceptionTranslator; +import org.springframework.ldap.NamingExceptionTranslator; + +/** + * Implements the interesting methods of the DirContext interface. In particular + * it contains utility methods for getting and setting Attributes. Using the + * {@link org.springframework.ldap.support.DefaultDirObjectFactory} in your + * ContextSource you may receive instances of this class from searches and + * lookups. This can be particularly useful when updating data, since this class + * implements + * {@link org.springframework.ldap.support.AttributeModificationsAware}, + * providing a {@link #getModificationItems()} method. + * + * @author Magnus Robertsson + * @author Andreas Ronge + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DirContextAdapter implements DirContextOperations { + + private static final boolean ORDER_DOESNT_MATTER = false; + + private static Log log = LogFactory.getLog(DirContextAdapter.class); + + private final Attributes attrs; + + private DistinguishedName dn; + + private DistinguishedName base; + + private boolean updateMode = false; + + private Attributes updatedAttrs; + + private NamingExceptionTranslator exceptionTranslator; + + /** + * Default constructor. + */ + public DirContextAdapter() { + this(null, null, null); + } + + /** + * Create a new adapter from the supplied dn. + * + * @param dn + * the dn. + */ + public DirContextAdapter(Name dn) { + this(null, dn); + } + + /** + * Create a new adapter from the supplied attributes and dn. + * + * @param attrs + * the attributes. + * @param dn + * the dn. + */ + public DirContextAdapter(Attributes attrs, Name dn) { + this(attrs, dn, null); + } + + /** + * Create a new adapter from the supplied attributes, dn, and base. + * + * @param attrs + * the attributes. + * @param dn + * the dn. + * @param base + * the base name. + */ + public DirContextAdapter(Attributes attrs, Name dn, Name base) { + if (attrs != null) { + this.attrs = attrs; + } else { + this.attrs = new BasicAttributes(true); + } + if (dn != null) { + this.dn = new DistinguishedName(dn.toString()); + } else { + this.dn = new DistinguishedName(); + } + if (base != null) { + this.base = new DistinguishedName(base.toString()); + } else { + this.base = new DistinguishedName(); + } + } + + /** + * Constructor for cloning an existing adapter. + * + * @param master + * The adapter to be copied. + */ + protected DirContextAdapter(DirContextAdapter master) { + this.attrs = (Attributes) master.attrs.clone(); + this.dn = master.dn; + this.updatedAttrs = (Attributes) master.updatedAttrs.clone(); + this.updateMode = master.updateMode; + } + + /** + * Sets the update mode. The update mode should be false for + * a new entry and true for an existing entry that is being + * updated. + * + * @param mode + * Update mode. + */ + protected void setUpdateMode(boolean mode) { + this.updateMode = mode; + if (updateMode) { + updatedAttrs = new BasicAttributes(true); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#isUpdateMode() + */ + public boolean isUpdateMode() { + return updateMode; + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getNamesOfModifiedAttributes() + */ + public String[] getNamesOfModifiedAttributes() { + + List tmpList = new ArrayList(); + + NamingEnumeration attributesEnumeration; + if (isUpdateMode()) { + attributesEnumeration = updatedAttrs.getAll(); + } else { + attributesEnumeration = attrs.getAll(); + } + + try { + while (attributesEnumeration.hasMore()) { + Attribute oneAttribute = (Attribute) attributesEnumeration + .next(); + tmpList.add(oneAttribute.getID()); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + return (String[]) tmpList.toArray(new String[0]); + } + + private void closeNamingEnumeration(NamingEnumeration enumeration) { + try { + if (enumeration != null) { + enumeration.close(); + } + } catch (NamingException e) { + // Never mind this + } + } + + /* + * @see org.springframework.ldap.support.AttributeModificationsAware#getModificationItems() + */ + public ModificationItem[] getModificationItems() { + if (!updateMode) { + return new ModificationItem[0]; + } + + List tmpList = new LinkedList(); + NamingEnumeration attributesEnumeration = null; + try { + attributesEnumeration = updatedAttrs.getAll(); + + // find attributes that have been changed, removed or added + while (attributesEnumeration.hasMore()) { + Attribute oneAttr = (Attribute) attributesEnumeration.next(); + + collectModifications(oneAttr, tmpList); + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + if (log.isDebugEnabled()) { + log.debug("Number of modifications:" + tmpList.size()); + } + + return (ModificationItem[]) tmpList + .toArray(new ModificationItem[tmpList.size()]); + } + + /** + * Collect all modifications for the changed attribute. If no changes have + * been made, return immediately. If modifications have been made, and the + * original size as well as the updated size of the attribute is 1, replace + * the attribute. If the size of the updated attribute is 0, remove the + * attribute. Otherwise, the attribute is a multi-value attribute, in which + * case all modifications to the original value (removals and additions) + * will be collected individually. + * + * @param changedAttr + * the value of the changed attribute. + * @param modificationList + * the list in which to add the modifications. + * @throws NamingException + * if thrown by called Attribute methods. + */ + private void collectModifications(Attribute changedAttr, + List modificationList) throws NamingException { + Attribute currentAttribute = attrs.get(changedAttr.getID()); + + if (changedAttr.equals(currentAttribute)) { + // No changes + return; + } else if (currentAttribute != null && currentAttribute.size() == 1 + && changedAttr.size() == 1) { + // Replace single-vale attribute. + modificationList.add(new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, changedAttr)); + } else if (changedAttr.size() == 0) { + // Attribute has been removed. + modificationList.add(new ModificationItem( + DirContext.REMOVE_ATTRIBUTE, changedAttr)); + } else { + // Collect all modifications to attribute individually (this also + // covers additions to a previously non-existant attribute). + Collection oldValues = new LinkedList(); + Collection newValues = new LinkedList(); + + collectAttributeValues(oldValues, currentAttribute); + collectAttributeValues(newValues, changedAttr); + Collection myModifications = new LinkedList(); + + Collection addedValues = CollectionUtils.subtract(newValues, + oldValues); + Collection removedValues = CollectionUtils.subtract(oldValues, + newValues); + + collectModifications(DirContext.ADD_ATTRIBUTE, changedAttr, + addedValues, myModifications); + collectModifications(DirContext.REMOVE_ATTRIBUTE, changedAttr, + removedValues, myModifications); + + if (myModifications.isEmpty()) { + // This means that the attributes are not equal, but the + // actual values are the same - thus the order must have + // changed. This should result in a REPLACE_ATTRIBUTE operation. + myModifications.add(new ModificationItem( + DirContext.REPLACE_ATTRIBUTE, changedAttr)); + } + + modificationList.addAll(myModifications); + } + } + + private void collectModifications(int modificationType, Attribute attr, + Collection values, Collection c) { + if (values.size() > 0) { + BasicAttribute modificationAttribute = new BasicAttribute(attr + .getID()); + for (Iterator iter = values.iterator(); iter.hasNext();) { + modificationAttribute.add(iter.next()); + } + c + .add(new ModificationItem(modificationType, + modificationAttribute)); + } + } + + private void collectAttributeValues(Collection valueCollection, + Attribute attribute) throws NamingException { + + if (attribute == null) { + return; + } + + NamingEnumeration attributeValues = attribute.getAll(); + while (attributeValues.hasMoreElements()) { + Object value = (Object) attributeValues.nextElement(); + valueCollection.add(value); + } + } + + /** + * Compare the existing attribute name with the value in + * value. + *

+ * Also handles the case where the value has been reset to the original + * value after a previous change. For example, changing a to + * b and then back to a again must result in + * this method returning true so the first change can be + * overwritten with the latest change. TODO Do the null checks on the value + * instead + * + * @param name + * Name of the original attribute. + * @param value + * Value to check if it has been changed. + * @return true if there has been a change compared to original attribute, + * or a previous update + */ + private boolean isChanged(String name, Object value) { + Attribute orig = attrs.get(name); + Attribute prev = updatedAttrs.get(name); + + // FALSE if both are null it is not changed + // TODO Also include prev in null check + if (orig == null && value == null) { + return false; + } + + // TRUE if existing value is null or does not contain one value + if (orig == null || orig.size() != 1) { + return true; + } + + // TRUE if existing value is not null and the new one is null + if (orig != null && value == null) { + return true; + } + + // TRUE if we can't access the value + Object obj = null; + try { + obj = orig.get(0); + } catch (NamingException e) { + return true; + } + + if (prev == null) { + // TRUE if the value is not equal + return !value.equals(obj); + } else { + // TRUE if we can't access the value + Object prevObj = null; + try { + prevObj = prev.get(0); + } catch (NamingException e) { + return true; + } + // TRUE if the value is not equal + return !value.equals(obj) || !value.equals(prevObj); + } + } + + /** + * returns true if the attribute is empty. It is empty if a == null, size == + * 0 or get() == null or an exception if thrown when accessing the get + * method + */ + private boolean isEmptyAttribute(Attribute a) { + try { + return (a == null || a.size() == 0 || a.get() == null); + } catch (NamingException e) { + return true; + } + } + + /** + * Compare the existing attribute name with the values on the + * array values. The order of the array must be the same + * order as the existing multivalued attribute. + *

+ * Also handles the case where the values have been reset to the original + * values after a previous change. For example, changing + * [a,b,c] to [a,b] and then back to + * [a,b,c] again must result in this method returning + * true so the first change can be overwritten with the + * latest change. + * + * @param name + * Name of the original multi-valued attribute. + * @param values + * Array of values to check if they have been changed. + * @return true if there has been a change compared to original attribute, + * or a previous update + */ + private boolean isChanged(String name, Object[] values, boolean orderMatters) { + + Attribute orig = attrs.get(name); + Attribute prev = updatedAttrs.get(name); + + // values == null and values.length == 0 is treated the same way + boolean emptyNewValue = (values == null || values.length == 0); + + // Setting to empty --------------------- + if (emptyNewValue) { + // FALSE: if both are null, it is not changed (both don't exist) + // TRUE: if new value is null and old value exists (should be + // removed) + // TODO Also include prev in null check + // TODO Also check if there is a single null element + if (orig != null) { + return true; + } + return false; + } + + // NOT setting to empty ------------------- + + // TRUE if existing value is null + if (orig == null) { + return true; + } + + // TRUE if different length compared to original attributes + if (orig.size() != values.length) { + return true; + } + + // TRUE if different length compared to previously updated attributes + if (prev != null && prev.size() != values.length) { + return true; + } + + // Check contents of arrays + + // Order DOES matter, e.g. first names + try { + for (int i = 0; i < orig.size(); i++) { + Object obj = orig.get(i); + // TRUE if one value is not equal + if (!(obj instanceof String)) { + return true; + } + if (orderMatters) { + // check only the string with same index + if (!values[i].equals(obj)) { + return true; + } + } else { + // check all strings + if (!ArrayUtils.contains(values, obj)) { + return true; + } + } + } + + } catch (NamingException e) { + // TRUE if we can't access the value + return true; + } + + if (prev != null) { + // Also check against updatedAttrs, since there might have been + // a previous update + try { + for (int i = 0; i < prev.size(); i++) { + Object obj = prev.get(i); + // TRUE if one value is not equal + if (!(obj instanceof String)) { + return true; + } + if (orderMatters) { + // check only the string with same index + if (!values[i].equals(obj)) { + return true; + } + } else { + // check all strings + if (!ArrayUtils.contains(values, obj)) { + return true; + } + } + } + + } catch (NamingException e) { + // TRUE if we can't access the value + return true; + } + } + // FALSE since we have compared all values + return false; + } + + /** + * Checks if an entry has a specific attribute. + * + * This method simply calls exists(String) with the attribute name. + * + * @param attr + * the attribute to check. + * @return true if attribute exists in entry. + */ + protected final boolean exists(Attribute attr) { + return exists(attr.getID()); + } + + /** + * Checks if the attribute exists in this entry, either it was read or it + * has been added and update() has been called. + * + * @param attrId + * id of the attribute to check. + * @return true if the attribute exists in the entry. + */ + protected final boolean exists(String attrId) { + return attrs.get(attrId) != null; + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getStringAttribute(java.lang.String) + */ + public String getStringAttribute(String name) { + return (String) getObjectAttribute(name); + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getObjectAttribute(java.lang.String) + */ + public Object getObjectAttribute(String name) { + Attribute oneAttr = attrs.get(name); + if (oneAttr == null) { + return null; + } + try { + return oneAttr.get(); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValue(java.lang.String, + * java.lang.Object) + */ + public void setAttributeValue(String name, Object value) { + // new entry + if (!updateMode && value != null) { + attrs.put(name, value); + } + + // updating entry + if (updateMode && isChanged(name, value)) { + BasicAttribute attribute = new BasicAttribute(name); + if (value != null) { + attribute.add(value); + } + updatedAttrs.put(attribute); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String, + * java.lang.Object[]) + */ + public void setAttributeValues(String name, Object[] values) { + setAttributeValues(name, values, ORDER_DOESNT_MATTER); + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String, + * java.lang.Object[], boolean) + */ + public void setAttributeValues(String name, Object[] values, + boolean orderMatters) { + Attribute a = new BasicAttribute(name, orderMatters); + + for (int i = 0; values != null && i < values.length; i++) { + a.add(values[i]); + } + + // only change the original attribute if not in update mode + if (!updateMode && values != null && values.length > 0) { + // don't save empty arrays + attrs.put(a); + } + + // possible to set an already existing attribute to an empty array + if (updateMode && isChanged(name, values, orderMatters)) { + updatedAttrs.put(a); + } + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#update() + */ + public void update() { + NamingEnumeration attributesEnumeration = null; + + try { + attributesEnumeration = updatedAttrs.getAll(); + + // find what to update + while (attributesEnumeration.hasMore()) { + Attribute a = (Attribute) attributesEnumeration.next(); + + // if it does not exist it should be added + if (isEmptyAttribute(a)) { + attrs.remove(a.getID()); + } else { + // Otherwise it should be set. + attrs.put(a); + } + } + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } finally { + closeNamingEnumeration(attributesEnumeration); + } + + // Reset the attributes to be updated + updatedAttrs = new BasicAttributes(true); + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getStringAttributes(java.lang.String) + */ + public String[] getStringAttributes(String name) { + String[] attributes; + + Attribute attribute = attrs.get(name); + if (attribute != null && attribute.size() > 0) { + attributes = new String[attribute.size()]; + for (int i = 0; i < attribute.size(); i++) { + try { + attributes[i] = (String) attribute.get(i); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } else { + return null; + } + + return attributes; + } + + /* + * @see org.springframework.ldap.support.DirContextOperations#getAttributeSortedStringSet(java.lang.String) + */ + public SortedSet getAttributeSortedStringSet(String name) { + TreeSet attrSet = new TreeSet(); + + Attribute attribute = attrs.get(name); + if (attribute != null) { + for (int i = 0; i < attribute.size(); i++) { + try { + attrSet.add(attribute.get(i)); + } catch (NamingException e) { + throw getExceptionTranslator().translate(e); + } + } + } else { + return null; + } + + return attrSet; + } + + /** + * Set the supplied attribute. + * + * @param attribute + * the attribute to set. + */ + public void setAttribute(Attribute attribute) { + attrs.put(attribute); + } + + /** + * Get all attributes. + * + * @return all attributes. + */ + public Attributes getAttributes() { + return attrs; + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(Name) + */ + public Attributes getAttributes(Name name) throws NamingException { + return getAttributes(name.toString()); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(String) + */ + public Attributes getAttributes(String name) throws NamingException { + if (!StringUtils.isEmpty(name)) { + throw new NameNotFoundException(); + } + return (Attributes) attrs.clone(); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(Name, String[]) + */ + public Attributes getAttributes(Name name, String[] attrIds) + throws NamingException { + return getAttributes(name.toString(), attrIds); + } + + /** + * @see javax.naming.directory.DirContext#getAttributes(String, String[]) + */ + public Attributes getAttributes(String name, String[] attrIds) + throws NamingException { + if (!StringUtils.isEmpty(name)) { + throw new NameNotFoundException(); + } + + Attributes a = new BasicAttributes(true); + Attribute target; + for (int i = 0; i < attrIds.length; i++) { + target = attrs.get(attrIds[i]); + if (target != null) { + a.put(target); + } + } + + return a; + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(javax.naming.Name, + * int, javax.naming.directory.Attributes) + */ + public void modifyAttributes(Name name, int modOp, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(String, int, + * Attributes) + */ + public void modifyAttributes(String name, int modOp, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(Name, + * ModificationItem[]) + */ + public void modifyAttributes(Name name, ModificationItem[] mods) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#modifyAttributes(String, + * ModificationItem[]) + */ + public void modifyAttributes(String name, ModificationItem[] mods) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#bind(Name, Object, Attributes) + */ + public void bind(Name name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#bind(String, Object, Attributes) + */ + public void bind(String name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#rebind(Name, Object, Attributes) + */ + public void rebind(Name name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#rebind(String, Object, Attributes) + */ + public void rebind(String name, Object obj, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#createSubcontext(Name, Attributes) + */ + public DirContext createSubcontext(Name name, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#createSubcontext(String, + * Attributes) + */ + public DirContext createSubcontext(String name, Attributes attrs) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchema(Name) + */ + public DirContext getSchema(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchema(String) + */ + public DirContext getSchema(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchemaClassDefinition(Name) + */ + public DirContext getSchemaClassDefinition(Name name) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#getSchemaClassDefinition(String) + */ + public DirContext getSchemaClassDefinition(String name) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, Attributes, String[]) + */ + public NamingEnumeration search(Name name, Attributes matchingAttributes, + String[] attributesToReturn) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, Attributes, + * String[]) + */ + public NamingEnumeration search(String name, Attributes matchingAttributes, + String[] attributesToReturn) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, Attributes) + */ + public NamingEnumeration search(Name name, Attributes matchingAttributes) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, Attributes) + */ + public NamingEnumeration search(String name, Attributes matchingAttributes) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, String, + * SearchControls) + */ + public NamingEnumeration search(Name name, String filter, + SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, String, + * SearchControls) + */ + public NamingEnumeration search(String name, String filter, + SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(Name, String, Object[], + * SearchControls) + */ + public NamingEnumeration search(Name name, String filterExpr, + Object[] filterArgs, SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.directory.DirContext#search(String, String, Object[], + * SearchControls) + */ + public NamingEnumeration search(String name, String filterExpr, + Object[] filterArgs, SearchControls cons) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookup(Name) + */ + public Object lookup(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookup(String) + */ + public Object lookup(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#bind(Name, Object) + */ + public void bind(Name name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#bind(String, Object) + */ + public void bind(String name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rebind(Name, Object) + */ + public void rebind(Name name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rebind(String, Object) + */ + public void rebind(String name, Object obj) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#unbind(Name) + */ + public void unbind(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#unbind(String) + */ + public void unbind(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rename(Name, Name) + */ + public void rename(Name oldName, Name newName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#rename(String, String) + */ + public void rename(String oldName, String newName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#list(Name) + */ + public NamingEnumeration list(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#list(String) + */ + public NamingEnumeration list(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#listBindings(Name) + */ + public NamingEnumeration listBindings(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#listBindings(String) + */ + public NamingEnumeration listBindings(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#destroySubcontext(Name) + */ + public void destroySubcontext(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#destroySubcontext(String) + */ + public void destroySubcontext(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#createSubcontext(Name) + */ + public Context createSubcontext(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#createSubcontext(String) + */ + public Context createSubcontext(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookupLink(Name) + */ + public Object lookupLink(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#lookupLink(String) + */ + public Object lookupLink(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameParser(Name) + */ + public NameParser getNameParser(Name name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameParser(String) + */ + public NameParser getNameParser(String name) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#composeName(Name, Name) + */ + public Name composeName(Name name, Name prefix) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#composeName(String, String) + */ + public String composeName(String name, String prefix) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#addToEnvironment(String, Object) + */ + public Object addToEnvironment(String propName, Object propVal) + throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#removeFromEnvironment(String) + */ + public Object removeFromEnvironment(String propName) throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getEnvironment() + */ + public Hashtable getEnvironment() throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#close() + */ + public void close() throws NamingException { + throw new UnsupportedOperationException("Not implemented."); + } + + /** + * @see javax.naming.Context#getNameInNamespace() + */ + public String getNameInNamespace() { + DistinguishedName result = new DistinguishedName(dn); + result.prepend(base); + return result.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#getDn() + */ + public Name getDn() { + return dn; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.DirContextOperations#setDn(javax.naming.Name) + */ + public final void setDn(Name dn) { + if (!updateMode) { + this.dn = new DistinguishedName(dn.toString()); + } + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + return EqualsBuilder.reflectionEquals(this, obj); + } + + /** + * @see Object#hashCode() + */ + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(getClass().getName()); + buf.append(":"); + if (dn != null) { + buf.append(" dn=" + dn); + } + buf.append(" {"); + + try { + for (NamingEnumeration i = attrs.getAll(); i.hasMore();) { + Attribute attribute = (Attribute) i.next(); + if (attribute.size() == 1) { + buf.append(attribute.getID()); + buf.append('='); + buf.append(attribute.get()); + } else { + for (int j = 0; j < attribute.size(); j++) { + if (j > 0) { + buf.append(", "); + } + buf.append(attribute.getID()); + buf.append('['); + buf.append(j); + buf.append("]="); + buf.append(attribute.get(j)); + } + } + + if (i.hasMore()) { + buf.append(", "); + } + } + } catch (NamingException e) { + log.warn("Error in toString()"); + } + buf.append('}'); + + return buf.toString(); + } + + /** + * Get the NamingExceptionTranslator. + * + * @return the NamingExceptionTranslator to use; if none is specified, + * {@link DefaultNamingExceptionTranslator} is used. + */ + public NamingExceptionTranslator getExceptionTranslator() { + if (exceptionTranslator == null) { + exceptionTranslator = new DefaultNamingExceptionTranslator(); + } + return exceptionTranslator; + } + + /** + * Set the NamingExceptionTranslator to use. + * + * @param exceptionTranslator + * the NamingExceptionTranslator to use. + */ + public void setExceptionTranslator( + NamingExceptionTranslator exceptionTranslator) { + this.exceptionTranslator = exceptionTranslator; + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextOperations.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextOperations.java new file mode 100644 index 00000000..c44f3fbd --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextOperations.java @@ -0,0 +1,161 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.SortedSet; + +import javax.naming.Name; +import javax.naming.directory.DirContext; + +/** + * Interface for DirContextAdapter to simplify mock testing. + * + * @author Mattias Arthursson + */ +public interface DirContextOperations extends DirContext, + AttributeModificationsAware { + + /** + * Gets the update mode. The update mode should be true for a + * new entry and true for an existing entry that is being + * updated. + * + * @return update mode + */ + public boolean isUpdateMode(); + + /** + * Creates a String array of the names of the attributes which have been + * changed. + * + * If this is a new entry, all set entries will be in the list. If this is + * an updated entry, only changed and removed entries will be in the array. + * + * @return Array of String + */ + public String[] getNamesOfModifiedAttributes(); + + /** + * Get the value of a String attribute. + * + * @param name + * name of the attribute. + * @return the value of the attribute. + */ + public String getStringAttribute(String name); + + /** + * Get the value of an Object attribute. + * + * @param name + * name of the attribute. + * @return the attribute value as an object if it exists, or + * null otherwise. + */ + public Object getObjectAttribute(String name); + + /** + * Set the with the name name to the value. + * + * @param name + * name of the attribute. + * @param value + * value to set the attribute to. + */ + public void setAttributeValue(String name, Object value); + + /** + * Sets a multivalue attribute, disregarding the order of the values. + * + * If value is null or value.length == 0 then the attribute will be removed. + * + * If update mode, changes will be made only if the array has more or less + * objects or if one or more object has changed. Reordering the objects will + * not cause an update. + * + * @param name + * The id of the attribute. + * @param values + * Attribute values. + */ + public void setAttributeValues(String name, Object[] values); + + /** + * Sets a multivalue attribute. + * + * If value is null or value.length == 0 then the attribute will be removed. + * + * If update mode, changes will be made if the array has more or less + * objects or if one or more string has changed. + * + * Reordering the objects will only cause an update if orderMatters is set + * to true. + * + * @param name + * The id of the attribute. + * @param values + * Attribute values. + * @param orderMatters + * If true, it will be changed even if data was + * just reordered. + */ + public void setAttributeValues(String name, Object[] values, + boolean orderMatters); + + /** + * Update the attributes. This will mean that the getters + * (getStringAttribute methods) will return the updated values. Remove the + * attributes to be updated. + */ + public void update(); + + /** + * Get all values of a String attribute. + * + * @param name + * name of the attribute. + * + * @return all registered values of the attribute. + */ + public String[] getStringAttributes(String name); + + /** + * Get all String values of the attribute as a SortedSet. + * + * @param name + * name of the attribute. + * @return a SortedSet containing all values of the attribute. + */ + public SortedSet getAttributeSortedStringSet(String name); + + /** + * Returns DN, without the base path. + * + * @return The distinguished name of the current context. + * + * @see DirContextAdapter#getNameInNamespace() + */ + public Name getDn(); + + /** + * Set the dn of this entry. + * + * @param dn + * the dn. + */ + public void setDn(Name dn); +} \ No newline at end of file diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextSource.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextSource.java new file mode 100644 index 00000000..e69d6a0a --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DirContextSource.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; + +/** + * ContextSource implementation which creates InitialDirContext instances, for + * LDAPv2 compatibility. For configuration information, see + * {@link org.springframework.ldap.support.AbstractContextSource AbstractContextSource}. + * + * @see org.springframework.ldap.support.AbstractContextSource + * + * @author Mattias Arthursson + */ +public class DirContextSource extends AbstractContextSource { + + /** + * Create a new InitialDirContext instance. + * + * @param environment + * the environment to use when creating the context. + * @return a new InitialDirContext implementation. + */ + protected DirContext getDirContextInstance(Hashtable environment) + throws NamingException { + return new InitialDirContext(environment); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DistinguishedName.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DistinguishedName.java new file mode 100644 index 00000000..050ea203 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DistinguishedName.java @@ -0,0 +1,647 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import javax.naming.CompositeName; +import javax.naming.InvalidNameException; +import javax.naming.Name; + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.BadLdapGrammarException; +import org.springframework.ldap.util.ListComparator; + +/** + * Default implementation of a Name corresponding to an LDAP path. A + * DistinguishedName implementation is included in JDK1.5 (LdapName), but not in + * prior releases. + * + * An DistinguishedName is particularly useful when building or modifying an + * Ldap path dynamically, as escaping will be taken care of. + * + * A path is split into several names. The Name interface specifies that the + * most significant part be in position 0, i.e. + * + * The path: uid=adam.skogman, ou=People, ou=EU Name[0]: ou=EU Name[1]: + * ou=People Name[2]: uid=adam.skogman + *

+ * Useful for parsing and building LDAP paths. + * + *

+ * DistinguishedName path = new DistinguishedName();
+ * path.addLast("cn", entry.getUid());
+ * path.addLast("ou", "users");
+ * path.append(new DistinguishedName(helpdesk.getSomeSuffix()));
+ * String dn = path.toString();
+ * 
+ * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DistinguishedName implements Name { + private static final long serialVersionUID = 3514344371999042586L; + + /** + * An empty, unmodifiable DistinguishedName. + */ + public static final DistinguishedName EMPTY_PATH = new DistinguishedName( + Collections.EMPTY_LIST); + + private List names; + + /** + * Construct a new DistinguishedName with no components. + */ + public DistinguishedName() { + names = new LinkedList(); + } + + /** + * Construct a new DistinguishedName from a String. + * + * @param path + * a String corresponding to a (syntactically) valid LDAP path. + */ + public DistinguishedName(String path) { + if (StringUtils.isBlank(path)) { + names = new LinkedList(); + } else { + parse(path); + } + } + + /** + * Construct a new DistinguishedName from the supplied List of LdapRdn + * objects. + * + * @param list + * the components that this instance will consist of. + */ + public DistinguishedName(List list) { + this.names = list; + } + + /** + * Construct a new DistinguishedName from the supplied Name. The parts of + * the supplied Name must be syntactically correct LdapRdns. + * + * @param name + * the Name to construct a new DistinguishedName from. + */ + public DistinguishedName(Name name) { + names = new LinkedList(); + for (int i = 0; i < name.size(); i++) { + names.add(new LdapRdn(name.get(i))); + } + } + + /** + * Parse the supplied String and make this instance represent the + * corresponding distinguished name. + * + * @param path + * the LDAP path to parse. + */ + protected void parse(String path) { + DnParser parser = DefaultDnParserFactory + .createDnParser(unmangleCompositeName(path)); + DistinguishedName dn; + try { + dn = parser.dn(); + } catch (ParseException e) { + throw new BadLdapGrammarException("Failed to parse DN", e); + } catch (TokenMgrError e) { + throw new BadLdapGrammarException("Failed to parse DN", e); + } + this.names = dn.names; + } + + /** + * If path is surrounded by quotes, strip them. JNDI considers forward slash + * ('/') special, but LDAP doesn't. {@link CompositeName#toString()} tends + * to mangle a Name with a slash by surrounding it with quotes ('"'). + * + * @param path + * Path to check and possibly strip. + * @return A String with the possibly stripped path. + */ + private String unmangleCompositeName(String path) { + String tempPath; + // Check if CompositeName has mangled the name with quotes + if (path.startsWith("\"") && path.endsWith("\"")) { + tempPath = path.substring(1, path.length() - 1); + } else { + tempPath = path; + } + return tempPath; + } + + /** + * Get the LdapRdn at a specified position. + * + * @param index + * the LdapRdn to retrieve. + * @return the LdapRdn at the requested position. + */ + public LdapRdn getLdapRdn(int index) { + return (LdapRdn) names.get(index); + } + + /** + * Get the name list. + * + * @return the list of LdapRdns that this DistinguishedName consists of. + */ + public List getNames() { + return names; + } + + /** + * Get the String representation of this DistinguishedName. + * + * @return a syntactically correct, escaped String representation of the + * DistinguishedName. + */ + public String toString() { + return encode(); + } + + /** + * Builds a complete LDAP path, ldap encoded, useful as a DN. + * + * Always uses lowercase, always separates with ", " i.e. comma and a space. + * + * @return the LDAP path. + */ + public String encode() { + + // empty path + if (names.size() == 0) + return ""; + + StringBuffer buffer = new StringBuffer(256); + + ListIterator i = names.listIterator(names.size()); + while (i.hasPrevious()) { + LdapRdn rdn = (LdapRdn) i.previous(); + buffer.append(rdn.getLdapEncoded()); + + // add comma, except in last iteration + if (i.hasPrevious()) + buffer.append(", "); + } + + return buffer.toString(); + + } + + /** + * Builds a complete LDAP path, ldap and url encoded. Separates only with + * ",". + * + * @return the LDAP path, for use in an url. + */ + public String toUrl() { + StringBuffer buffer = new StringBuffer(256); + + for (int i = names.size() - 1; i >= 0; i--) { + LdapRdn n = (LdapRdn) names.get(i); + buffer.append(n.encodeUrl()); + if (i > 0) { + buffer.append(","); + } + } + return buffer.toString(); + } + + /** + * Determines if a ldap path contains another path. + * + * @param path + * the path to check. + * @return true if the supplied path is conained in this instance, false + * otherwise. + */ + public boolean contains(DistinguishedName path) { + + List shortlist = path.getNames(); + + // this path must be at least as long + if (getNames().size() < shortlist.size()) + return false; + + // must have names + if (shortlist.size() == 0) + return false; + + Iterator longiter = getNames().iterator(); + Iterator shortiter = shortlist.iterator(); + + LdapRdn longname = (LdapRdn) longiter.next(); + LdapRdn shortname = (LdapRdn) shortiter.next(); + + // find first match + while (!longname.equals(shortname) && longiter.hasNext()) { + longname = (LdapRdn) longiter.next(); + } + + // Done? + if (!shortiter.hasNext() && longname.equals(shortname)) + return true; + if (!longiter.hasNext()) + return false; + + // compare + while (longname.equals(shortname) && longiter.hasNext() + && shortiter.hasNext()) { + longname = (LdapRdn) longiter.next(); + shortname = (LdapRdn) shortiter.next(); + } + + // Done + if (!shortiter.hasNext() && longname.equals(shortname)) + return true; + else + return false; + + } + + /** + * Add an LDAP path last in this DistinguishedName. E.g.: + * + *
+     * DistinguishedName name1 = new DistinguishedName("c=SE, dc=jayway, dc=se");
+     * DistinguishedName name2 = new DistinguishedName("ou=people");
+     * name1.append(name2);
+     * 
+ * + * will result in ou=people, c=SE, dc=jayway, dc=se + * + * @param path + * the path to append. + */ + public void append(DistinguishedName path) { + getNames().addAll(path.getNames()); + } + + /** + * Add an LDAP path first in this DistinguishedName. E.g.: + * + *
+     * DistinguishedName name1 = new DistinguishedName("ou=people");
+     * DistinguishedName name2 = new DistinguishedName("c=SE, dc=jayway, dc=se");
+     * name1.prepend(name2);
+     * 
+ * + * will result in ou=people, c=SE, dc=jayway, dc=se + * + * @param path + * the path to prepend. + */ + public void prepend(DistinguishedName path) { + ListIterator i = path.getNames().listIterator(path.getNames().size()); + while (i.hasPrevious()) { + names.add(0, i.previous()); + } + } + + /** + * Remove the first part of this DistinguishedName. + * + * @return the removed entry. + */ + public LdapRdn removeFirst() { + return (LdapRdn) names.remove(0); + } + + /** + * Remove the supplied path from the beginning of this DistinguishedName if + * this instance starts with . Useful for stripping base path suffix + * from a DistinguishedName. + * + * @param path + * the path to remove from the beginning of this instance. + */ + public void removeFirst(Name path) { + if (path != null && this.startsWith(path)) { + for (int i = 0; i < path.size(); i++) + this.removeFirst(); + } + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + + // just duplicate the list, the rdns are immutable. + LinkedList list = new LinkedList(getNames()); + + return new DistinguishedName(list); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + // A subclass with identical values should NOT be considered equal. + // EqualsBuilder in commons-lang cannot handle subclasses correctly. + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + + DistinguishedName name = (DistinguishedName) obj; + + // compare the lists + return getNames().equals(name.getNames()); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.getClass().hashCode() ^ getNames().hashCode(); + } + + /** + * Compare this instance to another object. Note that the comparison is done + * in order of significance, so the most significant Rdn is compared first, + * then the second and so on. + * + * @see javax.naming.Name#compareTo(java.lang.Object) + */ + public int compareTo(Object obj) { + DistinguishedName that = (DistinguishedName) obj; + ListComparator comparator = new ListComparator(); + return comparator.compare(this.names, that.names); + } + + public int size() { + return names.size(); + } + + public boolean isEmpty() { + return names.size() == 0; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getAll() + */ + public Enumeration getAll() { + LinkedList strings = new LinkedList(); + for (Iterator iter = names.iterator(); iter.hasNext();) { + LdapRdn rdn = (LdapRdn) iter.next(); + strings.add(rdn.getLdapEncoded()); + } + + return Collections.enumeration(strings); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#get(int) + */ + public String get(int index) { + LdapRdn rdn = (LdapRdn) names.get(index); + return rdn.getLdapEncoded(); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getPrefix(int) + */ + public Name getPrefix(int index) { + LinkedList newNames = new LinkedList(); + for (int i = 0; i < index; i++) { + newNames.add(names.get(i)); + } + + return new DistinguishedName(newNames); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#getSuffix(int) + */ + public Name getSuffix(int index) { + if (index > names.size()) { + throw new ArrayIndexOutOfBoundsException(); + } + + LinkedList newNames = new LinkedList(); + for (int i = index; i < names.size(); i++) { + newNames.add(names.get(i)); + } + + return new DistinguishedName(newNames); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#startsWith(javax.naming.Name) + */ + public boolean startsWith(Name name) { + if (name.size() == 0) { + return false; + } + + DistinguishedName start = null; + if (name instanceof DistinguishedName) { + start = (DistinguishedName) name; + } else { + return false; + } + + if (start.size() > this.size()) { + return false; + } + + Iterator longiter = names.iterator(); + Iterator shortiter = start.getNames().iterator(); + + while (shortiter.hasNext()) { + Object longname = longiter.next(); + Object shortname = shortiter.next(); + + if (!longname.equals(shortname)) { + return false; + } + } + + // All names in shortiter matched. + return true; + } + + /** + * Determines if this ldap path ends with a certian path. + * + * If the argument path is empty (no names in path) this methid will return + * false. + * + * @param name + * The suffix to check for + * + */ + public boolean endsWith(Name name) { + DistinguishedName path = null; + if (name instanceof DistinguishedName) { + path = (DistinguishedName) name; + } else { + return false; + } + + List shortlist = path.getNames(); + + // this path must be at least as long + if (getNames().size() < shortlist.size()) + return false; + + // must have names + if (shortlist.size() == 0) + return false; + + ListIterator longiter = getNames().listIterator(getNames().size()); + ListIterator shortiter = shortlist.listIterator(shortlist.size()); + + while (shortiter.hasPrevious()) { + LdapRdn longname = (LdapRdn) longiter.previous(); + LdapRdn shortname = (LdapRdn) shortiter.previous(); + + if (!longname.equals(shortname)) + return false; + } + + // if short list ended, all were equal + return true; + + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#addAll(javax.naming.Name) + */ + public Name addAll(Name name) throws InvalidNameException { + return addAll(names.size(), name); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#addAll(int, javax.naming.Name) + */ + public Name addAll(int arg0, Name name) throws InvalidNameException { + DistinguishedName distinguishedName = null; + try { + distinguishedName = (DistinguishedName) name; + } catch (ClassCastException e) { + throw new InvalidNameException("Invalid name type"); + } + + names.addAll(arg0, distinguishedName.getNames()); + return this; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#add(java.lang.String) + */ + public Name add(String string) throws InvalidNameException { + return add(names.size(), string); + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#add(int, java.lang.String) + */ + public Name add(int index, String string) throws InvalidNameException { + try { + names.add(index, new LdapRdn(string)); + } catch (BadLdapGrammarException e) { + throw new InvalidNameException("Failed to parse rdn '" + string + + "'"); + } + return this; + } + + /* + * (non-Javadoc) + * + * @see javax.naming.Name#remove(int) + */ + public Object remove(int arg0) throws InvalidNameException { + LdapRdn rdn = (LdapRdn) names.remove(arg0); + return rdn.getLdapEncoded(); + } + + /** + * Remove the ldast part of this DistinguishedName. + * + * @return the removed LdapRdn. + */ + public LdapRdn removeLast() { + return (LdapRdn) names.remove(names.size() - 1); + } + + /** + * Add a new LdapRdn using the supplied key and value. + * + * @param key + * the key of the LdapRdn. + * @param value + * the value of the LdapRdn. + */ + public void add(String key, String value) { + names.add(new LdapRdn(key, value)); + } + + /** + * Add the supplied LdapRdn last in the list of Rdns. + * + * @param rdn + * the LdapRdn to add. + */ + public void add(LdapRdn rdn) { + names.add(rdn); + } + + /** + * Add the supplied LdapRdn att the specified index. + * + * @param idx + * the index at which to add the LdapRdn. + * @param rdn + * the LdapRdn to add. + */ + public void add(int idx, LdapRdn rdn) { + names.add(idx, rdn); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/DnParser.java b/spring-ldap/src/main/java/org/springframework/ldap/support/DnParser.java new file mode 100644 index 00000000..7bd29baa --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/DnParser.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + + +/** + * A parser for RFC2253-compliant Distinguished Names. + * + * @author Mattias Arthursson + * + */ +public interface DnParser { + /** + * Parse a full Distinguished Name. + * + * @return the DistinguishedName corresponding to the parsed stream. + */ + public DistinguishedName dn() throws ParseException; + + /** + * Parse a Relative Distinguished Name. + * + * @return the next rdn on the stream. + */ + public LdapRdn rdn() throws ParseException; +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/LdapContextSource.java b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapContextSource.java new file mode 100644 index 00000000..ef3e7597 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapContextSource.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.ControlFactory; +import javax.naming.ldap.InitialLdapContext; +import javax.naming.ldap.LdapContext; + +import com.sun.jndi.ldap.ctl.ResponseControlFactory; + +/** + * ContextSource implementation which creates an InitialLdapContext + * instance. For configuration information, see + * {@link org.springframework.ldap.support.AbstractContextSource AbstractContextSource}. + * + * @see org.springframework.ldap.support.AbstractContextSource + * + * @author Mattias Arthursson + * @author Adam Skogman + * @author Ulrik Sandberg + */ +public class LdapContextSource extends AbstractContextSource { + + private static final Class DEFAULT_RESPONSE_CONTROL_FACTORY = ResponseControlFactory.class; + + private Class responseControlFactory = DEFAULT_RESPONSE_CONTROL_FACTORY; + + protected Hashtable getAnonymousEnv() { + Hashtable env = super.getAnonymousEnv(); + env + .put(LdapContext.CONTROL_FACTORIES, responseControlFactory + .getName() + ".trasig"); + return env; + } + + /* + * @see org.springframework.ldap.support.AbstractContextSource#getDirContextInstance(java.util.Hashtable) + */ + protected DirContext getDirContextInstance(Hashtable environment) + throws NamingException { + return new InitialLdapContext(environment, null); + } + + /** + * Set the ResponseControlFactory to use. Default is + * {@link com.sun.jndi.ldap.ctl.ResponseControlFactory}. The specified + * class needs to be an implementation of + * {@link javax.naming.ldap.ControlFactory}. + * + * @param responseControlFactory + * the ResponseControlFactory to be used. Null means reset to the + * default. + */ + public void setResponseControlFactory(Class responseControlFactory) { + if (responseControlFactory == null) { + this.responseControlFactory = DEFAULT_RESPONSE_CONTROL_FACTORY; + } else if (ControlFactory.class + .isAssignableFrom(responseControlFactory)) { + this.responseControlFactory = responseControlFactory; + } else { + throw new IllegalArgumentException( + "Invalid ReponseControlFactory: " + responseControlFactory + + " is not an implementation of " + + ControlFactory.class.getName()); + } + } + + /** + * @return the current ResponseControlFactory. + */ + Class getResponseControlFactory() { + return responseControlFactory; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/LdapEncoder.java b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapEncoder.java new file mode 100644 index 00000000..d6525bc2 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapEncoder.java @@ -0,0 +1,235 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Helper class to encode and decode ldap names and values. + * + * @author Adam Skogman + */ +public class LdapEncoder { + + static private String[] nameEscapeTable = new String[96]; + + static private String[] filterEscapeTable = new String['\\' + 1]; + + /** + * Pattern for matching escaped ldap name values. + * + * Double escaping: \ -> \\ (in pattern) -> \\\\ (in java string literal) + * + * Group 1: Hex escapes = \XX -> \p{XDigit}{2} Group 2: Ordinary escapes = + * \x -> \. Group 3: Anything but \ [^\\] + * + * Note that the \ is not part of the match. + */ + static private final Pattern VALUE_DECODE_PATTERN = Pattern + .compile("(?:\\\\(\\p{XDigit}{2}))|(?:\\\\(.))|([^\\\\])"); + + static { + + // Name encoding table ------------------------------------- + + // all below 0x20 (control chars) + for (char c = 0; c < ' '; c++) { + nameEscapeTable[c] = "\\" + toTwoCharHex(c); + } + + nameEscapeTable['#'] = "\\#"; + nameEscapeTable[','] = "\\,"; + nameEscapeTable[';'] = "\\;"; + nameEscapeTable['='] = "\\="; + nameEscapeTable['+'] = "\\+"; + nameEscapeTable['<'] = "\\<"; + nameEscapeTable['>'] = "\\>"; + // nameEscapeTable['\''] = "\\"; + nameEscapeTable['\"'] = "\\\""; + // nameEscapeTable['/'] = "\\" + toTwoCharHex('/'); + nameEscapeTable['\\'] = "\\\\"; + + // Filter encoding table ------------------------------------- + + // fill with char itself + for (char c = 0; c < filterEscapeTable.length; c++) { + filterEscapeTable[c] = String.valueOf(c); + } + + // escapes (RFC2254) + filterEscapeTable['*'] = "\\2a"; + filterEscapeTable['('] = "\\28"; + filterEscapeTable[')'] = "\\29"; + filterEscapeTable['\\'] = "\\5c"; + filterEscapeTable[0] = "\\00"; + + } + + static protected String toTwoCharHex(char c) { + + String raw = Integer.toHexString(c).toUpperCase(); + + if (raw.length() > 1) + return raw; + else + return "0" + raw; + } + + /** + * All static methods + */ + private LdapEncoder() { + } + + static public String filterEncode(String value) { + + if (value == null) + return null; + + // make buffer roomy + StringBuffer encodedValue = new StringBuffer(value.length() * 2); + + int length = value.length(); + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + if (c < filterEscapeTable.length) { + encodedValue.append(filterEscapeTable[c]); + } else { + // default: add the char + encodedValue.append(c); + } + } + + return encodedValue.toString(); + } + + /** + * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! + * + *
Escapes:
' ' [space] - "\ " [if first or last]
'#' + * [hash] - "\#"
',' [comma] - "\,"
';' [semicolon] - "\;"
'= + * [equals] - "\="
'+' [plus] - "\+"
'<' [less than] - + * "\<"
'>' [greater than] - "\>"
'"' [double quote] - + * "\""
'\' [backslash] - "\\"
+ * + * @param value + * @return The escaped value + */ + static public String nameEncode(String value) { + + if (value == null) + return null; + + // make buffer roomy + StringBuffer encodedValue = new StringBuffer(value.length() * 2); + + int length = value.length(); + int last = length - 1; + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + // space first or last + if (c == ' ' && (i == 0 || i == last)) { + encodedValue.append("\\ "); + continue; + } + + if (c < nameEscapeTable.length) { + // check in table for escapes + String esc = nameEscapeTable[c]; + + if (esc != null) { + encodedValue.append(esc); + continue; + } + } + + // default: add the char + encodedValue.append(c); + } + + return encodedValue.toString(); + + } + + /** + * Decodes a value. Converts escaped chars to ordinary chars. + * + * @param value + * Trimmed value, so no leading an trailing blanks, except an + * escaped space last. + * @return The decoded value as a string. + * @throws BadLdapGrammarException + */ + static public String nameDecode(String value) + throws BadLdapGrammarException { + + if (value == null) + return null; + + // make buffer same size + StringBuffer decoded = new StringBuffer(value.length()); + + Matcher matcher = VALUE_DECODE_PATTERN.matcher(value); + + int end = 0; + + while (matcher.find()) { + end = matcher.end(); + // group 1 + if (matcher.group(1) != null) { + // parse as hex = base 16 + try { + char c = (char) Integer.parseInt(matcher.group(1), 16); + decoded.append(c); + } catch (NumberFormatException e) { + throw new BadLdapGrammarException( + "Escaped hex value Could not be parsed. Found '\\" + + matcher.group(1) + "'"); + } + } else if (matcher.group(2) != null) { + // just add, we stripped away the \ + decoded.append(matcher.group(2)); + } else if (matcher.group(3) != null) { + // just add + decoded.append(matcher.group(3)); + } + + } + // end is match + +1 so it should be same as length, i.e. + // last + 1 + if (end < value.length()) { + throw new BadLdapGrammarException( + "RDN could not be parsed fully, remaining '" + + StringUtils.substring(value, end) + "'"); + } + + return decoded.toString(); + + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdn.java b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdn.java new file mode 100644 index 00000000..f5ccdd6d --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdn.java @@ -0,0 +1,198 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.ldap.BadLdapGrammarException; +import org.springframework.ldap.util.ListComparator; + +/** + * Datatype for a LDAP name, a part of a path. + * + * The name: uid=adam.skogman Key: uid Value: adam.skogman + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class LdapRdn implements Serializable, Comparable { + private static final long serialVersionUID = 5681397547245228750L; + + private List components = new LinkedList(); + + /** + * Default constructor. + */ + public LdapRdn() { + } + + /** + * Parse the supplied string and construct this instance accordingly. + * + * @param string + * the string to parse. + */ + public LdapRdn(String string) { + DnParser parser = DefaultDnParserFactory.createDnParser(string); + LdapRdn rdn; + try { + rdn = parser.rdn(); + } catch (ParseException e) { + throw new BadLdapGrammarException("Failed to parse Rdn", e); + } catch (TokenMgrError e) { + throw new BadLdapGrammarException("Failed to parse Rdn", e); + } + this.components = rdn.components; + } + + /** + * Construct an LdapRdn using the supplied key and value. + * + * @param key + * @param value + */ + public LdapRdn(String key, String value) { + components.add(new LdapRdnComponent(key, value)); + } + + /** + * Add an LdapRdnComponent to this LdapRdn. + * + * @param rdnComponent + * the LdapRdnComponent to add.s + */ + public void addComponent(LdapRdnComponent rdnComponent) { + components.add(rdnComponent); + } + + /** + * Gets all components in this LdapRdn. + * + * @return the List of all LdapRdnComponents composing this LdapRdn. + */ + public List getComponents() { + return components; + } + + /** + * Gets the first LdapRdnComponent of this LdapRdn. + * + * @return The first LdapRdnComponent of this LdapRdn. + * @throws IndexOutOfBoundsException + * if no components have been added. + */ + public LdapRdnComponent getComponent() { + return (LdapRdnComponent) components.get(0); + } + + /** + * Get the LdapRdnComponent at index idx. + * + * @param idx + * the 0-based index of the component to get. + * @return the LdapRdnComponent at indet idx. + * @throws IndexOutOfBoundsException + * if no component exists at index idx. + */ + public LdapRdnComponent getComponent(int idx) { + return (LdapRdnComponent) components.get(idx); + } + + /** + * Get a properly rfc2253-encoded String representation to this LdapRdn. + * + * @return an encoded String corresponding to this LdapRdn. + */ + public String getLdapEncoded() { + if (components.size() == 0) { + throw new IndexOutOfBoundsException("No components in Rdn."); + } + StringBuffer sb = new StringBuffer(100); + for (Iterator iter = components.iterator(); iter.hasNext();) { + LdapRdnComponent component = (LdapRdnComponent) iter.next(); + sb.append(component.encodeLdap()); + if (iter.hasNext()) { + sb.append("+"); + } + } + + return sb.toString(); + } + + /** + * Get a String representation of this LdapRdn for use in urls. + * + * @return a String representation of this LdapRdn for use in urls. + */ + public String encodeUrl() { + StringBuffer sb = new StringBuffer(100); + for (Iterator iter = components.iterator(); iter.hasNext();) { + LdapRdnComponent component = (LdapRdnComponent) iter.next(); + sb.append(component.encodeUrl()); + if (iter.hasNext()) { + sb.append("+"); + } + } + + return sb.toString(); + } + + /** + * Compare this LdapRdn to another object. + * + * @param obj + * the object to compare to. + * @throws ClassCastException + * if the supplied object is not an LdapRdn instance. + */ + public int compareTo(Object obj) { + LdapRdn that = (LdapRdn) obj; + Comparator comparator = new ListComparator(); + return comparator.compare(this.components, that.components); + } + + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + + LdapRdn that = (LdapRdn) obj; + return this.getComponents().equals(that.getComponents()); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.getClass().hashCode() ^ getComponents().hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return getLdapEncoded(); + } +} \ No newline at end of file diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java new file mode 100644 index 00000000..52bd4e72 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapRdnComponent.java @@ -0,0 +1,163 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; + +/** + * Represents part of an LdapRdn. As specified in RFC2253 an LdapRdn may be + * composed of several attributes, separated by "+". An + * LdapRdnComponent represents one of these attributes. + * + * @author Mattias Arthursson + * + */ +public class LdapRdnComponent implements Comparable { + public static final boolean DONT_DECODE_VALUE = false; + + private String key; + + private String value; + + /** + * Constructs an LdapRdnComponent without decoding the value. + * + * @param key + * the Atttribute name. + * @param value + * the Attribute value. + */ + public LdapRdnComponent(String key, String value) { + this(key, value, DONT_DECODE_VALUE); + } + + /** + * Constructs an LdapRdnComponent, optionally decoding the value. + * + * @param key + * the Atttribute name. + * @param value + * the Attribute value. + * @param decodeValue + * if true the value is decoded (typically used + * when a DN is parsed from a String), otherwise the value is + * used as specified. + */ + public LdapRdnComponent(String key, String value, boolean decodeValue) { + Validate.notEmpty(key, "Key must not be empty"); + Validate.notEmpty(value, "Value must not be empty"); + + this.key = StringUtils.lowerCase(key); + if (decodeValue) { + this.value = LdapEncoder.nameDecode(value); + } else { + this.value = value; + } + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + /** + * Encode key and value to ldap + * + * @return The ldap encoded rdn + */ + protected String encodeLdap() { + StringBuffer buff = new StringBuffer(key.length() + value.length() * 2); + + buff.append(key); + buff.append('='); + buff.append(LdapEncoder.nameEncode(value)); + + return buff.toString(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return getLdapEncoded(); + } + + /** + * @return The LdapRdn as a string where the value is LDAP-encoded. + */ + public String getLdapEncoded() { + return encodeLdap(); + } + + public String encodeUrl() { + // Use the URI class to properly URL encode the value. + try { + URI valueUri = new URI(null, null, value, null); + return key + "=" + valueUri.toString(); + } catch (URISyntaxException e) { + // This should really never happen... + return key + "=" + "value"; + } + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return key.hashCode() ^ value.hashCode(); + } + + public boolean equals(Object obj) { + if (obj != null && obj.getClass() == LdapRdnComponent.class) { + LdapRdnComponent that = (LdapRdnComponent) obj; + return StringUtils.equalsIgnoreCase(this.key, that.key) + && StringUtils.equalsIgnoreCase(this.value, that.value); + + } else { + return false; + } + } + + /** + * Compare this instance to the supplied object. + * + * @param obj + * the object to compare to. + * @throws ClassCastException + * if the object is not possible to cast to an LdapRdnComponent. + */ + public int compareTo(Object obj) { + LdapRdnComponent that = (LdapRdnComponent) obj; + return this.toString().compareTo(that.toString()); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java b/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java new file mode 100644 index 00000000..1e28a087 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSource.java @@ -0,0 +1,81 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import org.acegisecurity.Authentication; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.AuthenticationSource; + + +/** + * An AuthenticationSource to retrieve authentication information stored in + * Acegi's SecurityContextHolder. Use Acegi's LdapAuthenticationProvider have a + * LdapUserDetails object placed in the authentication. + * + * @author Mattias Arthursson + * + */ +public class AcegiAuthenticationSource implements AuthenticationSource { + private static final Log log = LogFactory + .getLog(AcegiAuthenticationSource.class); + + /** + * Get the principals of the logged in user, in this case the distinguished + * name. + * + * @return the distinguished name of the logged in user. + */ + public String getPrincipal() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (!(principal instanceof LdapUserDetails)) { + throw new IllegalArgumentException( + "The principal property of the authentication object -" + + "needs to be a LdapUserDetails."); + } else { + LdapUserDetails details = (LdapUserDetails) principal; + return details.getDn(); + } + } else { + log.warn("No Authentication object set in SecurityContext - " + + "returning empty String as Principal"); + return ""; + } + } + + /* + * @see org.springframework.ldap.AuthenticationSource#getCredentials() + */ + public String getCredentials() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + + if (authentication != null) { + return (String) authentication.getCredentials(); + } else { + log.warn("No Authentication object set in SecurityContext - " + + "returning empty String as Credentials"); + return ""; + } + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java b/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java new file mode 100644 index 00000000..ed94d937 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecorator.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.ldap.AuthenticationSource; + +/** + * Decorator on AuthenticationSource to have default authentication information + * be returned should the target return empty principal and credentials. Useful + * in combination with {@link AcegiAuthenticationSource} if users are to be + * allowed to read some information even though they are not logged in. + *

+ * Note: The defaultUser should be an non-privileged + * user. This is important as this is the one that will be used when no user is + * logged in (i.e. empty principal is returned from the target + * AuthenticationSource). + * + * @author Mattias Arthursson + * + */ +public class DefaultValuesAuthenticationSourceDecorator implements + AuthenticationSource, InitializingBean { + + private AuthenticationSource target; + + private String defaultUser; + + private String defaultPassword; + + /** + * Constructor for bean usage. + */ + public DefaultValuesAuthenticationSourceDecorator() { + } + + /** + * Constructor to setup instance directly. + * + * @param target + * the target AuthenticationSource. + * @param defaultUser + * dn of the user to use when the target returns an empty + * principal. + * @param defaultPassword + * password of the user to use when the target returns an empty + * principal. + */ + public DefaultValuesAuthenticationSourceDecorator( + AuthenticationSource target, String defaultUser, + String defaultPassword) { + this.target = target; + this.defaultUser = defaultUser; + this.defaultPassword = defaultPassword; + } + + /** + * Checks if the target's principal is not empty; if not, the credentials + * from the target is returned - otherwise return the + * defaultPassword. + * + * @return the target's password if the target's principal is not empty, the + * defaultPassword otherwise. + */ + public String getCredentials() { + if (StringUtils.isNotEmpty(target.getPrincipal())) { + return target.getCredentials(); + } else { + return defaultPassword; + } + } + + /** + * Checks if the target's principal is not empty; if not, this is returned - + * otherwise return the defaultUser. + * + * @return the target's principal if it is not empty, the + * defaultUser otherwise. + */ + public String getPrincipal() { + String principal = target.getPrincipal(); + if (StringUtils.isNotEmpty(principal)) { + return principal; + } else { + return defaultUser; + } + } + + /** + * Set the password of the default user. + * + * @param defaultPassword + * the password of the default user. + */ + public void setDefaultPassword(String defaultPassword) { + this.defaultPassword = defaultPassword; + } + + /** + * Set the default user DN. This should be a non-privileged user, since it + * will be used when no authentication information is returned from the + * target. + * + * @param defaultUser + * DN of the default user. + */ + public void setDefaultUser(String defaultUser) { + this.defaultUser = defaultUser; + } + + /** + * Set the target AuthenticationSource. + * + * @param target + * the target AuthenticationSource. + */ + public void setTarget(AuthenticationSource target) { + this.target = target; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + if (target == null) { + throw new IllegalArgumentException( + "Property 'target' must be set.'"); + } + + if (defaultUser == null) { + throw new IllegalArgumentException( + "Property 'defaultUser' must be set.'"); + } + + if (defaultPassword == null) { + throw new IllegalArgumentException( + "Property 'defaultPassword' must be set.'"); + } + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/package.html b/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/package.html new file mode 100644 index 00000000..d15fe6bc --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/authentication/package.html @@ -0,0 +1,3 @@ + +Support classes for custom authentication. + diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java b/spring-ldap/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java new file mode 100644 index 00000000..3d54d9c4 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessor.java @@ -0,0 +1,90 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.ldap.DirContextProcessor; + +/** + * Abstract superclass with responsibility to apply a single RequestControl on + * an LdapContext, preserving any existing controls. Subclasses should implement + * {@link DirContextProcessor#postProcess(DirContext)} and template method + * {@link #createRequestControl()}. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public abstract class AbstractRequestControlDirContextProcessor implements + DirContextProcessor { + protected Log log = LogFactory + .getLog(AbstractRequestControlDirContextProcessor.class); + + /** + * Get the existing RequestControls from the LdapContext, call + * {@link #createRequestControl()} to get a new instance, build a new array + * of Controls and set it on the LdapContext. + *

+ * The {@link Control} feature is specific for LDAP v3 and thus applies only + * to {@link LdapContext}. However, the generic DirContextProcessor + * mechanism used for calling preProcess and + * postProcess uses DirContext, since it also works for LDAP + * v2. This is the reason that DirContext has to be cast into LdapContext. + * + * @param ctx + * an LdapContext instance. + * @throws NamingException + * @throws IllegalArgumentException + * if the supplied DirContext is not an LdapContext. + */ + public void preProcess(DirContext ctx) throws NamingException { + LdapContext ldapContext; + if (ctx instanceof LdapContext) { + ldapContext = (LdapContext) ctx; + } else { + throw new IllegalArgumentException( + "Request Control operations require LDAPv3 - " + + "Context must be of type LdapContext"); + } + + Control[] requestControls = ldapContext.getRequestControls(); + Control newControl = createRequestControl(); + + Control[] newControls = new Control[requestControls.length + 1]; + for (int i = 0; i < requestControls.length; i++) { + newControls[i] = requestControls[i]; + } + + // Add the new Control at the end of the array. + newControls[newControls.length - 1] = newControl; + + ldapContext.setRequestControls(newControls); + } + + /** + * Create an instance of the appropriate RequestControl. + * + * @return the new instance. + */ + public abstract Control createRequestControl(); + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResult.java b/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResult.java new file mode 100644 index 00000000..ccb22460 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResult.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support.control; + +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Bean to encapsulate a result List and a {@link PagedResultsCookie} to use for + * returning the results when using {@link PagedResultsRequestControl}. + */ +public class PagedResult { + + private List resultList; + + private PagedResultsCookie cookie; + + /** + * Constructs a PagedResults using the supplied List and + * {@link PagedResultsCookie}. + * + * @param resultList + * the result list. + * @param cookie + * the cookie. + */ + public PagedResult(List resultList, PagedResultsCookie cookie) { + this.resultList = resultList; + this.cookie = cookie; + } + + /** + * Get the cookie. + * + * @return the cookie. + */ + public PagedResultsCookie getCookie() { + return cookie; + } + + /** + * Get the result list. + * + * @return the result list. + */ + public List getResultList() { + return resultList; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj != null && this.getClass().equals(obj.getClass())) { + PagedResult that = (PagedResult) obj; + return new EqualsBuilder().append(this.resultList, that.resultList) + .append(this.cookie, that.cookie).isEquals(); + } + + return false; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return new HashCodeBuilder().append(this.resultList) + .append(this.cookie).toHashCode(); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java b/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java new file mode 100644 index 00000000..46d179c2 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsCookie.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import com.sun.jndi.ldap.ctl.PagedResultsControl; + +/** + * Wrapper class for the cookie returned when using the + * {@link PagedResultsControl}. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PagedResultsCookie { + + private byte[] cookie; + + /** + * Constructor. + * + * @param cookie + * the cookie returned by a PagedResultsResponseControl. + */ + public PagedResultsCookie(byte[] cookie) { + this.cookie = ArrayUtils.clone(cookie); + } + + /** + * Get the cookie. + * + * @return the cookie. + */ + public byte[] getCookie() { + return ArrayUtils.clone(cookie); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj != null && this.getClass().equals(obj.getClass())) { + PagedResultsCookie that = (PagedResultsCookie) obj; + return new EqualsBuilder().append(this.cookie, that.cookie) + .isEquals(); + } + + return false; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return new HashCodeBuilder().append(this.cookie).toHashCode(); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java b/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java new file mode 100644 index 00000000..ab85e3c6 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/control/PagedResultsRequestControl.java @@ -0,0 +1,200 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.control; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import org.springframework.ldap.UncategorizedLdapException; +import org.springframework.util.ReflectionUtils; + +import com.sun.jndi.ldap.ctl.PagedResultsControl; +import com.sun.jndi.ldap.ctl.PagedResultsResponseControl; + +/** + * DirContextProcessor implementation for managing the paged results. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class PagedResultsRequestControl extends + AbstractRequestControlDirContextProcessor { + + private static final Class DEFAULT_RESPONSE_CONTROL = PagedResultsResponseControl.class; + + private static final boolean CRITICAL_CONTROL = true; + + private static final String JAVA5_RESPONSE_CONTROL = "javax.naming.ldap.PagedResultsResponseControl"; + + private int pageSize; + + private PagedResultsCookie cookie; + + private int resultSize; + + private Class responseControlClass = DEFAULT_RESPONSE_CONTROL; + + private Class fallbackResponseControlClass; + + private Class currentResponseControlClass; + + public PagedResultsRequestControl(int pageSize) { + this(pageSize, null); + } + + public PagedResultsRequestControl(int pageSize, PagedResultsCookie cookie) { + this.pageSize = pageSize; + this.cookie = cookie; + fallbackResponseControlClass = loadFallbackResponseControlClass(); + } + + public PagedResultsCookie getCookie() { + return cookie; + } + + public int getPageSize() { + return pageSize; + } + + public int getResultSize() { + return resultSize; + } + + /** + * Set the class of the expected ResponseControl for the paged results + * response. The default is {@link PagedResultsResponseControl}. + * + * @param responseControlClass + * Class of the expected response control. + */ + public void setResponseControlClass(Class responseControlClass) { + this.responseControlClass = responseControlClass; + } + + /* + * @see org.springframework.ldap.support.control.AbstractRequestControlDirContextProcessor#createRequestControl() + */ + public Control createRequestControl() { + try { + if (cookie != null) { + return new PagedResultsControl(pageSize, cookie.getCookie(), + CRITICAL_CONTROL); + } else { + return new PagedResultsControl(pageSize); + } + } catch (IOException e) { + throw new UncategorizedLdapException( + "Error creating PagedResultsControl", e); + } + } + + /* + * @see org.springframework.ldap.DirContextProcessor#postProcess(javax.naming.directory.DirContext) + */ + public void postProcess(DirContext ctx) throws NamingException { + // initialize from property + currentResponseControlClass = responseControlClass; + + LdapContext ldapContext = (LdapContext) ctx; + Control[] responseControls = ldapContext.getResponseControls(); + + // Go through response controls and get info, regardless of class + for (int i = 0; i < responseControls.length; i++) { + Control responseControl = responseControls[i]; + + // check for match, try fallback otherwise + if (isPagedResultsResponseControl(responseControl)) { + Object control = responseControl; + byte[] result = (byte[]) invokeMethod("getCookie", + currentResponseControlClass, control); + this.cookie = new PagedResultsCookie(result); + Integer wrapper = (Integer) invokeMethod("getResultSize", + currentResponseControlClass, control); + this.resultSize = wrapper.intValue(); + } + } + } + + /** + * Check if the given control matches a paged results response control. Try + * the fallback class from Java5 if there is no match. Set the + * {@link #currentResponseControlClass} to the fallback if it matches. + * + * @param responseControl + * the control to check for a match + * @return whether the control is a paged results response control + */ + private boolean isPagedResultsResponseControl(Control responseControl) { + if (responseControl.getClass().isAssignableFrom( + currentResponseControlClass)) { + return true; + } + if (fallbackResponseControlClass != null + && responseControl.getClass().isAssignableFrom( + fallbackResponseControlClass)) { + currentResponseControlClass = fallbackResponseControlClass; + return true; + } + return false; + } + + private Class loadFallbackResponseControlClass() { + Class fallbackResponseControlClass = null; + try { + fallbackResponseControlClass = Class + .forName(JAVA5_RESPONSE_CONTROL); + } catch (ClassNotFoundException e) { + log.debug("Could not load Java5 response control class " + + JAVA5_RESPONSE_CONTROL); + } + return fallbackResponseControlClass; + } + + private Object invokeMethod(String method, Class clazz, Object control) { + // For Spring 2.0 ReflectionUtils could be used for all of this, but + // since we still want to support the 1.2 branch we do it manually and + // only use the stuff present in 1.2.8. + Method actualMethod = null; + Object retval = null; + try { + actualMethod = clazz.getMethod(method, new Class[0]); + } catch (SecurityException e) { + ReflectionUtils.handleReflectionException(e); + } catch (NoSuchMethodException e) { + ReflectionUtils.handleReflectionException(e); + } + + try { + retval = actualMethod.invoke(control, new Object[0]); + } catch (IllegalArgumentException e) { + ReflectionUtils.handleReflectionException(e); + } catch (IllegalAccessException e) { + ReflectionUtils.handleReflectionException(e); + } catch (InvocationTargetException e) { + ReflectionUtils.handleReflectionException(e); + } + + // Retval will be set unless an exception has been thrown. + return retval; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/control/package.html b/spring-ldap/src/main/java/org/springframework/ldap/support/control/package.html new file mode 100644 index 00000000..e8351194 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/control/package.html @@ -0,0 +1,3 @@ + +Support classes for custom request control context processors. + diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java new file mode 100644 index 00000000..e00f8f04 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/AbstractFilter.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Convenience class that implements most of the methods in the Filter + * interface. + * + * @author Adam Skogman + */ +public abstract class AbstractFilter implements Filter { + + protected AbstractFilter() { + super(); + } + + /** + * Prints the query with LDAP encoding to a stringbuffer + * + * @param buff + * The stringbuffer + * @return The very same stringbuffer + */ + public abstract StringBuffer encode(StringBuffer buff); + + /** + * Encodes the filter to a string using the (@link #encode(StringBuffer) + * method. + * + * @return The encoded filter + */ + public String encode() { + StringBuffer buff = new StringBuffer(256); + buff = encode(buff); + return buff.toString(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return encode(); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/AndFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/AndFilter.java new file mode 100644 index 00000000..4622da1f --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/AndFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter for a logical AND. E.g.: + * + *

+ *     AndFilter filter = new AndFilter();
+ *     filter.and(new EqualsFilter("objectclass", "person");
+ *     filter.and(new EqualsFilter("cn", "Some CN");
+ *     System.out.println(filter.ecode());    
+ * 
+ * + * would result in: (&(objectclass=person)(cn=Some CN)) + * + * @see org.springframework.ldap.support.filter.EqualsFilter + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class AndFilter extends BinaryLogicalFilter { + + private static final String AMPERSAND = "&"; + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.filter.BinaryLogicalFilter#getLogicalOperator() + */ + protected String getLogicalOperator() { + return AMPERSAND; + } + + /** + * Add a query to the and expression + * + * @param query + * The query to and with the rest of the and:ed queries. + * @return This LdapAndQuery + */ + public AndFilter and(Filter query) { + queryList.add(query); + return this; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java new file mode 100644 index 00000000..0c3ef3a2 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/BinaryLogicalFilter.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Abstract superclass for binary logical operations, that is "and" + * and "or" operations. + * + * @author Mattias Arthursson + */ +public abstract class BinaryLogicalFilter extends AbstractFilter { + + protected List queryList = new LinkedList(); + + /** + * @see org.springframework.ldap.support.filter.Filter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + if (queryList.size() <= 0) { + + // only output query if contains anything + return buff; + + } else if (queryList.size() == 1) { + + // don't add the & + Filter query = (Filter) queryList.get(0); + return query.encode(buff); + + } else { + buff.append("(" + getLogicalOperator()); + + for (Iterator i = queryList.iterator(); i.hasNext();) { + Filter query = (Filter) i.next(); + buff = query.encode(buff); + } + + buff.append(")"); + + return buff; + } + } + + /** + * Implement this in subclass to return the logical operator, for example + * &qout;&&qout;. + * + * @return the logical operator. + */ + protected abstract String getLogicalOperator(); + + /** + * Compares each filter in turn + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj instanceof BinaryLogicalFilter + && this.getClass() == obj.getClass()) { + return EqualsBuilder.reflectionEquals(this, obj); + } else { + return false; + } + } + + /** + * Hashes all contained data + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java new file mode 100644 index 00000000..20fc78f0 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/CompareFilter.java @@ -0,0 +1,123 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.ldap.support.LdapEncoder; + +/** + * Abstract superclass for filters to compare values. + * + * @author Mattias Arthursson + */ +public abstract class CompareFilter extends AbstractFilter { + + private final String attribute; + + private final String value; + + private final String encodedValue; + + public CompareFilter(String attribute, String value) { + this.attribute = attribute; + this.value = value; + this.encodedValue = encodeValue(value); + } + + /** + * For testing purposes. + * + * @return the encoded value. + */ + String getEncodedValue() { + return encodedValue; + } + + /** + * Override to perform special encoding in subclass. + * + * @param value + * the value to encode. + * @return properly escaped value. + */ + protected String encodeValue(String value) { + return LdapEncoder.filterEncode(value); + } + + /** + * Convenience constructor for int values. + * + * @param attribute + * @param value + */ + public CompareFilter(String attribute, int value) { + this.attribute = attribute; + this.value = String.valueOf(value); + this.encodedValue = LdapEncoder.filterEncode(this.value); + } + + /* + * @see org.springframework.ldap.support.filter.AbstractFilter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + buff.append('('); + buff.append(attribute).append(getCompareString()).append(encodedValue); + buff.append(')'); + + return buff; + } + + /** + * Compares key and value before encoding. + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object o) { + if (o instanceof CompareFilter && o.getClass() == this.getClass()) { + CompareFilter that = (CompareFilter) o; + EqualsBuilder builder = new EqualsBuilder(); + builder.append(this.attribute, that.attribute); + builder.append(this.value, that.value); + return builder.isEquals(); + } else { + return false; + } + } + + /** + * Calculate the hash code for the attribute and the value. + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + HashCodeBuilder builder = new HashCodeBuilder(); + builder.append(attribute); + builder.append(value); + return builder.toHashCode(); + } + + /** + * Implement this method in subclass to return a String representing the + * operator. The {@link EqualsFilter#getCompareString()} would for example + * return an equals sign, "=". + * + * @return the String to use as operator in the comparison for the specific + * subclass. + */ + protected abstract String getCompareString(); +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java new file mode 100644 index 00000000..069d8186 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/EqualsFilter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + + +/** + * A filter for 'equals'. The following code: + * + *
+ * EqualsFilter filter = new EqualsFilter("cn", "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + *
(cn=Some CN)
+ * + * @author Adam Skogman + */ +public class EqualsFilter extends CompareFilter { + + private static final String EQUALS_SIGN = "="; + + public EqualsFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Convenience constructor for int values. + * + * @param attribute Name of attribute in filter. + * @param value The value of the attribute in the filter. + */ + public EqualsFilter(String attribute, int value) { + super(attribute, value); + } + + /* + * @see org.springframework.ldap.support.filter.CompareFilter#getCompareString() + */ + protected String getCompareString() { + return EQUALS_SIGN; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/Filter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/Filter.java new file mode 100644 index 00000000..a5ae4f69 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/Filter.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Common interface for filters. + * + * @author Adam Skogman + */ +public interface Filter { + + /** + * Encodes the filter to a string using the (@link #encode(StringBuffer) + * method. + * + * @return The encoded filter + */ + public String encode(); + + /** + * Prints the query with LDAP encoding to a stringbuffer + * + * @param buff + * The stringbuffer + * @return The very same stringbuffer + */ + public StringBuffer encode(StringBuffer buff); + + /** + * All filters must implement equals. + * + * @param o + * @return true if the objects are equal. + */ + public boolean equals(Object o); + + /** + * All filters must implement hashCode() + * + * @return hascode + */ + public int hashCode(); + +} \ No newline at end of file diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java new file mode 100644 index 00000000..871b8dd1 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter to compare >=. LDAP RFC does not allow > comparison. The following + * code: + * + *
+ * GreaterThanOrEqualsFilter filter = new GreaterThanOrEqualsFilter("cn",
+ *         "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ * (cn>=Some CN)
+ * 
+ * + * @author Mattias Arthursson + */ +public class GreaterThanOrEqualsFilter extends CompareFilter { + + private static final String GREATER_THAN_OR_EQUALS = ">="; + + public GreaterThanOrEqualsFilter(String attribute, String value) { + super(attribute, value); + } + + public GreaterThanOrEqualsFilter(String attribute, int value) { + super(attribute, value); + } + + protected String getCompareString() { + return GREATER_THAN_OR_EQUALS; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java new file mode 100644 index 00000000..36b5e723 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilter.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * A filter to compare <=. LDAP RFC does not allow < comparison. The following + * code: + * + *
+ * LessThanOrEqualsFilter filter = new LessThanOrEqualsFilter("cn", "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ * (cn<=Some CN)
+ * 
+ * + * @author Mattias Arthursson + */ +public class LessThanOrEqualsFilter extends CompareFilter { + + private static final String LESS_THAN_OR_EQUALS = "<="; + + public LessThanOrEqualsFilter(String attribute, String value) { + super(attribute, value); + } + + public LessThanOrEqualsFilter(String attribute, int value) { + super(attribute, value); + } + + protected String getCompareString() { + return LESS_THAN_OR_EQUALS; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java new file mode 100644 index 00000000..41d46ebd --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/LikeFilter.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.LdapEncoder; + +/** + * This filter allows the user to specify wildcards (*) by not escaping them in + * the filter. The following code: + * + *
+ * LikeFilter filter = new LikeFilter("cn", "foo*");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
+ *  (cn=foo*)
+ * 
+ * + * @author Anders Henja + * @author Mattias Arthursson + */ +public class LikeFilter extends EqualsFilter { + + public LikeFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Encodes a value according to the rules for this filter. + * + * @param value + * Value to encode. + * @return Encoded value. + */ + protected String encodeValue(String value) { + // just return if blank string + if (value == null) { + return ""; + } + + String[] substrings = value.split("\\*", -2); + + if (substrings.length == 1) { + return LdapEncoder.filterEncode(substrings[0]); + } + + StringBuffer buff = new StringBuffer(); + for (int i = 0; i < substrings.length; i++) { + buff.append(LdapEncoder.filterEncode(substrings[i])); + if (i < substrings.length - 1) { + buff.append("*"); + } else { + if (substrings[i].equals("")) { + continue; + } + } + } + + return buff.toString(); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/NotFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/NotFilter.java new file mode 100644 index 00000000..972edfa5 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/NotFilter.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.apache.commons.lang.Validate; + +/** + * A filter for 'not'. The following code: + * + *
+ * Filter filter = new NotFilter(new EqualsFilter("cn", "foo");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: + * + *
(!(cn=foo))
+ * + * @author Adam Skogman + */ +public class NotFilter extends AbstractFilter { + + private final Filter filter; + + static private final int HASH = "!".hashCode(); + + /** + * Create a filter that negates the outcome of the given filter. + * + * @param filter + * The filter that should be negated. + */ + public NotFilter(Filter filter) { + Validate.notNull(filter); + this.filter = filter; + } + + /** + * @see org.springframework.ldap.support.filter.Filter#encode(java.lang.StringBuffer) + */ + public StringBuffer encode(StringBuffer buff) { + + buff.append("(!"); + filter.encode(buff); + buff.append(')'); + + return buff; + + } + + /** + * Compares key and value before encoding + * + * @see org.springframework.ldap.support.filter.Filter#equals(java.lang.Object) + */ + public boolean equals(Object o) { + + if (o instanceof NotFilter && o.getClass() == this.getClass()) { + NotFilter f = (NotFilter) o; + return this.filter.equals(f.filter); + } + + return false; + } + + /** + * hash attribute and value + * + * @see org.springframework.ldap.support.filter.Filter#hashCode() + */ + public int hashCode() { + return HASH ^ filter.hashCode(); + } + +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/OrFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/OrFilter.java new file mode 100644 index 00000000..20ff1ddf --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/OrFilter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +/** + * Filter for logical OR. + * + *
+ *        AndFilter filter = new AndFilter();
+ *        filter.or(new EqualsFilter("objectclass", "person");
+ *        filter.or(new EqualsFilter("objectclass", "organizationalUnit");
+ *        System.out.println(filter.ecode());    
+ * 
+ * + * would result in: + * (|(objectclass=person)(objectclass=organizationalUnit)) + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class OrFilter extends BinaryLogicalFilter { + + private static final String PIPE_SIGN = "|"; + + /** + * Add a query to the OR expression + * + * @param query + * The query to or with the rest of the or:ed queries. + * @return This LdapOrQuery + */ + public OrFilter or(Filter query) { + queryList.add(query); + return this; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.support.filter.BinaryLogicalFilter#getLogicalOperator() + */ + protected String getLogicalOperator() { + return PIPE_SIGN; + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java new file mode 100644 index 00000000..bbd6b8d0 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilter.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; +import org.springframework.ldap.support.LdapEncoder; + +/** + * This filter automatically converts all whitespace to wildcards (*). The + * following code: + * + *
+ * WhitespaceWildcardsFilter filter = new WhitespaceWildcardsFilter("cn",
+ *         "Some CN");
+ * System.out.println(filter.ecode());
+ * 
+ * + * would result in: (cn=*Some*CN*) + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class WhitespaceWildcardsFilter extends EqualsFilter { + private static Pattern starReplacePattern = Pattern.compile("\\s+"); + + public WhitespaceWildcardsFilter(String attribute, String value) { + super(attribute, value); + } + + /** + * Encodes a value according to the rules for this filter. + * + * @param value + * Value to encode. + * @return Encoded value. + */ + protected String encodeValue(String value) { + + // blank string means just ONE star + if (StringUtils.isBlank(value)) { + return "*"; + } + + // trim value, we will add in stars first and last anywhay + value = value.trim(); + + // filter encode so that any stars etc. are preserved + String filterEncoded = LdapEncoder.filterEncode(value); + + // Now replace all whitespace with stars + Matcher m = starReplacePattern.matcher(filterEncoded); + + // possibly 2 longer (stars at ends) + StringBuffer buff = new StringBuffer(value.length() + 2); + + buff.append('*'); + + while (m.find()) { + m.appendReplacement(buff, "*"); + } + m.appendTail(buff); + + buff.append('*'); + + return buff.toString(); + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/filter/package.html b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/package.html new file mode 100644 index 00000000..e05a77ed --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/filter/package.html @@ -0,0 +1,16 @@ + +Utility classes for dynamically building LDAP +filters. Filters can be nested and wrapped around each other: +
+AndFilter andFilter = new AndFilter();
+andFilter.and(new EqualsFilter("objectclass", "person");
+andFilter.and(new EqualsFilter("cn", "Some CN");
+OrFilter orFilter = new OrFilter();
+orFilter.or(andFilter);
+orFilter.or(new EqualsFilter("objectclass", "organizationalUnit));
+System.out.println(orFilter.encode());
+
+would result in: + +
(|(&(objectclass=person)(cn=Some CN))(objectclass=organizationalUnit))
+ diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/package.html b/spring-ldap/src/main/java/org/springframework/ldap/support/package.html new file mode 100644 index 00000000..bf83afd5 --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/package.html @@ -0,0 +1,3 @@ + +Support classes for Spring-LDAP. + \ No newline at end of file diff --git a/spring-ldap/src/main/java/org/springframework/ldap/util/ListComparator.java b/spring-ldap/src/main/java/org/springframework/ldap/util/ListComparator.java new file mode 100644 index 00000000..0ea9857c --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/util/ListComparator.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.util; + +import java.util.Comparator; +import java.util.List; + +/** + * Comparator for comparing lists of Comparable objects. + * + * @author Mattias Arthursson + * + */ +public class ListComparator implements Comparator { + + /** + * Compare two lists of Comparable objects. + * + * @param o1 + * the first object to be compared. + * @param o2 + * the second object to be compared. + * @throws ClassCastException + * if either of the lists contains an object that is not + * Comparable. + */ + public int compare(Object o1, Object o2) { + List list1 = (List) o1; + List list2 = (List) o2; + + for (int i = 0; i < list1.size(); i++) { + if (list2.size() > i) { + Comparable component1 = (Comparable) list1.get(i); + Comparable component2 = (Comparable) list2.get(i); + int componentsCompared = component1.compareTo(component2); + if (componentsCompared != 0) { + return componentsCompared; + } + } else { + // First instance has more components, so that instance is + // greater. + return 1; + } + } + + // All components so far are equal - if the other instance has + // more components it is greater otherwise they are equal. + if (list2.size() > list1.size()) { + return -1; + } else { + return 0; + } + } +} diff --git a/spring-ldap/src/main/java/org/springframework/ldap/util/package.html b/spring-ldap/src/main/java/org/springframework/ldap/util/package.html new file mode 100644 index 00000000..b01effef --- /dev/null +++ b/spring-ldap/src/main/java/org/springframework/ldap/util/package.html @@ -0,0 +1,3 @@ + +Internal utility classes. + diff --git a/spring-ldap/src/main/java/overview.html b/spring-ldap/src/main/java/overview.html new file mode 100644 index 00000000..fe97647c --- /dev/null +++ b/spring-ldap/src/main/java/overview.html @@ -0,0 +1,3 @@ + +This document is the API specification for the Spring LDAP Framework. + \ No newline at end of file diff --git a/spring-ldap/src/main/javacc/DnParserImpl.jj b/spring-ldap/src/main/javacc/DnParserImpl.jj new file mode 100644 index 00000000..3660fcc3 --- /dev/null +++ b/spring-ldap/src/main/javacc/DnParserImpl.jj @@ -0,0 +1,165 @@ +/* + * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * California 95054, U.S.A. All rights reserved. Sun Microsystems, Inc. has + * intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, + * these intellectual property rights may include one or more of the U.S. + * patents listed at http://www.sun.com/patents and one or more additional + * patents or pending patent applications in the U.S. and in other countries. + * U.S. Government Rights - Commercial software. Government users are subject + * to the Sun Microsystems, Inc. standard license agreement and applicable + * provisions of the FAR and its supplements. Use is subject to license terms. + * Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered + * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This + * product is covered and controlled by U.S. Export Control laws and may be + * subject to the export or import laws in other countries. Nuclear, missile, + * chemical biological weapons or nuclear maritime end uses or end users, + * whether direct or indirect, are strictly prohibited. Export or reexport + * to countries subject to U.S. embargo or to entities identified on U.S. + * export exclusion lists, including, but not limited to, the denied persons + * and specially designated nationals lists is strictly prohibited. + */ + + +options { + LOOKAHEAD = 1; + CHOICE_AMBIGUITY_CHECK = 3; + OTHER_AMBIGUITY_CHECK = 3; + STATIC = false; + DEBUG_PARSER = false; + DEBUG_LOOKAHEAD = false; + DEBUG_TOKEN_MANAGER = false; + ERROR_REPORTING = true; + JAVA_UNICODE_ESCAPE = false; + UNICODE_INPUT = true; + IGNORE_CASE = false; + USER_TOKEN_MANAGER = false; + USER_CHAR_STREAM = false; + BUILD_PARSER = true; + BUILD_TOKEN_MANAGER = true; + SANITY_CHECK = true; + FORCE_LA_CHECK = true; +} + +PARSER_BEGIN(DnParserImpl) + +package org.springframework.ldap.support; + +import org.springframework.ldap.support.LdapRdn; +import org.springframework.ldap.support.LdapRdnComponent; +import org.springframework.ldap.support.DistinguishedName; + +public class DnParserImpl implements DnParser{ + +} + +PARSER_END(DnParserImpl) + +TOKEN: { <#ALPHA: ["a"-"z", "A"-"Z"] > } +TOKEN: { <#DIGIT: ["0"-"9"]> } +TOKEN: { <#STRINGCHAR: ~[",","=","\r","+","<",">","#",";","\\","\""]> } +TOKEN: { <#STRINGENDCHAR: ~[",","=","\r","+","<",">","#",";","\\","\""," "]> } +TOKEN: { <#SPECIAL: [",","=","\r","+","<",">","#",";"]> } +TOKEN: { <#HEXCHAR: ["0"-"9","a"-"f","A"-"F"]> } +TOKEN: { <#HEXPAIR: > } +TOKEN: { <#BACKSLASHCHAR: "\\"> } +TOKEN: { <#PAIR: ( | | | )> } +TOKEN: { <#ESCAPEDSPACE: >} +TOKEN: { <#ESCAPEDSTART: ( | )> } +TOKEN: { <#STRINGEND: ( | | )> } + + TOKEN: +{ + + | + + | + ( | | "-")*> + | + )+ ("." ()+ )* > + | + +} + + TOKEN: +{ + ( | | )+ + | + ()+ + | + ()? ( | )* + )> +} + + TOKEN: +{ + )* "=" ()*> +} + +/** + * input -> dn + * dn -> rdn ( ( "," | ";" ) rdn )* + * rdn -> attributeTypeAndValue ( "+" attributeTypeAndValue )* + * attributeTypeAndValue -> + * ( )* AttributeType SpacedEquals AttributeValue ( )* + * SpacedEquals -> + * AttributeType -> | + * AttributeValue -> + */ +void input() : +{ +} +{ + dn() +} + +DistinguishedName dn(): +{ +DistinguishedName dn = new DistinguishedName(); +LdapRdn rdn; +} +{ + ( rdn = rdn() {dn.add(0, rdn);} (("," | ";") rdn = rdn() {dn.add(0, rdn);})* ) + {return dn;} +} + +LdapRdn rdn(): +{ +LdapRdnComponent rdnComponent; +LdapRdn rdn = new LdapRdn(); +} +{ + (rdnComponent = attributeTypeAndValue() {rdn.addComponent(rdnComponent);} ("+" rdnComponent = attributeTypeAndValue() {rdn.addComponent(rdnComponent);})*) + {return rdn;} +} + +LdapRdnComponent attributeTypeAndValue(): +{ +String attributeType; +String value; +} +{ + ( ()* attributeType = AttributeType() SpacedEquals() value = AttributeValue() ()*) + {return new LdapRdnComponent(attributeType, value, true);} +} + +void SpacedEquals(): +{} +{ + {token_source.SwitchTo(SPACED_EQUALS_S);} +} + +String AttributeType(): +{Token t;} +{ + ( t = | t = ) + {return t.image.toString();} +} + +String AttributeValue(): +{Token t;} +{ + {token_source.SwitchTo(ATTRVALUE_S);} t = {token_source.SwitchTo(DEFAULT);} + {return t.image.toString();} +} \ No newline at end of file diff --git a/spring-ldap/src/test/java/org/springframework/ldap/CollectingNameClassPairCallbackHandlerTest.java b/spring-ldap/src/test/java/org/springframework/ldap/CollectingNameClassPairCallbackHandlerTest.java new file mode 100644 index 00000000..2328454e --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/CollectingNameClassPairCallbackHandlerTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.NameClassPair; + +import junit.framework.TestCase; + +public class CollectingNameClassPairCallbackHandlerTest extends TestCase { + + private CollectingNameClassPairCallbackHandler tested; + + private Object expectedResult; + + private NameClassPair expectedNameClassPair; + + protected void setUp() throws Exception { + super.setUp(); + + expectedResult = new Object(); + expectedNameClassPair = new NameClassPair(null, null); + tested = new CollectingNameClassPairCallbackHandler() { + public Object getObjectFromNameClassPair(NameClassPair nameClassPair) { + assertSame(expectedNameClassPair, nameClassPair); + return expectedResult; + } + }; + } + + protected void tearDown() throws Exception { + super.tearDown(); + + expectedNameClassPair = null; + expectedResult = null; + tested = null; + } + + public void testHandleNameClassPair() { + tested.handleNameClassPair(expectedNameClassPair); + List result = tested.getList(); + assertEquals(1, result.size()); + assertSame(expectedResult, result.get(0)); + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateListTest.java b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateListTest.java new file mode 100644 index 00000000..d1e3b942 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateListTest.java @@ -0,0 +1,439 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.PartialResultException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.LdapContext; + +import junit.framework.TestCase; + +import org.easymock.MockControl; + +/** + * Unit tests for the list operations in {@link LdapTemplate}. + * + * @author Ulrik Sandberg + */ +public class LdapTemplateListTest extends TestCase { + + private static final String NAME = "o=example.com"; + + private static final String CLASS = "com.example.SomeClass"; + + private MockControl contextSourceControl; + + private ContextSource contextSourceMock; + + private MockControl dirContextControl; + + private DirContext dirContextMock; + + private MockControl namingEnumerationControl; + + private NamingEnumeration namingEnumerationMock; + + private MockControl nameControl; + + private Name nameMock; + + private MockControl handlerControl; + + private NameClassPairCallbackHandler handlerMock; + + private MockControl contextMapperControl; + + private ContextMapper contextMapperMock; + + private MockControl exceptionTranslatorControl; + + private NamingExceptionTranslator exceptionTranslatorMock; + + private LdapTemplate tested; + + protected void setUp() throws Exception { + super.setUp(); + + // Setup ContextSource mock + contextSourceControl = MockControl.createControl(ContextSource.class); + contextSourceMock = (ContextSource) contextSourceControl.getMock(); + + // Setup LdapContext mock + dirContextControl = MockControl.createControl(LdapContext.class); + dirContextMock = (LdapContext) dirContextControl.getMock(); + + // Setup NamingEnumeration mock + namingEnumerationControl = MockControl + .createControl(NamingEnumeration.class); + namingEnumerationMock = (NamingEnumeration) namingEnumerationControl + .getMock(); + + // Setup Name mock + nameControl = MockControl.createControl(Name.class); + nameMock = (Name) nameControl.getMock(); + + // Setup Handler mock + handlerControl = MockControl + .createControl(NameClassPairCallbackHandler.class); + handlerMock = (NameClassPairCallbackHandler) handlerControl.getMock(); + + contextMapperControl = MockControl.createControl(ContextMapper.class); + contextMapperMock = (ContextMapper) contextMapperControl.getMock(); + + exceptionTranslatorControl = MockControl + .createControl(NamingExceptionTranslator.class); + exceptionTranslatorMock = (NamingExceptionTranslator) exceptionTranslatorControl + .getMock(); + + tested = new LdapTemplate(contextSourceMock); + tested.setExceptionTranslator(exceptionTranslatorMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + contextSourceControl = null; + contextSourceMock = null; + + dirContextControl = null; + dirContextMock = null; + + namingEnumerationControl = null; + namingEnumerationMock = null; + + nameControl = null; + nameMock = null; + + handlerControl = null; + handlerMock = null; + + contextMapperControl = null; + contextMapperMock = null; + + exceptionTranslatorControl = null; + exceptionTranslatorMock = null; + } + + protected void replay() { + contextSourceControl.replay(); + dirContextControl.replay(); + namingEnumerationControl.replay(); + nameControl.replay(); + handlerControl.replay(); + contextMapperControl.replay(); + exceptionTranslatorControl.replay(); + } + + protected void verify() { + contextSourceControl.verify(); + dirContextControl.verify(); + namingEnumerationControl.verify(); + nameControl.verify(); + handlerControl.verify(); + contextMapperControl.verify(); + exceptionTranslatorControl.verify(); + } + + private void expectGetReadOnlyContext() { + contextSourceControl.expectAndReturn(contextSourceMock + .getReadOnlyContext(), dirContextMock); + } + + private void setupStringListAndNamingEnumeration(NameClassPair listResult) + throws NamingException { + dirContextControl.expectAndReturn(dirContextMock.list(NAME), + namingEnumerationMock); + + setupNamingEnumeration(listResult); + } + + private void setupListAndNamingEnumeration(NameClassPair listResult) + throws NamingException { + dirContextControl.expectAndReturn(dirContextMock.list(nameMock), + namingEnumerationMock); + + setupNamingEnumeration(listResult); + } + + private void setupStringListBindingsAndNamingEnumeration(NameClassPair listResult) + throws NamingException { + dirContextControl.expectAndReturn(dirContextMock.listBindings(NAME), + namingEnumerationMock); + + setupNamingEnumeration(listResult); + } + + private void setupListBindingsAndNamingEnumeration(NameClassPair listResult) + throws NamingException { + dirContextControl.expectAndReturn(dirContextMock.listBindings(nameMock), + namingEnumerationMock); + + setupNamingEnumeration(listResult); + } + + private void setupNamingEnumeration(NameClassPair listResult) + throws NamingException { + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + listResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + } + + public void testList_Name() throws NamingException { + expectGetReadOnlyContext(); + + NameClassPair listResult = new NameClassPair(NAME, CLASS); + + setupListAndNamingEnumeration(listResult); + + dirContextMock.close(); + + replay(); + + List list = tested.list(nameMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(NAME, list.get(0)); + } + + public void testList_String() throws NamingException { + expectGetReadOnlyContext(); + + NameClassPair listResult = new NameClassPair(NAME, CLASS); + + setupStringListAndNamingEnumeration(listResult); + + dirContextMock.close(); + + replay(); + + List list = tested.list(NAME); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(NAME, list.get(0)); + } + + public void testList_Name_CallbackHandler() throws NamingException { + expectGetReadOnlyContext(); + + NameClassPair listResult = new NameClassPair(NAME, CLASS); + + setupListAndNamingEnumeration(listResult); + + handlerMock.handleNameClassPair(listResult); + + dirContextMock.close(); + + replay(); + + tested.list(nameMock, handlerMock); + + verify(); + } + + public void testList_String_CallbackHandler() throws NamingException { + expectGetReadOnlyContext(); + + NameClassPair listResult = new NameClassPair(NAME, CLASS); + + setupStringListAndNamingEnumeration(listResult); + + handlerMock.handleNameClassPair(listResult); + + dirContextMock.close(); + + replay(); + + tested.list("o=example.com", handlerMock); + + verify(); + } + + public void testList_PartialResultException() throws NamingException { + expectGetReadOnlyContext(); + + PartialResultException pre = new PartialResultException(); + dirContextControl.expectAndThrow(dirContextMock.list(NAME), pre); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(pre), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.list(NAME); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testList_PartialResultException_Ignore() throws NamingException { + expectGetReadOnlyContext(); + + PartialResultException pre = new PartialResultException(); + dirContextControl.expectAndThrow(dirContextMock.list(NAME), pre); + + dirContextMock.close(); + + tested.setIgnorePartialResultException(true); + + replay(); + + List list = tested.list(NAME); + + verify(); + + assertNotNull(list); + assertEquals(0, list.size()); + } + + public void testList_NamingException() throws NamingException { + expectGetReadOnlyContext(); + + NamingException ne = new NamingException(); + dirContextControl.expectAndThrow(dirContextMock.list(NAME), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.list(NAME); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + // Tests for listBindings + + public void testListBindings_String() throws NamingException { + expectGetReadOnlyContext(); + + Binding listResult = new Binding(NAME, CLASS, null); + + setupStringListBindingsAndNamingEnumeration(listResult); + + dirContextMock.close(); + + replay(); + + List list = tested.listBindings(NAME); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(NAME, list.get(0)); + } + + public void testListBindings_Name() throws NamingException { + expectGetReadOnlyContext(); + + Binding listResult = new Binding(NAME, CLASS, null); + + setupListBindingsAndNamingEnumeration(listResult); + + dirContextMock.close(); + + replay(); + + List list = tested.listBindings(nameMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(NAME, list.get(0)); + } + + public void testListBindings_ContextMapper() throws NamingException { + expectGetReadOnlyContext(); + + Object expectedObject = new Object(); + Binding listResult = new Binding("", expectedObject); + + setupStringListBindingsAndNamingEnumeration(listResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.listBindings(NAME, contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testListBindings_Name_ContextMapper() throws NamingException { + expectGetReadOnlyContext(); + + Object expectedObject = new Object(); + Binding listResult = new Binding("", expectedObject); + + setupListBindingsAndNamingEnumeration(listResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.listBindings(nameMock, contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateLookupTest.java b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateLookupTest.java new file mode 100644 index 00000000..8f151426 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateLookupTest.java @@ -0,0 +1,453 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.ldap.LdapContext; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; + +public class LdapTemplateLookupTest extends TestCase { + + private static final String DEFAULT_BASE_STRING = "o=example.com"; + + private MockControl contextSourceControl; + + private ContextSource contextSourceMock; + + private MockControl dirContextControl; + + private DirContext dirContextMock; + + private MockControl attributesMapperControl; + + private AttributesMapper attributesMapperMock; + + private MockControl nameControl; + + private Name nameMock; + + private MockControl contextMapperControl; + + private ContextMapper contextMapperMock; + + private MockControl exceptionTranslatorControl; + + private NamingExceptionTranslator exceptionTranslatorMock; + + private LdapTemplate tested; + + protected void setUp() throws Exception { + super.setUp(); + + // Setup ContextSource mock + contextSourceControl = MockControl.createControl(ContextSource.class); + contextSourceMock = (ContextSource) contextSourceControl.getMock(); + + // Setup LdapContext mock + dirContextControl = MockControl.createControl(LdapContext.class); + dirContextMock = (LdapContext) dirContextControl.getMock(); + + // Setup Name mock + nameControl = MockControl.createControl(Name.class); + nameMock = (Name) nameControl.getMock(); + + contextMapperControl = MockControl.createControl(ContextMapper.class); + contextMapperMock = (ContextMapper) contextMapperControl.getMock(); + + attributesMapperControl = MockControl + .createControl(AttributesMapper.class); + attributesMapperMock = (AttributesMapper) attributesMapperControl + .getMock(); + + exceptionTranslatorControl = MockControl + .createControl(NamingExceptionTranslator.class); + exceptionTranslatorMock = (NamingExceptionTranslator) exceptionTranslatorControl + .getMock(); + + tested = new LdapTemplate(contextSourceMock); + tested.setExceptionTranslator(exceptionTranslatorMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + contextSourceControl = null; + contextSourceMock = null; + + dirContextControl = null; + dirContextMock = null; + + nameControl = null; + nameMock = null; + + contextMapperControl = null; + contextMapperMock = null; + + attributesMapperControl = null; + attributesMapperMock = null; + + exceptionTranslatorControl = null; + exceptionTranslatorMock = null; + } + + protected void replay() { + contextSourceControl.replay(); + dirContextControl.replay(); + nameControl.replay(); + contextMapperControl.replay(); + attributesMapperControl.replay(); + exceptionTranslatorControl.replay(); + } + + protected void verify() { + contextSourceControl.verify(); + dirContextControl.verify(); + nameControl.verify(); + contextMapperControl.verify(); + attributesMapperControl.verify(); + exceptionTranslatorControl.verify(); + } + + private void expectGetReadOnlyContext() { + contextSourceControl.expectAndReturn(contextSourceMock + .getReadOnlyContext(), dirContextMock); + } + + // Tests for lookup(name) + + public void testLookup() throws NamingException { + expectGetReadOnlyContext(); + + Object expected = new Object(); + dirContextControl.expectAndReturn(dirContextMock.lookup(nameMock), + expected); + + dirContextMock.close(); + + replay(); + + Object actual = tested.lookup(nameMock); + + verify(); + + assertSame(expected, actual); + } + + public void testLookup_String() throws NamingException { + expectGetReadOnlyContext(); + + Object expected = new Object(); + dirContextControl.expectAndReturn(dirContextMock + .lookup(DEFAULT_BASE_STRING), expected); + + dirContextMock.close(); + + replay(); + + Object actual = tested.lookup(DEFAULT_BASE_STRING); + + verify(); + + assertSame(expected, actual); + } + + public void testLookup_NamingException() throws NamingException { + expectGetReadOnlyContext(); + + NamingException ne = new NamingException(); + dirContextControl.expectAndThrow(dirContextMock.lookup(nameMock), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.lookup(nameMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + // Tests for lookup(name, AttributesMapper) + + public void testLookup_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); + + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextControl.expectAndReturn(dirContextMock + .getAttributes(nameMock), expectedAttributes); + dirContextMock.close(); + + Object expected = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expected); + + replay(); + + Object actual = tested.lookup(nameMock, attributesMapperMock); + + verify(); + + assertSame(expected, actual); + } + + public void testLookup_String_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); + + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextControl.expectAndReturn(dirContextMock + .getAttributes(DEFAULT_BASE_STRING), expectedAttributes); + dirContextMock.close(); + + Object expected = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expected); + + replay(); + + Object actual = tested + .lookup(DEFAULT_BASE_STRING, attributesMapperMock); + + verify(); + + assertSame(expected, actual); + } + + public void testLookup_AttributesMapper_NamingException() throws Exception { + expectGetReadOnlyContext(); + + NamingException ne = new NamingException(); + dirContextControl.expectAndThrow( + dirContextMock.getAttributes(nameMock), ne); + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.lookup(nameMock, attributesMapperMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + // Tests for lookup(name, ContextMapper) + + public void testLookup_ContextMapper() throws Exception { + expectGetReadOnlyContext(); + + Object transformed = new Object(); + Object expected = new Object(); + dirContextControl.expectAndReturn(dirContextMock.lookup(nameMock), + expected); + + dirContextMock.close(); + + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expected), transformed); + + replay(); + + Object actual = tested.lookup(nameMock, contextMapperMock); + + verify(); + + assertSame(transformed, actual); + } + + public void testLookup_String_ContextMapper() throws Exception { + expectGetReadOnlyContext(); + + Object transformed = new Object(); + Object expected = new Object(); + dirContextControl.expectAndReturn(dirContextMock + .lookup(DEFAULT_BASE_STRING), expected); + + dirContextMock.close(); + + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expected), transformed); + + replay(); + + Object actual = tested.lookup(DEFAULT_BASE_STRING, contextMapperMock); + + verify(); + + assertSame(transformed, actual); + } + + public void testLookup_ContextMapper_NamingException() throws Exception { + expectGetReadOnlyContext(); + + NameNotFoundException ne = new NameNotFoundException(); + dirContextControl.expectAndThrow(dirContextMock.lookup(nameMock), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.lookup(nameMock, contextMapperMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + // Tests for lookup(name, attributes, AttributesMapper) + + public void testLookup_ReturnAttributes_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); + + String[] attributeNames = new String[] { "cn" }; + + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("cn", "Some Name"); + + dirContextControl.expectAndReturn(dirContextMock.getAttributes( + nameMock, attributeNames), expectedAttributes); + dirContextMock.close(); + + Object expected = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expected); + + replay(); + + Object actual = tested.lookup(nameMock, attributeNames, + attributesMapperMock); + + verify(); + + assertSame(expected, actual); + } + + public void testLookup_String_ReturnAttributes_AttributesMapper() + throws Exception { + expectGetReadOnlyContext(); + + String[] attributeNames = new String[] { "cn" }; + + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("cn", "Some Name"); + + dirContextControl.expectAndReturn(dirContextMock.getAttributes( + DEFAULT_BASE_STRING, attributeNames), expectedAttributes); + dirContextMock.close(); + + Object expected = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expected); + + replay(); + + Object actual = tested.lookup(DEFAULT_BASE_STRING, attributeNames, + attributesMapperMock); + + verify(); + + assertSame(expected, actual); + } + + // Tests for lookup(name, attributes, ContextMapper) + + public void testLookup_ReturnAttributes_ContextMapper() throws Exception { + expectGetReadOnlyContext(); + + String[] attributeNames = new String[] { "cn" }; + + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("cn", "Some Name"); + + DistinguishedName name = new DistinguishedName(DEFAULT_BASE_STRING); + DirContextAdapter adapter = new DirContextAdapter(expectedAttributes, + name); + + dirContextControl.expectAndReturn(dirContextMock.getAttributes(name, + attributeNames), expectedAttributes); + dirContextMock.close(); + + Object transformed = new Object(); + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(adapter), transformed); + + replay(); + + Object actual = tested.lookup(name, attributeNames, contextMapperMock); + + verify(); + + assertSame(transformed, actual); + } + + public void testLookup_String_ReturnAttributes_ContextMapper() + throws Exception { + expectGetReadOnlyContext(); + + String[] attributeNames = new String[] { "cn" }; + + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("cn", "Some Name"); + + dirContextControl.expectAndReturn(dirContextMock.getAttributes( + DEFAULT_BASE_STRING, attributeNames), expectedAttributes); + dirContextMock.close(); + + DistinguishedName name = new DistinguishedName(DEFAULT_BASE_STRING); + DirContextAdapter adapter = new DirContextAdapter(expectedAttributes, + name); + + Object transformed = new Object(); + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(adapter), transformed); + + replay(); + + Object actual = tested.lookup(DEFAULT_BASE_STRING, attributeNames, + contextMapperMock); + + verify(); + + assertSame(transformed, actual); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateRenameTest.java b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateRenameTest.java new file mode 100644 index 00000000..459c9be7 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateRenameTest.java @@ -0,0 +1,198 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.Name; +import javax.naming.NameAlreadyBoundException; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.LdapContext; + +import junit.framework.TestCase; + + +import org.easymock.MockControl; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.ldap.ContextSource; +import org.springframework.ldap.LdapTemplate; +import org.springframework.ldap.NamingExceptionTranslator; +import org.springframework.ldap.UncategorizedLdapException; + +/** + * Unit tests for the rename operations in the LdapTemplate class. + * + * @author Ulrik Sandberg + */ +public class LdapTemplateRenameTest extends TestCase { + + private MockControl contextSourceControl; + + private ContextSource contextSourceMock; + + private MockControl dirContextControl; + + private DirContext dirContextMock; + + private MockControl oldNameControl; + + private Name oldNameMock; + + private MockControl newNameControl; + + private Name newNameMock; + + private MockControl exceptionTranslatorControl; + + private NamingExceptionTranslator exceptionTranslatorMock; + + private LdapTemplate tested; + + protected void setUp() throws Exception { + super.setUp(); + + // Setup ContextSource mock + contextSourceControl = MockControl.createControl(ContextSource.class); + contextSourceMock = (ContextSource) contextSourceControl.getMock(); + + // Setup LdapContext mock + dirContextControl = MockControl.createControl(LdapContext.class); + dirContextMock = (LdapContext) dirContextControl.getMock(); + + // Setup Name mock for old name + oldNameControl = MockControl.createControl(Name.class); + oldNameMock = (Name) oldNameControl.getMock(); + + // Setup Name mock for new name + newNameControl = MockControl.createControl(Name.class); + newNameMock = (Name) newNameControl.getMock(); + + exceptionTranslatorControl = MockControl + .createControl(NamingExceptionTranslator.class); + exceptionTranslatorMock = (NamingExceptionTranslator) exceptionTranslatorControl + .getMock(); + + tested = new LdapTemplate(contextSourceMock); + tested.setExceptionTranslator(exceptionTranslatorMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + contextSourceControl = null; + contextSourceMock = null; + + dirContextControl = null; + dirContextMock = null; + + oldNameControl = null; + newNameMock = null; + + exceptionTranslatorControl = null; + exceptionTranslatorMock = null; + } + + protected void replay() { + contextSourceControl.replay(); + dirContextControl.replay(); + oldNameControl.replay(); + exceptionTranslatorControl.replay(); + } + + protected void verify() { + contextSourceControl.verify(); + dirContextControl.verify(); + oldNameControl.verify(); + exceptionTranslatorControl.verify(); + } + + private void expectGetReadWriteContext() { + contextSourceControl.expectAndReturn(contextSourceMock + .getReadWriteContext(), dirContextMock); + } + + public void testRename() throws NamingException { + expectGetReadWriteContext(); + + dirContextMock.rename(oldNameMock, newNameMock); + dirContextMock.close(); + + replay(); + + tested.rename(oldNameMock, newNameMock); + + verify(); + } + + public void testRename_NameAlreadyBoundException() throws Exception { + expectGetReadWriteContext(); + + dirContextMock.rename(oldNameMock, newNameMock); + NameAlreadyBoundException ne = new NameAlreadyBoundException(); + dirContextControl.setThrowable(ne); + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new DataIntegrityViolationException("dummy")); + + replay(); + + try { + tested.rename(oldNameMock, newNameMock); + fail("DataIntegrityViolationException expected"); + } catch (DataIntegrityViolationException expected) { + assertTrue(true); + } + + verify(); + } + + public void testRename_NamingException() throws Exception { + expectGetReadWriteContext(); + + dirContextMock.rename(oldNameMock, newNameMock); + NamingException ne = new NamingException(); + dirContextControl.setThrowable(ne); + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new UncategorizedLdapException("dummy", ne)); + + replay(); + + try { + tested.rename(oldNameMock, newNameMock); + fail("UncategorizedLdapException expected"); + } catch (UncategorizedLdapException expected) { + assertTrue(true); + } + + verify(); + } + + public void testRename_String() throws NamingException { + expectGetReadWriteContext(); + + dirContextMock.rename("o=example.com", "o=somethingelse.com"); + dirContextMock.close(); + + replay(); + + tested.rename("o=example.com", "o=somethingelse.com"); + + verify(); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateTest.java b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateTest.java new file mode 100644 index 00000000..e7c78259 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/LdapTemplateTest.java @@ -0,0 +1,1708 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import java.util.List; + +import javax.naming.Binding; +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.PartialResultException; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.naming.ldap.LdapContext; + +import junit.framework.TestCase; + +import org.easymock.AbstractMatcher; +import org.easymock.MockControl; +import org.springframework.ldap.support.DistinguishedName; + +public class LdapTemplateTest extends TestCase { + + private static final String DEFAULT_BASE_STRING = "o=example.com"; + + private MockControl contextSourceControl; + + private ContextSource contextSourceMock; + + private MockControl dirContextControl; + + private DirContext dirContextMock; + + private MockControl attributesMapperControl; + + private AttributesMapper attributesMapperMock; + + private MockControl namingEnumerationControl; + + private NamingEnumeration namingEnumerationMock; + + private MockControl nameControl; + + private Name nameMock; + + private MockControl handlerControl; + + private NameClassPairCallbackHandler handlerMock; + + private MockControl contextMapperControl; + + private ContextMapper contextMapperMock; + + private MockControl exceptionTranslatorControl; + + private NamingExceptionTranslator exceptionTranslatorMock; + + private MockControl contextExecutorControl; + + private ContextExecutor contextExecutorMock; + + private MockControl searchExecutorControl; + + private SearchExecutor searchExecutorMock; + + private LdapTemplate tested; + + private MockControl dirContextProcessorControl; + + private DirContextProcessor dirContextProcessorMock; + + protected void setUp() throws Exception { + super.setUp(); + + // Setup ContextSource mock + contextSourceControl = MockControl.createControl(ContextSource.class); + contextSourceMock = (ContextSource) contextSourceControl.getMock(); + + // Setup LdapContext mock + dirContextControl = MockControl.createControl(LdapContext.class); + dirContextMock = (LdapContext) dirContextControl.getMock(); + + // Setup NamingEnumeration mock + namingEnumerationControl = MockControl + .createControl(NamingEnumeration.class); + namingEnumerationMock = (NamingEnumeration) namingEnumerationControl + .getMock(); + + // Setup Name mock + nameControl = MockControl.createControl(Name.class); + nameMock = (Name) nameControl.getMock(); + + // Setup Handler mock + handlerControl = MockControl + .createControl(NameClassPairCallbackHandler.class); + handlerMock = (NameClassPairCallbackHandler) handlerControl.getMock(); + + contextMapperControl = MockControl.createControl(ContextMapper.class); + contextMapperMock = (ContextMapper) contextMapperControl.getMock(); + + attributesMapperControl = MockControl + .createControl(AttributesMapper.class); + attributesMapperMock = (AttributesMapper) attributesMapperControl + .getMock(); + + exceptionTranslatorControl = MockControl + .createControl(NamingExceptionTranslator.class); + exceptionTranslatorMock = (NamingExceptionTranslator) exceptionTranslatorControl + .getMock(); + + contextExecutorControl = MockControl + .createControl(ContextExecutor.class); + contextExecutorMock = (ContextExecutor) contextExecutorControl + .getMock(); + + searchExecutorControl = MockControl.createControl(SearchExecutor.class); + searchExecutorMock = (SearchExecutor) searchExecutorControl.getMock(); + + dirContextProcessorControl = MockControl + .createControl(DirContextProcessor.class); + dirContextProcessorMock = (DirContextProcessor) dirContextProcessorControl + .getMock(); + + tested = new LdapTemplate(contextSourceMock); + tested.setExceptionTranslator(exceptionTranslatorMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + contextSourceControl = null; + contextSourceMock = null; + + dirContextControl = null; + dirContextMock = null; + + namingEnumerationControl = null; + namingEnumerationMock = null; + + nameControl = null; + nameMock = null; + + handlerControl = null; + handlerMock = null; + + contextMapperControl = null; + contextMapperMock = null; + + attributesMapperControl = null; + attributesMapperMock = null; + + exceptionTranslatorControl = null; + exceptionTranslatorMock = null; + + contextExecutorControl = null; + contextExecutorMock = null; + + searchExecutorControl = null; + searchExecutorMock = null; + + dirContextProcessorControl = null; + dirContextProcessorMock = null; + } + + protected void replay() { + contextSourceControl.replay(); + dirContextControl.replay(); + namingEnumerationControl.replay(); + nameControl.replay(); + handlerControl.replay(); + contextMapperControl.replay(); + attributesMapperControl.replay(); + exceptionTranslatorControl.replay(); + contextExecutorControl.replay(); + searchExecutorControl.replay(); + dirContextProcessorControl.replay(); + } + + protected void verify() { + contextSourceControl.verify(); + dirContextControl.verify(); + namingEnumerationControl.verify(); + nameControl.verify(); + handlerControl.verify(); + contextMapperControl.verify(); + attributesMapperControl.verify(); + exceptionTranslatorControl.verify(); + contextExecutorControl.verify(); + searchExecutorControl.verify(); + dirContextProcessorControl.verify(); + } + + private void expectGetReadWriteContext() { + contextSourceControl.expectAndReturn(contextSourceMock + .getReadWriteContext(), dirContextMock); + } + + private void expectGetReadOnlyContext() { + contextSourceControl.expectAndReturn(contextSourceMock + .getReadOnlyContext(), dirContextMock); + } + + public void testSearch_CallbackHandler() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + + SearchResult searchResult = new SearchResult("", new Object(), + new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + handlerMock.handleNameClassPair(searchResult); + + dirContextMock.close(); + + replay(); + + tested.search(nameMock, "(ou=somevalue)", 1, true, handlerMock); + + verify(); + } + + public void testSearch_StringBase_CallbackHandler() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + + SearchResult searchResult = new SearchResult("", new Object(), + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + handlerMock.handleNameClassPair(searchResult); + + dirContextMock.close(); + + replay(); + + tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, true, + handlerMock); + + verify(); + } + + private void setupStringSearchAndNamingEnumeration(SearchControls controls, + SearchResult searchResult) throws NamingException { + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndReturn(dirContextMock.search( + DEFAULT_BASE_STRING, "(ou=somevalue)", controls), + namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + } + + public void testSearch_CallbackHandler_Defaults() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + SearchResult searchResult = new SearchResult("", new Object(), + new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + handlerMock.handleNameClassPair(searchResult); + + dirContextMock.close(); + + replay(); + + tested.search(nameMock, "(ou=somevalue)", handlerMock); + + verify(); + } + + public void testSearch_String_CallbackHandler_Defaults() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + SearchResult searchResult = new SearchResult("", new Object(), + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + handlerMock.handleNameClassPair(searchResult); + + dirContextMock.close(); + + replay(); + + tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", handlerMock); + + verify(); + } + + private void setupSearchAndNamingEnumeration(SearchControls controls, + SearchResult searchResult) throws NamingException { + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndReturn(dirContextMock.search(nameMock, + "(ou=somevalue)", controls), namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + } + + public void testSearch_NameNotFoundException() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndThrow(dirContextMock.search(nameMock, + "(ou=somevalue)", controls), new NameNotFoundException()); + + dirContextMock.close(); + + replay(); + + tested.search(nameMock, "(ou=somevalue)", handlerMock); + + verify(); + } + + public void testSearch_NamingException() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + NamingException ne = new NamingException(); + dirContextControl.expectAndThrow(dirContextMock.search(nameMock, + "(ou=somevalue)", controls), ne); + + dirContextMock.close(); + + EntryNotFoundException expectedException = new EntryNotFoundException( + "dummy"); + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), expectedException); + + replay(); + + try { + tested.search(nameMock, "(ou=somevalue)", handlerMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertSame(expectedException, expected); + } + + verify(); + } + + public void testSearch_CallbackHandler_DirContextProcessor() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + SearchResult searchResult = new SearchResult("", new Object(), + new BasicAttributes()); + + dirContextProcessorMock.preProcess(dirContextMock); + + setupSearchAndNamingEnumeration(controls, searchResult); + + handlerMock.handleNameClassPair(searchResult); + + dirContextProcessorMock.postProcess(dirContextMock); + + dirContextMock.close(); + + replay(); + + tested.search(nameMock, "(ou=somevalue)", controls, handlerMock, + dirContextProcessorMock); + + verify(); + } + + public void testSearch_String_CallbackHandler_DirContextProcessor() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + SearchResult searchResult = new SearchResult("", new Object(), + new BasicAttributes()); + + dirContextProcessorMock.preProcess(dirContextMock); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + handlerMock.handleNameClassPair(searchResult); + + dirContextProcessorMock.postProcess(dirContextMock); + + dirContextMock.close(); + + replay(); + + tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, + handlerMock, dirContextProcessorMock); + + verify(); + } + + public void testSearch_String_AttributesMapper_DirContextProcessor() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + dirContextProcessorMock.preProcess(dirContextMock); + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + controls, attributesMapperMock, dirContextProcessorMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_Name_AttributesMapper_DirContextProcessor() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + dirContextProcessorMock.preProcess(dirContextMock); + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", controls, + attributesMapperMock, dirContextProcessorMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_SearchControls_ContextMapper_DirContextProcessor() + throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + dirContextProcessorMock.preProcess(dirContextMock); + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + controls, contextMapperMock, dirContextProcessorMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_Name_SearchControls_ContextMapper_DirContextProcessor() + throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + dirContextProcessorMock.preProcess(dirContextMock); + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", + controls, contextMapperMock, dirContextProcessorMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_AttributesMapper_ReturningAttrs() + throws NamingException { + expectGetReadOnlyContext(); + + String[] attrs = new String[0]; + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + controls.setReturningAttributes(attrs); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", 1, attrs, + attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_AttributesMapper_ReturningAttrs() + throws NamingException { + expectGetReadOnlyContext(); + + String[] attrs = new String[0]; + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + controls.setReturningAttributes(attrs); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, + attrs, attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_AttributesMapper() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", 1, + attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_AttributesMapper() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, + attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_AttributesMapper_Default() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", + attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_AttributesMapper_Default() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_ContextMapper() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", 1, + contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_ContextMapper_ReturningAttrs() + throws NamingException { + expectGetReadOnlyContext(); + + String[] attrs = new String[0]; + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + controls.setReturningAttributes(attrs); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", 1, attrs, + contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_ContextMapper_ReturningAttrs() + throws NamingException { + expectGetReadOnlyContext(); + + String[] attrs = new String[0]; + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + controls.setReturningAttributes(attrs); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, + attrs, contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_ContextMapper() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, + contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_ContextMapper_Default() throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested + .search(nameMock, "(ou=somevalue)", contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_ContextMapper_Default() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_SearchControls_ContextMapper() + throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + controls, contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_SearchControls_ContextMapper_ReturningObjFlagNotSet() + throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + SearchControls expectedControls = new SearchControls(); + expectedControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + expectedControls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupStringSearchAndNamingEnumeration(expectedControls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + controls, contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_Name_SearchControls_ContextMapper() throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, + new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock + .mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", controls, + contextMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_String_SearchControls_AttributesMapper() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupStringSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", + controls, attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testSearch_Name_SearchControls_AttributesMapper() + throws NamingException { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, + expectedAttributes); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock + .mapFromAttributes(expectedAttributes), expectedResult); + + dirContextMock.close(); + + replay(); + + List list = tested.search(nameMock, "(ou=somevalue)", controls, + attributesMapperMock); + + verify(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } + + public void testModifyAttributes() throws Exception { + expectGetReadWriteContext(); + + ModificationItem[] mods = new ModificationItem[0]; + dirContextMock.modifyAttributes(nameMock, mods); + + dirContextMock.close(); + + replay(); + + tested.modifyAttributes(nameMock, mods); + + verify(); + } + + public void testModifyAttributes_String() throws Exception { + expectGetReadWriteContext(); + + ModificationItem[] mods = new ModificationItem[0]; + dirContextMock.modifyAttributes(DEFAULT_BASE_STRING, mods); + + dirContextMock.close(); + + replay(); + + tested.modifyAttributes(DEFAULT_BASE_STRING, mods); + + verify(); + } + + public void testModifyAttributes_NamingException() throws Exception { + expectGetReadWriteContext(); + + ModificationItem[] mods = new ModificationItem[0]; + dirContextMock.modifyAttributes(nameMock, mods); + NamingException ne = new NamingException(); + dirContextControl.setThrowable(ne); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + dirContextMock.close(); + + replay(); + + try { + tested.modifyAttributes(nameMock, mods); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testBind() throws Exception { + expectGetReadWriteContext(); + + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.bind(nameMock, expectedObject, expectedAttributes); + dirContextMock.close(); + + replay(); + + tested.bind(nameMock, expectedObject, expectedAttributes); + + verify(); + + } + + public void testBind_String() throws Exception { + expectGetReadWriteContext(); + + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.bind(DEFAULT_BASE_STRING, expectedObject, + expectedAttributes); + dirContextMock.close(); + + replay(); + + tested.bind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); + + verify(); + + } + + public void testBind_NamingException() throws Exception { + expectGetReadWriteContext(); + + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.bind(nameMock, expectedObject, expectedAttributes); + NamingException ne = new NamingException(); + dirContextControl.setThrowable(ne); + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.bind(nameMock, expectedObject, expectedAttributes); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + + } + + public void testUnbind() throws Exception { + expectGetReadWriteContext(); + + dirContextMock.unbind(nameMock); + dirContextMock.close(); + replay(); + + tested.unbind(nameMock); + + verify(); + } + + public void testUnbind_String() throws Exception { + expectGetReadWriteContext(); + + dirContextMock.unbind(DEFAULT_BASE_STRING); + dirContextMock.close(); + replay(); + + tested.unbind(DEFAULT_BASE_STRING); + + verify(); + } + + public void testUnbindRecursive() throws Exception { + expectGetReadWriteContext(); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + Binding binding = new Binding("cn=Some name", null); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + binding); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + + DistinguishedName listDn = new DistinguishedName(DEFAULT_BASE_STRING); + dirContextMock.listBindings(listDn); + dirContextControl.setReturnValue(namingEnumerationMock); + DistinguishedName subListDn = new DistinguishedName( + "cn=Some name, o=example.com"); + dirContextMock.listBindings(subListDn); + dirContextControl.setReturnValue(namingEnumerationMock); + + dirContextMock.unbind(subListDn); + dirContextMock.unbind(listDn); + dirContextMock.close(); + + // Caused by creating a DistinguishedName from a Name + nameControl.expectAndReturn(nameMock.size(), 1, 2); + nameControl.expectAndReturn(nameMock.get(0), "o=example.com"); + + replay(); + + tested.unbind(nameMock, true); + + verify(); + } + + public void testUnbindRecursive_String() throws Exception { + expectGetReadWriteContext(); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + Binding binding = new Binding("cn=Some name", null); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + binding); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + + DistinguishedName listDn = new DistinguishedName(DEFAULT_BASE_STRING); + dirContextMock.listBindings(listDn); + dirContextControl.setReturnValue(namingEnumerationMock); + DistinguishedName subListDn = new DistinguishedName( + "cn=Some name, o=example.com"); + dirContextMock.listBindings(subListDn); + dirContextControl.setReturnValue(namingEnumerationMock); + + dirContextMock.unbind(subListDn); + dirContextMock.unbind(listDn); + dirContextMock.close(); + replay(); + + tested.unbind(DEFAULT_BASE_STRING, true); + + verify(); + } + + public void testRebind() throws NamingException { + expectGetReadWriteContext(); + + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.rebind(nameMock, expectedObject, expectedAttributes); + + dirContextMock.close(); + + replay(); + + tested.rebind(nameMock, expectedObject, expectedAttributes); + + verify(); + } + + public void testRebind_String() throws NamingException { + expectGetReadWriteContext(); + + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.rebind(DEFAULT_BASE_STRING, expectedObject, + expectedAttributes); + + dirContextMock.close(); + + replay(); + + tested.rebind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); + + verify(); + } + + public void testUnbind_NamingException() throws Exception { + expectGetReadWriteContext(); + + dirContextMock.unbind(nameMock); + NamingException ne = new NamingException(); + dirContextControl.setThrowable(ne); + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.unbind(nameMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testExecuteReadOnly() throws Exception { + expectGetReadOnlyContext(); + + Object object = new Object(); + contextExecutorControl.expectAndReturn(contextExecutorMock + .executeWithContext(dirContextMock), object); + + dirContextMock.close(); + + replay(); + + Object result = tested.executeReadOnly(contextExecutorMock); + + verify(); + + assertSame(object, result); + } + + public void testExecuteReadOnly_NamingException() throws Exception { + expectGetReadOnlyContext(); + + NamingException ne = new NamingException(); + contextExecutorControl.expectAndThrow(contextExecutorMock + .executeWithContext(dirContextMock), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.executeReadOnly(contextExecutorMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testExecuteReadWrite() throws Exception { + expectGetReadWriteContext(); + + Object object = new Object(); + contextExecutorControl.expectAndReturn(contextExecutorMock + .executeWithContext(dirContextMock), object); + + dirContextMock.close(); + + replay(); + + Object result = tested.executeReadWrite(contextExecutorMock); + + verify(); + + assertSame(object, result); + } + + public void testExecuteReadWrite_NamingException() throws Exception { + expectGetReadWriteContext(); + + NamingException ne = new NamingException(); + contextExecutorControl.expectAndThrow(contextExecutorMock + .executeWithContext(dirContextMock), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.executeReadWrite(contextExecutorMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); + + SearchResult searchResult = new SearchResult(null, null, null); + + dirContextProcessorMock.preProcess(dirContextMock); + + searchExecutorControl.expectAndReturn(searchExecutorMock + .executeSearch(dirContextMock), namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + + handlerMock.handleNameClassPair(searchResult); + + dirContextProcessorMock.postProcess(dirContextMock); + + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); + + verify(); + } + + public void testDoSearch_DirContextProcessor_NamingException() + throws Exception { + expectGetReadOnlyContext(); + + dirContextProcessorMock.preProcess(dirContextMock); + + NamingException ne = new NamingException(); + searchExecutorControl.expectAndThrow(searchExecutorMock + .executeSearch(dirContextMock), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock, + dirContextProcessorMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch() throws Exception { + expectGetReadOnlyContext(); + + SearchResult searchResult = new SearchResult(null, null, null); + + searchExecutorControl.expectAndReturn(searchExecutorMock + .executeSearch(dirContextMock), namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), + searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock + .hasMore(), false); + namingEnumerationMock.close(); + + handlerMock.handleNameClassPair(searchResult); + + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock); + + verify(); + } + + public void testDoSearch_NamingException() throws Exception { + expectGetReadOnlyContext(); + + NamingException ne = new NamingException(); + searchExecutorControl.expectAndThrow(searchExecutorMock + .executeSearch(dirContextMock), ne); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch_NamingException_NamingEnumeration() + throws Exception { + expectGetReadOnlyContext(); + + searchExecutorControl.expectAndReturn(searchExecutorMock + .executeSearch(dirContextMock), namingEnumerationMock); + + NamingException ne = new NamingException(); + namingEnumerationControl.expectAndThrow( + namingEnumerationMock.hasMore(), ne); + namingEnumerationMock.close(); + + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ne), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch_NameNotFoundException() throws Exception { + expectGetReadOnlyContext(); + + searchExecutorControl.expectAndThrow(searchExecutorMock + .executeSearch(dirContextMock), new NameNotFoundException()); + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock); + + verify(); + } + + public void testSearch_PartialResult_IgnoreNotSet() throws NamingException { + expectGetReadOnlyContext(); + + PartialResultException ex = new PartialResultException(); + searchExecutorControl.expectAndThrow(searchExecutorMock + .executeSearch(dirContextMock), ex); + dirContextMock.close(); + + exceptionTranslatorControl.expectAndReturn(exceptionTranslatorMock + .translate(ex), new EntryNotFoundException("dummy")); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock); + fail("EntryNotFoundException expected"); + } catch (EntryNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testSearch_PartialResult_IgnoreSet() throws NamingException { + tested.setIgnorePartialResultException(true); + + expectGetReadOnlyContext(); + + searchExecutorControl.expectAndThrow(searchExecutorMock + .executeSearch(dirContextMock), new PartialResultException()); + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock); + + verify(); + } + + /** + * Needed to verify search control values. + * + * @author Mattias Arthursson + */ + private static class SearchControlsMatcher extends AbstractMatcher { + protected boolean argumentMatches(Object arg0, Object arg1) { + if (arg0 instanceof SearchControls + && arg1 instanceof SearchControls) { + SearchControls s0 = (SearchControls) arg0; + SearchControls s1 = (SearchControls) arg1; + + return s0.getSearchScope() == s1.getSearchScope() + && s0.getReturningObjFlag() == s1.getReturningObjFlag() + && s0.getDerefLinkFlag() == s1.getDerefLinkFlag() + && s0.getCountLimit() == s1.getCountLimit() + && s0.getTimeLimit() == s1.getTimeLimit() + && s0.getReturningAttributes() == s1 + .getReturningAttributes(); + } else { + return super.argumentMatches(arg0, arg1); + } + } + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/RequestControlMatcher.java b/spring-ldap/src/test/java/org/springframework/ldap/RequestControlMatcher.java new file mode 100644 index 00000000..b430fd96 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/RequestControlMatcher.java @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import javax.naming.ldap.Control; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.easymock.AbstractMatcher; + +/** + * Custom argument matcher that matches javax.naming.ldap.Control objects. + * + * @author Adam Skogman + */ +public class RequestControlMatcher extends AbstractMatcher { + + /** + * @see org.easymock.AbstractMatcher#argumentMatches(java.lang.Object, + * java.lang.Object) + */ + protected boolean argumentMatches(Object expected, Object actual) { + + // null checks + if (expected == null && actual == null) { + return true; + } + if (expected == null || actual == null) { + return false; + } + + // Both params should be arrays + Object[] expArray = (Object[]) expected; + Object[] actArray = (Object[]) actual; + + if (expArray.length != actArray.length) { + return false; + } + + // Compary each object + for (int i = 0; i < expArray.length; i++) { + if (!controlMatches((Control) expArray[i], (Control) actArray[i])) { + return false; + } + } + return true; + + } + + private boolean controlMatches(Control expected, Control actual) { + + // Compare SortControl + return StringUtils.equals(expected.getID(), actual.getID()) + && expected.isCritical() == actual.isCritical() + && ArrayUtils.isEquals(expected.getEncodedValue(), actual + .getEncodedValue()); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/AggregateDirContextProcessorTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/AggregateDirContextProcessorTest.java new file mode 100644 index 00000000..0bf5b136 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/AggregateDirContextProcessorTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.NamingException; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.DirContextProcessor; + +public class AggregateDirContextProcessorTest extends TestCase { + + private MockControl processor1Control; + + private DirContextProcessor processor1Mock; + + private MockControl processor2Control; + + private DirContextProcessor processor2Mock; + + private AggregateDirContextProcessor tested; + + protected void setUp() throws Exception { + super.setUp(); + + // Create processor1 mock + processor1Control = MockControl + .createControl(DirContextProcessor.class); + processor1Mock = (DirContextProcessor) processor1Control.getMock(); + + // Create processor2 mock + processor2Control = MockControl + .createControl(DirContextProcessor.class); + processor2Mock = (DirContextProcessor) processor2Control.getMock(); + + tested = new AggregateDirContextProcessor(); + tested.addDirContextProcessor(processor1Mock); + tested.addDirContextProcessor(processor2Mock); + + } + + protected void tearDown() throws Exception { + super.tearDown(); + + processor1Control = null; + processor1Mock = null; + + processor2Control = null; + processor2Mock = null; + } + + protected void replay() { + processor1Control.replay(); + processor2Control.replay(); + + } + + protected void verify() { + processor1Control.verify(); + processor2Control.verify(); + } + + public void testPreProcess() throws NamingException { + processor1Mock.preProcess(null); + processor2Mock.preProcess(null); + + replay(); + + tested.preProcess(null); + + verify(); + } + + public void testPostProcess() throws NamingException { + processor1Mock.postProcess(null); + processor2Mock.postProcess(null); + + replay(); + + tested.postProcess(null); + + verify(); + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/CountNameClassPairResultCallbackHandlerTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/CountNameClassPairResultCallbackHandlerTest.java new file mode 100644 index 00000000..0eacbeb0 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/CountNameClassPairResultCallbackHandlerTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.directory.SearchResult; + +import org.springframework.ldap.support.CountNameClassPairCallbackHandler; + + +import junit.framework.TestCase; + +public class CountNameClassPairResultCallbackHandlerTest extends TestCase { + + + private CountNameClassPairCallbackHandler tested; + + protected void setUp() throws Exception { + super.setUp(); + + tested = new CountNameClassPairCallbackHandler(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + tested = null; + } + + public void testHandleSearchResult() throws Exception { + SearchResult dummy = new SearchResult(null, null, null); + tested.handleNameClassPair(dummy); + tested.handleNameClassPair(dummy); + tested.handleNameClassPair(dummy); + + assertEquals(3, tested.getNoOfRows()); + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/DefaultDirObjectFactoryTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/DefaultDirObjectFactoryTest.java new file mode 100644 index 00000000..c0f4e499 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/DefaultDirObjectFactoryTest.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.Name; +import javax.naming.directory.BasicAttributes; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.ldap.support.DefaultDirObjectFactory; +import org.springframework.ldap.support.DirContextAdapter; +import org.springframework.ldap.support.DistinguishedName; + +public class DefaultDirObjectFactoryTest extends TestCase { + + private MockControl contextControl; + + private Context contextMock; + + private static final Name DN = new DistinguishedName( + "ou=some unit, dc=jayway, dc=se"); + + private DefaultDirObjectFactory tested; + + private MockControl contextControl2; + + private Context contextMock2; + + protected void setUp() throws Exception { + super.setUp(); + + contextControl = MockControl.createControl(Context.class); + contextMock = (Context) contextControl.getMock(); + + contextControl2 = MockControl.createControl(Context.class); + contextMock2 = (Context) contextControl2.getMock(); + + tested = new DefaultDirObjectFactory(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + contextControl = null; + contextMock = null; + + contextControl2 = null; + contextMock2 = null; + + tested = null; + } + + protected void replay() { + contextControl.replay(); + contextControl2.replay(); + } + + protected void verify() { + contextControl.verify(); + contextControl2.verify(); + } + + public void testGetObjectInstance() throws Exception { + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("someAttribute", "someValue"); + + contextMock.close(); + + replay(); + + DirContextAdapter adapter = (DirContextAdapter) tested + .getObjectInstance(contextMock, DN, null, new Hashtable(), + expectedAttributes); + + verify(); + + assertEquals(DN, adapter.getDn()); + assertEquals(expectedAttributes, adapter.getAttributes()); + } + + public void testGetObjectInstance_nullObject() throws Exception { + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("someAttribute", "someValue"); + + replay(); + + DirContextAdapter adapter = (DirContextAdapter) tested + .getObjectInstance(null, DN, null, new Hashtable(), + expectedAttributes); + + verify(); + + assertEquals(DN, adapter.getDn()); + assertEquals(expectedAttributes, adapter.getAttributes()); + } + + public void testGetObjectInstance_ObjectNotContext() throws Exception { + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("someAttribute", "someValue"); + + replay(); + + DirContextAdapter adapter = (DirContextAdapter) tested + .getObjectInstance(new Object(), DN, null, new Hashtable(), + expectedAttributes); + + verify(); + + assertEquals(DN, adapter.getDn()); + assertEquals(expectedAttributes, adapter.getAttributes()); + } + + /** + * Make sure that the base suffix is stripped off from the DN. + * + * @throws Exception + */ + public void testGetObjectInstance_BaseSet() throws Exception { + BasicAttributes expectedAttributes = new BasicAttributes(); + expectedAttributes.put("someAttribute", "someValue"); + + contextControl2.expectAndReturn(contextMock2.getNameInNamespace(), + "dc=jayway, dc=se"); + contextMock.close(); + + replay(); + + DirContextAdapter adapter = (DirContextAdapter) tested + .getObjectInstance(contextMock, new DistinguishedName( + "ou=some unit"), contextMock2, new Hashtable(), + expectedAttributes); + + verify(); + + assertEquals("ou=some unit", adapter.getDn().toString()); + assertEquals("ou=some unit, dc=jayway, dc=se", adapter + .getNameInNamespace()); + assertEquals(expectedAttributes, adapter.getAttributes()); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterBugTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterBugTest.java new file mode 100644 index 00000000..e57c2d07 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterBugTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import javax.naming.Name; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttributes; + +import junit.framework.TestCase; + +/** + * Unit tests that serve as regression tests for bugs that have been fixed. + * + * @author Luke Taylor + */ +public class DirContextAdapterBugTest extends TestCase { + + public void testResetAttributeValuesNotReportedAsModifications() { + BasicAttributes attrs = new BasicAttributes("myattr", "a"); + attrs.get("myattr").add("b"); + attrs.get("myattr").add("c"); + UpdateAdapter ctx = new UpdateAdapter(attrs, new DistinguishedName()); + + ctx.setAttributeValues("myattr", new String[] { "a", "b" }); + ctx.setAttributeValues("myattr", new String[] { "a", "b", "c" }); + + assertEquals(0, ctx.getModificationItems().length); + } + + public void testResetAttributeValuesSameLengthNotReportedAsModifications() { + BasicAttributes attrs = new BasicAttributes("myattr", "a"); + attrs.get("myattr").add("b"); + attrs.get("myattr").add("c"); + UpdateAdapter ctx = new UpdateAdapter(attrs, new DistinguishedName()); + + ctx.setAttributeValues("myattr", new String[] { "a", "b", "d" }); + ctx.setAttributeValues("myattr", new String[] { "a", "b", "c" }); + + assertEquals(0, ctx.getModificationItems().length); + } + + /** + * This test starts with an array with a null value in it (because that's + * how BasicAttributes will do it), changes to [a], and then + * changes to null. The current code interprets this as a + * change and will replace the original array with an empty array. + * + * TODO Is this correct behaviour? + */ + public void testResetNullAttributeValuesReportedAsModifications() { + BasicAttributes attrs = new BasicAttributes("myattr", null); + UpdateAdapter ctx = new UpdateAdapter(attrs, new DistinguishedName()); + + ctx.setAttributeValues("myattr", new String[] { "a" }); + ctx.setAttributeValues("myattr", null); + + assertEquals(1, ctx.getModificationItems().length); + } + + public void testResetNullAttributeValueNotReportedAsModification() throws Exception { + BasicAttributes attrs = new BasicAttributes("myattr", "b"); + UpdateAdapter ctx = new UpdateAdapter(attrs, new DistinguishedName()); + + ctx.setAttributeValue("myattr", "a"); + ctx.setAttributeValue("myattr", "b"); + + assertEquals(0, ctx.getModificationItems().length); + } + + private static class UpdateAdapter extends DirContextAdapter { + public UpdateAdapter(Attributes attrs, Name dn) { + super(attrs, dn); + setUpdateMode(true); + } + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterTest.java new file mode 100644 index 00000000..e25fc1e6 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/DirContextAdapterTest.java @@ -0,0 +1,664 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import javax.naming.Name; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; + +import org.springframework.ldap.support.DirContextAdapter; + +import junit.framework.TestCase; + +/** + * Tests the DirContextAdapter class. + * + * @author Andreas Ronge + * @author Mattias Arthursson + */ +public class DirContextAdapterTest extends TestCase { + private static final DistinguishedName BASE_NAME = new DistinguishedName( + "dc=jayway, dc=se"); + + private static final DistinguishedName DUMMY_NAME = new DistinguishedName( + "c=SE, dc=jayway, dc=se"); + + private DirContextAdapter classUnderTest; + + protected void setUp() throws Exception { + super.setUp(); + classUnderTest = new DirContextAdapter(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSetUpdateMode() throws Exception { + assertFalse(classUnderTest.isUpdateMode()); + classUnderTest.setUpdateMode(true); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setUpdateMode(false); + assertFalse(classUnderTest.isUpdateMode()); + } + + public void testGetModificationItems() throws Exception { + ModificationItem[] items = classUnderTest.getModificationItems(); + assertEquals(0, items.length); + classUnderTest.setUpdateMode(true); + assertEquals(0, items.length); + } + + public void testAlwaysReplace() throws Exception { + ModificationItem[] items = classUnderTest.getModificationItems(); + assertEquals(0, items.length); + classUnderTest.setUpdateMode(true); + assertEquals(0, items.length); + } + + public void testGetStringAttributeNotExists() throws Exception { + String s = classUnderTest.getStringAttribute("does not exist"); + assertNull(s); + } + + public void testGetStringAttributeExists() throws Exception { + final Attributes attrs = new BasicAttributes(); + attrs.put(new BasicAttribute("abc", "def")); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(attrs, null); + } + } + classUnderTest = new TestableDirContextAdapter(); + String s = classUnderTest.getStringAttribute("abc"); + assertEquals("def", s); + } + + public void testGetStringAttributesExists() throws Exception { + final Attributes attrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("234"); + attrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(attrs, null); + } + } + classUnderTest = new TestableDirContextAdapter(); + String s[] = classUnderTest.getStringAttributes("abc"); + assertEquals("123", s[0]); + assertEquals("234", s[1]); + assertEquals(2, s.length); + } + + public void testGetStringAttributesNotExists() throws Exception { + String s[] = classUnderTest.getStringAttributes("abc"); + assertNull(s); + } + + public void testSetStringAttribute() throws Exception { + assertFalse(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", "123"); + Attributes attrs = classUnderTest.getAttributes(); + Attribute attr = attrs.get("abc"); + assertEquals("123", (String) attr.get()); + } + + public void testSetStringAttributeNull() throws Exception { + assertFalse(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", null); + Attributes attrs = classUnderTest.getAttributes(); + Attribute attr = attrs.get("abc"); + assertNull(attr); + } + + public void testAddAttribute() throws Exception { + classUnderTest.setUpdateMode(true); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", "123"); + Attributes attrs = classUnderTest.getAttributes(); + Attribute attr = attrs.get("abc"); + assertNull(attr); + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.ADD_ATTRIBUTE, mods[0].getModificationOp()); + attr = mods[0].getAttribute(); + assertEquals("123", (String) attr.get()); + + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(1, modNames.length); + assertEquals("abc", modNames[0]); + + classUnderTest.update(); + mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + attrs = classUnderTest.getAttributes(); + attr = attrs.get("abc"); + assertEquals("123", (String) attr.get()); + } + + public void testGetDn() throws Exception { + DirContextAdapter tested = new DirContextAdapter(DUMMY_NAME); + Name result = tested.getDn(); + assertEquals(DUMMY_NAME, result); + } + + public void testGetDn_BasePath() { + DirContextAdapter tested = new DirContextAdapter(null, DUMMY_NAME, + BASE_NAME); + Name result = tested.getDn(); + assertEquals(DUMMY_NAME, result); + } + + public void testGetNameInNamespace() { + DirContextAdapter tested = new DirContextAdapter(DUMMY_NAME); + String result = tested.getNameInNamespace(); + assertEquals(DUMMY_NAME.toString(), result); + } + + public void testGetNameInNamespace_BasePath() { + DirContextAdapter tested = new DirContextAdapter(null, + new DistinguishedName("c=SE"), BASE_NAME); + String result = tested.getNameInNamespace(); + assertEquals(DUMMY_NAME.toString(), result); + } + + public void testAddMultiAttributes() throws Exception { + classUnderTest.setUpdateMode(true); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123", "456" }); + Attributes attrs = classUnderTest.getAttributes(); + Attribute attr = attrs.get("abc"); + assertNull(attr); + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.ADD_ATTRIBUTE, mods[0].getModificationOp()); + attr = mods[0].getAttribute(); + assertEquals(2, attr.size()); + assertEquals("123", (String) attr.get(0)); + assertEquals("456", (String) attr.get(1)); + + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(1, modNames.length); + assertEquals("abc", modNames[0]); + + classUnderTest.update(); + mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + attrs = classUnderTest.getAttributes(); + attr = attrs.get("abc"); + assertEquals("123", (String) attr.get(0)); + assertEquals("456", (String) attr.get(1)); + } + + public void testRemoveAttribute() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + fixtureAttrs.put(new BasicAttribute("abc", "123")); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + + classUnderTest.setUpdateMode(true); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", null); + Attributes attrs = classUnderTest.getAttributes(); + Attribute attr = attrs.get("abc"); + assertEquals("123", (String) attr.get()); + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.REMOVE_ATTRIBUTE, mods[0].getModificationOp()); + attr = mods[0].getAttribute(); + assertEquals("abc", (String) attr.getID()); + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(1, modNames.length); + assertEquals("abc", modNames[0]); + + classUnderTest.update(); + mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + attrs = classUnderTest.getAttributes(); + attr = attrs.get("abc"); + assertNull(attr); + } + + public void testRemoveMultiAttribute() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute abc = new BasicAttribute("abc"); + abc.add("123"); + abc.add("456"); + fixtureAttrs.put(abc); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + + classUnderTest.setUpdateMode(true); + classUnderTest.setAttributeValues("abc", new String[] {}); + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.REMOVE_ATTRIBUTE, mods[0].getModificationOp()); + Attribute attr = mods[0].getAttribute(); + assertEquals("abc", (String) attr.getID()); + assertEquals(0, attr.size()); + } + + public void testChangeAttribute() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + fixtureAttrs.put(new BasicAttribute("abc", "123")); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + classUnderTest.setAttributeValue("abc", "234"); // change + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.REPLACE_ATTRIBUTE, mods[0].getModificationOp()); + Attribute attr = mods[0].getAttribute(); + assertEquals("abc", (String) attr.getID()); + assertEquals("234", (String) attr.get()); + } + + public void testNoChangeAttribute() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + fixtureAttrs.put(new BasicAttribute("abc", "123")); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", "123"); // change + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + } + + public void testNoChangeMultiAttribute() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123", "qwe" }); + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + } + + public void testNoChangeMultiAttributeOrderDoesNotMatter() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + classUnderTest.setAttributeValues("abc", new String[] { "qwe", "123" }); + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + } + + public void testChangeMultiAttributeOrderDoesMatter() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "qwe", "123" }, + true); + + // change + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.REPLACE_ATTRIBUTE, mods[0].getModificationOp()); + Attribute attr = mods[0].getAttribute(); + assertEquals("qwe", attr.get(0)); + assertEquals("123", attr.get(1)); + } + + public void testChangeMultiAttribute_AddValue() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123", "qwe", + "klytt" }); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(1, modificationItems.length); + assertEquals(DirContext.ADD_ATTRIBUTE, modificationItems[0] + .getModificationOp()); + assertEquals("klytt", modificationItems[0].getAttribute().get()); + } + + public void testChangeMultiAttribute_RemoveValue() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123" }); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(1, modificationItems.length); + assertEquals(DirContext.REMOVE_ATTRIBUTE, modificationItems[0] + .getModificationOp()); + assertEquals("qwe", modificationItems[0].getAttribute().get()); + } + + public void testChangeMultiAttribute_RemoveTwoValues() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + multi.add("rty"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123" }); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(1, modificationItems.length); + assertEquals(DirContext.REMOVE_ATTRIBUTE, modificationItems[0] + .getModificationOp()); + assertEquals("qwe", modificationItems[0].getAttribute().get(0)); + assertEquals("rty", modificationItems[0].getAttribute().get(1)); + } + + public void testChangeMultiAttribute_RemoveAllValues() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", null); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(1, modificationItems.length); + assertEquals(DirContext.REMOVE_ATTRIBUTE, modificationItems[0] + .getModificationOp()); + } + + public void testChangeMultiAttribute_SameValue() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123", "qwe" }); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(0, modificationItems.length); + } + + public void testChangeMultiAttribute_AddAndRemoveValue() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + multi.add("rty"); + multi.add("uio"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("abc", new String[] { "123", "qwe", + "klytt", "kalle" }); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(2, modificationItems.length); + + assertEquals(DirContext.ADD_ATTRIBUTE, modificationItems[0] + .getModificationOp()); + Attribute modifiedAttribute = modificationItems[0].getAttribute(); + assertEquals("abc", modifiedAttribute.getID()); + assertEquals(2, modifiedAttribute.size()); + assertEquals("klytt", modifiedAttribute.get(0)); + assertEquals("kalle", modifiedAttribute.get(1)); + + modifiedAttribute = modificationItems[1].getAttribute(); + assertEquals(DirContext.REMOVE_ATTRIBUTE, modificationItems[1] + .getModificationOp()); + assertEquals("abc", modifiedAttribute.getID()); + assertEquals(2, modifiedAttribute.size()); + assertEquals("rty", modifiedAttribute.get(0)); + assertEquals("uio", modifiedAttribute.get(1)); + } + + public void testAddAttribute_Multivalue() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + Attribute multi = new BasicAttribute("abc"); + multi.add("123"); + multi.add("qwe"); + fixtureAttrs.put(multi); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValues("def", new String[] { "kalle", + "klytt" }); + + ModificationItem[] modificationItems = classUnderTest + .getModificationItems(); + assertEquals(1, modificationItems.length); + assertEquals("def", modificationItems[0].getAttribute().getID()); + } + + public void testChangeAttributeTwice() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + fixtureAttrs.put(new BasicAttribute("abc", "123")); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", "234"); // change + classUnderTest.setAttributeValue("abc", "987"); + // change a second time + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(1, mods.length); + assertEquals(DirContext.REPLACE_ATTRIBUTE, mods[0].getModificationOp()); + Attribute attr = mods[0].getAttribute(); + assertEquals("abc", (String) attr.getID()); + assertEquals("987", (String) attr.get()); + + classUnderTest.update(); + mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + Attributes attrs = classUnderTest.getAttributes(); + attr = attrs.get("abc"); + assertEquals("987", (String) attr.get()); + assertEquals("987", classUnderTest.getStringAttribute("abc")); + } + + public void testAddReplaceAndChangeAttribute() throws Exception { + final Attributes fixtureAttrs = new BasicAttributes(); + fixtureAttrs.put(new BasicAttribute("abc", "123")); + fixtureAttrs.put(new BasicAttribute("qwe", "42")); + class TestableDirContextAdapter extends DirContextAdapter { + public TestableDirContextAdapter() { + super(fixtureAttrs, null); + setUpdateMode(true); + } + } + classUnderTest = new TestableDirContextAdapter(); + assertTrue(classUnderTest.isUpdateMode()); + classUnderTest.setAttributeValue("abc", "234"); // change + classUnderTest.setAttributeValue("qwe", null); // remove + classUnderTest.setAttributeValue("zzz", "new"); // new + Attributes attrs = classUnderTest.getAttributes(); + Attribute attr = attrs.get("abc"); + assertEquals("123", (String) attr.get()); + assertEquals(2, attrs.size()); + + ModificationItem[] mods = classUnderTest.getModificationItems(); + assertEquals(3, mods.length); + String[] modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(3, modNames.length); + + ModificationItem mod = getModificationItem(mods, + DirContext.REPLACE_ATTRIBUTE); + assertNotNull(mod); + attr = mod.getAttribute(); + assertEquals("abc", (String) attr.getID()); + assertEquals("234", (String) attr.get()); + + mod = getModificationItem(mods, DirContext.REMOVE_ATTRIBUTE); + assertNotNull(mod); + attr = mod.getAttribute(); + assertEquals("qwe", (String) attr.getID()); + + mod = getModificationItem(mods, DirContext.ADD_ATTRIBUTE); + assertNotNull(mod); + attr = mod.getAttribute(); + assertEquals("zzz", (String) attr.getID()); + assertEquals("new", (String) attr.get()); + + classUnderTest.update(); + mods = classUnderTest.getModificationItems(); + assertEquals(0, mods.length); + modNames = classUnderTest.getNamesOfModifiedAttributes(); + assertEquals(0, modNames.length); + + attrs = classUnderTest.getAttributes(); + assertEquals(2, attrs.size()); + attr = attrs.get("abc"); + assertEquals("234", (String) attr.get()); + assertEquals("new", classUnderTest.getStringAttribute("zzz")); + } + + private ModificationItem getModificationItem(ModificationItem[] mods, + int operation) { + for (int i = 0; i < mods.length; i++) { + if (mods[i].getModificationOp() == operation) + return mods[i]; + } + return null; + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/DistinguishedNameTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/DistinguishedNameTest.java new file mode 100644 index 00000000..3ae5a59d --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/DistinguishedNameTest.java @@ -0,0 +1,448 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Enumeration; + +import javax.naming.CompositeName; +import javax.naming.InvalidNameException; +import javax.naming.Name; + +import junit.framework.TestCase; + +import com.gargoylesoftware.base.testing.EqualsTester; + +/** + * Unit tests for the {@link DistinguishedName} class. + * + * @author Adam Skogman + * @author Mattias Arthursson + */ +public class DistinguishedNameTest extends TestCase { + + public void testDistinguishedName_CompositeWithSlash() throws Exception { + Name testPath = new CompositeName("cn=foo\\/bar"); + DistinguishedName path = new DistinguishedName(testPath.toString()); + assertEquals("cn=foo/bar", path.toString()); + } + + public void testEmptyPathImmutable() throws Exception { + DistinguishedName emptyPath = DistinguishedName.EMPTY_PATH; + try { + emptyPath.add("cn=John Doe"); + fail("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException expected) { + assertTrue(true); + } + } + + public void testDistinguishedName() { + + String testPath = "cn=foo\\,bar,OU=FOO\\,bar , OU=foo\\;bar;OU=foo\\;bar" + + " ; ou=foo\\,,ou=foo\\,;ou=foo\\;;ou=foo\\,;ou=bar\\,"; + System.out.println(testPath); + + DistinguishedName path = new DistinguishedName(testPath); + + assertEquals("cn", path.getLdapRdn(8).getComponent().getKey()); + assertEquals("foo,bar", path.getLdapRdn(8).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(7).getComponent().getKey()); + assertEquals("FOO,bar", path.getLdapRdn(7).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(6).getComponent().getKey()); + assertEquals("foo;bar", path.getLdapRdn(6).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(5).getComponent().getKey()); + assertEquals("foo;bar", path.getLdapRdn(5).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(4).getComponent().getKey()); + assertEquals("foo,", path.getLdapRdn(4).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(3).getComponent().getKey()); + assertEquals("foo,", path.getLdapRdn(3).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(2).getComponent().getKey()); + assertEquals("foo;", path.getLdapRdn(2).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(1).getComponent().getKey()); + assertEquals("foo,", path.getLdapRdn(1).getComponent().getValue()); + assertEquals("ou", path.getLdapRdn(0).getComponent().getKey()); + assertEquals("bar,", path.getLdapRdn(0).getComponent().getValue()); + } + + public void testRemove() throws InvalidNameException { + + String testPath = "cn=john.doe, OU=Users,OU=Some Company,OU=G,OU=I,OU=M"; + DistinguishedName path = new DistinguishedName(testPath); + + path.remove(1); + path.remove(3); + + assertEquals("cn=john.doe, ou=Some Company, ou=G, ou=M", path + .toString()); + } + + /** + * Tests parsing and toString. + */ + public void testContains() { + + DistinguishedName migpath = new DistinguishedName("OU=G,OU=I,OU=M"); + DistinguishedName path1 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE,OU=G,OU=I,OU=M"); + DistinguishedName path2 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE,ou=G,OU=i,OU=M, ou=foo"); + DistinguishedName path3 = new DistinguishedName( + "ou=G,OU=i,OU=M, ou=foo"); + DistinguishedName path4 = new DistinguishedName("ou=G,OU=i,ou=m"); + + DistinguishedName pathE1 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE,ou=G,OU=L,OU=M, ou=foo"); + DistinguishedName pathE2 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=SE"); + + assertTrue("Contains MIG", path1.contains(migpath)); + assertTrue("Contains MIG", path2.contains(migpath)); + assertTrue("Contains MIG", path3.contains(migpath)); + assertTrue("Contains MIG", path4.contains(migpath)); + + assertFalse("Does not contain MIG", pathE1.contains(migpath)); + assertFalse("Does not contain MIG", pathE2.contains(migpath)); + } + + public void testAppend() { + DistinguishedName path1 = new DistinguishedName("ou=foo, OU=bar"); + DistinguishedName path2 = new DistinguishedName("OU=baz"); + + path1.append(path2); + + assertEquals("Append failed", "ou=baz, ou=foo, ou=bar", path1 + .toString()); + } + + public void testPrepend() { + DistinguishedName path1 = new DistinguishedName("ou=foo, OU=bar"); + DistinguishedName path2 = new DistinguishedName("cn=fie, OU=baz"); + + path1.prepend(path2); + + assertEquals("Append failed", "ou=foo, ou=bar, cn=fie, ou=baz", path1 + .toString()); + } + + public void testEquals() throws Exception { + + // original object + final Object originalObject = new DistinguishedName( + "cn=john.doe, OU=Users,OU=Some company,C=SE"); + + // another object that has the same values as the original + final Object identicalObject = new DistinguishedName( + "cn=john.doe, OU=Users,OU=Some company,C=SE"); + + // another object with different values + final Object differentObject = new DistinguishedName( + "cn=john.doe, OU=Users,OU=Some other company,C=SE"); + + // a subclass with the same values as the original + final Object subclassObject = new DistinguishedName( + "cn=john.doe, OU=Users,OU=Some company,C=SE") { + private static final long serialVersionUID = 1L; + }; + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } + + public void testClone() { + + DistinguishedName path1 = new DistinguishedName( + "cn=john.doe, OU=Users,OU=Some company,C=SE"); + + DistinguishedName path2 = (DistinguishedName) path1.clone(); + + assertEquals("Should be equal", path1, path2); + + path2.removeFirst(); + assertFalse("Should not be equal", path1.equals(path2)); + + } + + public void testEndsWith_true() { + DistinguishedName path1 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName ending1 = new DistinguishedName("uid=mtah.test"); + + DistinguishedName path2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName ending2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU"); + + assertTrue(path1.endsWith(ending1)); + assertTrue(path2.endsWith(ending2)); + } + + public void testEndsWith_false() { + DistinguishedName path1 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName ending1 = new DistinguishedName("ou=people"); + + DistinguishedName path2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName ending2 = new DistinguishedName( + "ou=EU, o=example.com"); + + assertFalse(path1.endsWith(ending1)); + assertFalse(path2.endsWith(ending2)); + } + + public void testGetAll() throws Exception { + DistinguishedName path = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + + Enumeration elements = path.getAll(); + + String element = (String) elements.nextElement(); + assertEquals("o=example.com", element); + + element = (String) elements.nextElement(); + assertEquals("ou=EU", element); + + element = (String) elements.nextElement(); + assertEquals("ou=people", element); + + element = (String) elements.nextElement(); + assertEquals("uid=mtah.test", element); + } + + public void testGet() throws Exception { + DistinguishedName path = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + + String string = path.get(1); + + assertEquals("ou=EU", string); + } + + public void testSize() { + DistinguishedName path1 = new DistinguishedName(); + assertEquals(0, path1.size()); + + DistinguishedName path2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + assertEquals(4, path2.size()); + } + + public void testGetPrefix() { + DistinguishedName path = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + + Name prefix = path.getPrefix(0); + assertEquals(0, prefix.size()); + + prefix = path.getPrefix(1); + assertEquals(1, prefix.size()); + assertEquals("o=example.com", prefix.get(0)); + + prefix = path.getPrefix(2); + assertEquals(2, prefix.size()); + assertEquals("o=example.com", prefix.get(0)); + assertEquals("ou=EU", prefix.get(1)); + } + + public void testGetSuffix() { + DistinguishedName path = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + + Name suffix = path.getSuffix(0); + assertEquals(4, suffix.size()); + + suffix = path.getSuffix(2); + assertEquals(2, suffix.size()); + assertEquals("ou=people", suffix.get(0)); + + suffix = path.getSuffix(4); + assertEquals(0, suffix.size()); + + try { + path.getSuffix(5); + fail("ArrayIndexOutOfBoundsException expected"); + } catch (ArrayIndexOutOfBoundsException expected) { + assertTrue(true); + } + } + + public void testStartsWith_true() { + DistinguishedName path1 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName start1 = new DistinguishedName("o=example.com"); + + DistinguishedName path2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName start2 = new DistinguishedName( + "ou=people, ou=EU, o=example.com"); + + assertTrue(path1.startsWith(start1)); + assertTrue(path2.startsWith(start2)); + } + + public void testStartsWith_false() { + DistinguishedName path1 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName start1 = new DistinguishedName("ou=people"); + + DistinguishedName path2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + DistinguishedName start2 = new DistinguishedName( + "uid=mtah.test, ou=EU, ou=people"); + + assertFalse(path1.startsWith(start1)); + assertFalse(path2.startsWith(start2)); + } + + public void testStartsWith_Longer() { + DistinguishedName path1 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + + DistinguishedName path2 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com, o=a.com"); + + assertFalse(path1.startsWith(path2)); + } + + public void testStartsWith_EmptyPath() { + DistinguishedName path1 = new DistinguishedName( + "uid=mtah.test, ou=people, ou=EU, o=example.com"); + + DistinguishedName path2 = new DistinguishedName(); + + assertFalse(path1.startsWith(path2)); + } + + public void testIsEmpty_True() { + DistinguishedName path = new DistinguishedName(); + assertTrue(path.isEmpty()); + } + + public void testIsEmpty_False() { + DistinguishedName path = new DistinguishedName("o=example.com"); + assertFalse(path.isEmpty()); + } + + public void testAddAll() throws Exception { + DistinguishedName path1 = new DistinguishedName("ou=foo, OU=bar"); + DistinguishedName path2 = new DistinguishedName("OU=baz"); + + path1.addAll(path2); + + assertEquals("AddAll failed", "ou=baz, ou=foo, ou=bar", path1 + .toString()); + } + + public void testAddAll_Index() throws InvalidNameException { + DistinguishedName path1 = new DistinguishedName("ou=foo, OU=bar"); + DistinguishedName path2 = new DistinguishedName("OU=baz"); + + path1.addAll(1, path2); + + assertEquals("AddAll failed", "ou=foo, ou=baz, ou=bar", path1 + .toString()); + } + + public void testAdd() throws InvalidNameException { + DistinguishedName path1 = new DistinguishedName("ou=foo, ou=bar"); + path1.add("ou=baz"); + + assertEquals("Add failed", "ou=baz, ou=foo, ou=bar", path1.toString()); + } + + public void testAdd_Index() throws InvalidNameException { + DistinguishedName path1 = new DistinguishedName("ou=foo, ou=bar"); + path1.add(1, "ou=baz"); + + assertEquals("Add failed", "ou=foo, ou=baz, ou=bar", path1.toString()); + } + + public void testToUrl() { + DistinguishedName path = new DistinguishedName("dc=jayway, dc=se"); + String url = path.toUrl(); + + assertEquals("dc=jayway,dc=se", url); + } + + public void testMultiValueRdn() throws Exception { + DistinguishedName path = new DistinguishedName( + "firstName=Rod+lastName=Johnson,ou=UK,dc=interface21,dc=com"); + assertEquals(4, path.size()); + assertEquals("firstname=Rod+lastname=Johnson", path.get(3)); + } + + public void testCompareTo_Equals() throws Exception { + DistinguishedName name1 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + DistinguishedName name2 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + + int result = name1.compareTo(name2); + assertEquals(0, result); + } + + public void testCompareTo_Less() throws Exception { + DistinguishedName name1 = new DistinguishedName( + "cn=john doe, ou=Some company, c=DK"); + DistinguishedName name2 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + + int result = name1.compareTo(name2); + assertTrue(result < 0); + } + + public void testCompareTo_Less_MoreSignificant() throws Exception { + DistinguishedName name1 = new DistinguishedName( + "an=john doe, ou=Some company, c=DK"); + DistinguishedName name2 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + + int result = name1.compareTo(name2); + assertTrue(result < 0); + } + + public void testCompareTo_Greater() throws Exception { + DistinguishedName name1 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + DistinguishedName name2 = new DistinguishedName( + "cn=john doe, ou=Some company, c=DK"); + + int result = name1.compareTo(name2); + assertTrue(result > 0); + } + + public void testCompareTo_Longer() throws Exception { + DistinguishedName name1 = new DistinguishedName( + "leaf=someleaf, cn=john doe, ou=Some company, c=SE"); + DistinguishedName name2 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + + int result = name1.compareTo(name2); + assertTrue(result > 0); + } + + public void testCompareTo_Shorter() throws Exception { + DistinguishedName name1 = new DistinguishedName( + "cn=john doe, ou=Some company, c=SE"); + DistinguishedName name2 = new DistinguishedName( + "leaf=someleaf, cn=john doe, ou=Some company, c=SE"); + + int result = name1.compareTo(name2); + assertTrue(result < 0); + } + +} \ No newline at end of file diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/LdapContextSourceTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapContextSourceTest.java new file mode 100644 index 00000000..231b24a6 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapContextSourceTest.java @@ -0,0 +1,220 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.ldap.Control; +import javax.naming.ldap.ControlFactory; + +import junit.framework.TestCase; + +import org.springframework.ldap.AuthenticationSource; + +import com.sun.jndi.ldap.ctl.ResponseControlFactory; + +/** + * Unit tests for the LdapContextSource class. + * + * @author Mattias Arthursson + * @author Ulrik Sandberg + */ +public class LdapContextSourceTest extends TestCase { + + private LdapContextSource tested; + + protected void setUp() throws Exception { + tested = new LdapContextSource(); + } + + protected void tearDown() throws Exception { + tested = null; + } + + public void testAfterPropertiesSet_NoUrl() throws Exception { + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testAfterPropertiesSet_BaseAndTooEarlyJdk() throws Exception { + tested = new LdapContextSource() { + String getJdkVersion() { + return "1.4.1_03"; + } + }; + + tested.setUrl("http://ldap.example.com:389"); + tested.setBase("dc=jayway,dc=se"); + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testGetAnonymousEnv() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + tested.setUserName("cn=Some User"); + tested.setPassword("secret"); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env + .get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertNull(env.get(Context.SECURITY_PRINCIPAL)); + assertNull(env.get(Context.SECURITY_CREDENTIALS)); + + // Verify that changing values does not change the environment values. + tested.setBase("dc=other,dc=se"); + tested.setUrl("ldap://ldap2.example.com:389"); + tested.setPooled(false); + + env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env + .get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertNull(env.get(Context.SECURITY_PRINCIPAL)); + assertNull(env.get(Context.SECURITY_CREDENTIALS)); + } + + public void testGetAuthenticatedEnv() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + tested.setUserName("cn=Some User"); + tested.setPassword("secret"); + tested.afterPropertiesSet(); + + Hashtable env = tested.getAuthenticatedEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env + .get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); + assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); + } + + public void testGetAuthenticatedEnv_DummyAuthenticationProvider() + throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); + tested.setAuthenticationSource(authenticationProvider); + authenticationProvider.setPrincipal("cn=Some User"); + authenticationProvider.setCredentials("secret"); + tested.afterPropertiesSet(); + + Hashtable env = tested.getAuthenticatedEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env + .get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); + assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); + } + + public void testGetAuthenticatedEnv_DummyAuthenticationProvider_Changed() + throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); + tested.setAuthenticationSource(authenticationProvider); + authenticationProvider.setPrincipal("cn=Some User"); + authenticationProvider.setCredentials("secret"); + tested.afterPropertiesSet(); + + authenticationProvider.setPrincipal("cn=Some Other User"); + authenticationProvider.setCredentials("other secret"); + + Hashtable env = tested.getAuthenticatedEnv(); + assertEquals("cn=Some Other User", env.get(Context.SECURITY_PRINCIPAL)); + assertEquals("other secret", env.get(Context.SECURITY_CREDENTIALS)); + + } + + public void testGetAnonymousEnv_DontCacheEnv() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + tested.setUserName("cn=Some User"); + tested.setPassword("secret"); + tested.setCacheEnvironmentProperties(false); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env + .get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertNull(env.get(Context.SECURITY_PRINCIPAL)); + assertNull(env.get(Context.SECURITY_CREDENTIALS)); + + tested.setUrl("ldap://ldap2.example.com:389"); + env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap2.example.com:389/dc=example,dc=se", env + .get(Context.PROVIDER_URL)); + } + + public void testsetResponseControlFactory_Null() throws Exception { + tested.setResponseControlFactory(null); + assertNotNull(tested.getResponseControlFactory()); + assertEquals(ResponseControlFactory.class, tested + .getResponseControlFactory()); + } + + public void testsetResponseControlFactory_Valid() throws Exception { + tested.setResponseControlFactory(ControlFactory.class); + assertEquals(ControlFactory.class, tested.getResponseControlFactory()); + } + + public void testsetResponseControlFactory_Invalid() throws Exception { + try { + tested.setResponseControlFactory(Control.class); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + private class DummyAuthenticationProvider implements AuthenticationSource { + private String principal; + + private String credentials; + + public void setCredentials(String credentials) { + this.credentials = credentials; + } + + public void setPrincipal(String principal) { + this.principal = principal; + } + + public String getPrincipal() { + return principal; + } + + public String getCredentials() { + return credentials; + } + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/LdapEncoderTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapEncoderTest.java new file mode 100644 index 00000000..3afbd3c5 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapEncoderTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import org.springframework.ldap.BadLdapGrammarException; +import org.springframework.ldap.support.LdapEncoder; + +import junit.framework.TestCase; + +/** + * Unit test for the LdapEncode class. + * + * @author Adam Skogman + */ +public class LdapEncoderTest extends TestCase { + + /** + * Constructor for LdapEncoderTest. + * + * @param name + */ + public LdapEncoderTest(String name) { + super(name); + } + + public void testFilterEncode() { + String correct = "\\2aa\\2ab\\28c\\29d\\2a\\5c"; + assertEquals(correct, LdapEncoder.filterEncode("*a*b(c)d*\\")); + + } + + public void testNameEncode() { + + String res = LdapEncoder.nameEncode("# foo ,+\"\\<>; "); + + assertEquals("\\# foo \\,\\+\\\"\\\\\\<\\>\\;\\ ", res); + } + + public void testNameDecode() { + + String res = (String) LdapEncoder + .nameDecode("\\# foo \\,\\+\\\"\\\\\\<\\>\\;\\ "); + + assertEquals("# foo ,+\"\\<>; ", res); + } + + public void testNameDecode_slashlast() { + + try { + LdapEncoder.nameDecode("\\"); + fail("Should throw BadLdapGrammarException"); + } catch (BadLdapGrammarException e) { + assertTrue(true); + } + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnComponentTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnComponentTest.java new file mode 100644 index 00000000..5d93cbf3 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnComponentTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import junit.framework.TestCase; + +/** + * Tests for LdapRdnComponent. + * + * @author Mattias Arthursson + */ +public class LdapRdnComponentTest extends TestCase { + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testCompareTo_Less() { + LdapRdnComponent component1 = new LdapRdnComponent("cn", "john doe"); + LdapRdnComponent component2 = new LdapRdnComponent("sn", "doe"); + int result = component1.compareTo(component2); + assertTrue(result < 0); + } + + public void testCompareTo_Greater() { + LdapRdnComponent component1 = new LdapRdnComponent("sn", "doe"); + LdapRdnComponent component2 = new LdapRdnComponent("cn", "john doe"); + int result = component1.compareTo(component2); + assertTrue(result > 0); + } + + public void testCompareTo_Equal() { + LdapRdnComponent component1 = new LdapRdnComponent("cn", "john doe"); + LdapRdnComponent component2 = new LdapRdnComponent("cn", "john doe"); + int result = component1.compareTo(component2); + assertEquals(0, result); + } +} \ No newline at end of file diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnTest.java new file mode 100644 index 00000000..5994ad3c --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapRdnTest.java @@ -0,0 +1,214 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support; + +import junit.framework.TestCase; + +import org.springframework.ldap.BadLdapGrammarException; + +import com.gargoylesoftware.base.testing.EqualsTester; + +/** + * Unit test for the LdapRdn class. + * + * @author Adam Skogman + */ +public class LdapRdnTest extends TestCase { + + public void testLdapRdn_parse_simple() { + + LdapRdn rdn = new LdapRdn("foo=bar"); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals("bar", rdn.getComponent().getValue()); + assertEquals("foo=bar", rdn.getComponent().getLdapEncoded()); + } + + public void testLdapRdn_parse_spaces() { + + LdapRdn rdn = new LdapRdn(" foo = bar "); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals("bar", rdn.getComponent().getValue()); + assertEquals("foo=bar", rdn.getComponent().getLdapEncoded()); + } + + public void testLdapRdn_parse_escape() { + + LdapRdn rdn = new LdapRdn("foo=bar\\=fum"); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals("bar=fum", rdn.getComponent().getValue()); + assertEquals("foo=bar\\=fum", rdn.getComponent().getLdapEncoded()); + } + + public void testLdapRdn_parse_hexEscape() { + + LdapRdn rdn = new LdapRdn("foo=bar\\0dfum"); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals("bar\rfum", rdn.getComponent().getValue()); + assertEquals("foo=bar\\0Dfum", rdn.getComponent().getLdapEncoded()); + } + + public void testLdapRdn_parse_trailingBackslash() { + + try { + new LdapRdn("foo=bar\\"); + fail("Should throw BadLdapGrammarException"); + } catch (BadLdapGrammarException e) { + assertTrue(true); + } + } + + public void testLdapRdn_parse_spaces_escape() { + + LdapRdn rdn = new LdapRdn(" foo = \\ bar\\20 \\ "); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals(" bar ", rdn.getComponent().getValue()); + assertEquals("foo=\\ bar \\ ", rdn.getComponent().getLdapEncoded()); + } + + public void testLdapRdn_parse_tooMuchTrim() { + try { + new LdapRdn("foo=bar\\"); + fail("Should throw BadLdapGrammarException"); + } catch (BadLdapGrammarException e) { + assertTrue(true); + } + } + + public void testLdapRdn_parse_slash() { + LdapRdn rdn = new LdapRdn("ou=Clerical / Secretarial Staff"); + + assertEquals("ou", rdn.getComponent().getKey()); + assertEquals("Clerical / Secretarial Staff", rdn.getComponent() + .getValue()); + assertEquals("ou=Clerical / Secretarial Staff", rdn.getComponent() + .getLdapEncoded()); + } + + public void testLdapRdn_parse_quoteInKey() { + try { + new LdapRdn("\"umanroleid=2583"); + fail("Should throw BadLdapGrammarException"); + } catch (BadLdapGrammarException e) { + assertTrue(true); + } + } + + public void testLdapRdn_KeyValue_simple() { + LdapRdn rdn = new LdapRdn("foo", "bar"); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals("bar", rdn.getComponent().getValue()); + assertEquals("foo=bar", rdn.getComponent().getLdapEncoded()); + } + + public void testLdapRdn_KeyValue_valueNeedsEscape() { + LdapRdn rdn = new LdapRdn("foo", "bar\\"); + + assertEquals("foo", rdn.getComponent().getKey()); + assertEquals("bar\\", rdn.getComponent().getValue()); + assertEquals("foo=bar\\\\", rdn.getComponent().getLdapEncoded()); + } + + public void testEncodeUrl() { + LdapRdn rdn = new LdapRdn("o = example.com "); + assertEquals("o=example.com", rdn.encodeUrl()); + } + + public void testEncodeUrl_SpacesInValue() { + LdapRdn rdn = new LdapRdn("o = my organization "); + assertEquals("o=my%20organization", rdn.encodeUrl()); + } + + public void testLdapRdn_Parse_MultipleComponents() { + LdapRdn rdn = new LdapRdn("cn=John Doe+sn=Doe"); + assertEquals("cn=John Doe", rdn.getComponent(0).encodeLdap()); + assertEquals("sn=Doe", rdn.getComponent(1).encodeLdap()); + assertEquals("cn=John Doe+sn=Doe", rdn.getLdapEncoded()); + } + + public void testEquals() throws Exception { + // original object + final Object originalObject = new LdapRdn("cn", "john.doe"); + + // another object that has the same values as the original + final Object identicalObject = new LdapRdn("cn", "john.doe"); + + // another object with different values + final Object differentObject = new LdapRdn("cn", "john.svensson"); + + // a subclass with the same values as the original + final Object subclassObject = new LdapRdn("cn", "john.doe") { + private static final long serialVersionUID = 1L; + }; + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } + + public void testCompareTo_Equals() throws Exception { + LdapRdn rdn1 = new LdapRdn("cn=john doe"); + LdapRdn rdn2 = new LdapRdn("cn=john doe"); + + int result = rdn1.compareTo(rdn2); + assertEquals(0, result); + } + + public void testCompareTo_EqualsComplex() throws Exception { + LdapRdn rdn1 = new LdapRdn("cn=john doe+sn=doe"); + LdapRdn rdn2 = new LdapRdn("cn=john doe+sn=doe"); + + int result = rdn1.compareTo(rdn2); + assertEquals(0, result); + } + + public void testCompareTo_Less() { + LdapRdn rdn1 = new LdapRdn("cn=john doe+sn=doe"); + LdapRdn rdn2 = new LdapRdn("cn=john doe+tn=doe"); + + int result = rdn1.compareTo(rdn2); + assertTrue(result < 0); + } + + public void testCompareTo_Greater() { + LdapRdn rdn1 = new LdapRdn("cn=john doe+sn=doe"); + LdapRdn rdn2 = new LdapRdn("cn=john doe+an=doe"); + + int result = rdn1.compareTo(rdn2); + assertTrue(result > 0); + } + + public void testCompareTo_Shorter() { + LdapRdn rdn1 = new LdapRdn("cn=john doe+sn=doe"); + LdapRdn rdn2 = new LdapRdn("cn=john doe+sn=doe+description=tjo"); + + int result = rdn1.compareTo(rdn2); + assertTrue(result < 0); + } + + public void testCompareTo_Longer() { + LdapRdn rdn1 = new LdapRdn("cn=john doe+sn=doe+description=tjo"); + LdapRdn rdn2 = new LdapRdn("cn=john doe+sn=doe"); + + int result = rdn1.compareTo(rdn2); + assertTrue(result > 0); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceTest.java new file mode 100644 index 00000000..abfc4daa --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/authentication/AcegiAuthenticationSourceTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.authentication; + +import junit.framework.TestCase; + + +import org.acegisecurity.Authentication; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.userdetails.User; +import org.acegisecurity.userdetails.ldap.LdapUserDetails; +import org.easymock.MockControl; +import org.springframework.ldap.support.authentication.AcegiAuthenticationSource; + +public class AcegiAuthenticationSourceTest extends TestCase { + + private MockControl authenticationControl; + + private Authentication authenticationMock; + + private MockControl ldapUserDetailsControl; + + private LdapUserDetails ldapUserDetailsMock; + + private AcegiAuthenticationSource tested; + + protected void setUp() throws Exception { + super.setUp(); + + authenticationControl = MockControl.createControl(Authentication.class); + authenticationMock = (Authentication) authenticationControl.getMock(); + + ldapUserDetailsControl = MockControl + .createControl(LdapUserDetails.class); + ldapUserDetailsMock = (LdapUserDetails) ldapUserDetailsControl + .getMock(); + + tested = new AcegiAuthenticationSource(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + authenticationControl = null; + authenticationMock = null; + + ldapUserDetailsControl = null; + ldapUserDetailsMock = null; + + tested = null; + } + + protected void replay() { + authenticationControl.replay(); + ldapUserDetailsControl.replay(); + } + + protected void verify() { + authenticationControl.verify(); + ldapUserDetailsControl.verify(); + } + + public void testGetPrincipalAndCredentials() { + authenticationControl.expectAndReturn( + authenticationMock.getPrincipal(), ldapUserDetailsMock); + authenticationControl.expectAndReturn(authenticationMock + .getCredentials(), "secret"); + + ldapUserDetailsControl.expectAndDefaultReturn(ldapUserDetailsMock + .getDn(), "cn=Manager"); + + SecurityContextHolder.getContext() + .setAuthentication(authenticationMock); + + replay(); + + String principal = tested.getPrincipal(); + String credentials = tested.getCredentials(); + + verify(); + + assertEquals("secret", credentials); + assertEquals("cn=Manager", principal); + } + + public void testGetPrincipalAndCredentials_nullAuthentication() { + SecurityContextHolder.getContext().setAuthentication(null); + + replay(); + + assertEquals("", tested.getPrincipal()); + assertEquals("", tested.getCredentials()); + verify(); + } + + public void testGetPrincipal_InvalidPrincipal() { + authenticationControl.expectAndReturn( + authenticationMock.getPrincipal(), new User("dummy", "dummy", + true, true, true, true, new GrantedAuthority[0])); + + SecurityContextHolder.getContext() + .setAuthentication(authenticationMock); + + replay(); + + try { + tested.getPrincipal(); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + verify(); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecoratorTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecoratorTest.java new file mode 100644 index 00000000..3fdfbcea --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/authentication/DefaultValuesAuthenticationSourceDecoratorTest.java @@ -0,0 +1,119 @@ +package org.springframework.ldap.support.authentication; + +import org.easymock.MockControl; +import org.springframework.ldap.AuthenticationSource; +import org.springframework.ldap.support.authentication.DefaultValuesAuthenticationSourceDecorator; + +import junit.framework.TestCase; + +public class DefaultValuesAuthenticationSourceDecoratorTest extends TestCase { + + private static final String DEFAULT_PASSWORD = "defaultPassword"; + + private static final String DEFAULT_USER = "cn=defaultUser"; + + private DefaultValuesAuthenticationSourceDecorator tested; + + private MockControl authenticationSourceControl; + + private AuthenticationSource authenticationSourceMock; + + protected void setUp() throws Exception { + super.setUp(); + + authenticationSourceControl = MockControl + .createControl(AuthenticationSource.class); + authenticationSourceMock = (AuthenticationSource) authenticationSourceControl + .getMock(); + tested = new DefaultValuesAuthenticationSourceDecorator(); + tested.setDefaultUser(DEFAULT_USER); + tested.setDefaultPassword(DEFAULT_PASSWORD); + tested.setTarget(authenticationSourceMock); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + tested = null; + authenticationSourceControl = null; + authenticationSourceMock = null; + } + + public void testGetPrincipal_TargetHasPrincipal() { + authenticationSourceControl.expectAndDefaultReturn( + authenticationSourceMock.getPrincipal(), "cn=someUser"); + authenticationSourceControl.replay(); + + String principal = tested.getPrincipal(); + + authenticationSourceControl.verify(); + assertEquals("cn=someUser", principal); + } + + public void testGetPrincipal_TargetHasNoPrincipal() { + authenticationSourceControl.expectAndDefaultReturn( + authenticationSourceMock.getPrincipal(), ""); + authenticationSourceControl.replay(); + + String principal = tested.getPrincipal(); + + authenticationSourceControl.verify(); + assertEquals(DEFAULT_USER, principal); + } + + public void testGetCredentials_TargetHasPrincipal() { + authenticationSourceControl.expectAndDefaultReturn( + authenticationSourceMock.getPrincipal(), "cn=someUser"); + authenticationSourceControl.expectAndDefaultReturn( + authenticationSourceMock.getCredentials(), "somepassword"); + authenticationSourceControl.replay(); + + String credentials = tested.getCredentials(); + + authenticationSourceControl.verify(); + assertEquals("somepassword", credentials); + } + + public void testGetCredentials_TargetHasNoPrincipal() { + authenticationSourceControl.expectAndDefaultReturn( + authenticationSourceMock.getPrincipal(), ""); + authenticationSourceControl.expectAndDefaultReturn( + authenticationSourceMock.getCredentials(), "somepassword"); + authenticationSourceControl.replay(); + + String credentials = tested.getCredentials(); + + authenticationSourceControl.verify(); + assertEquals(DEFAULT_PASSWORD, credentials); + } + + public void testAfterPropertiesSet_noTarget() throws Exception { + tested.setTarget(null); + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testAfterPropertiesSet_noDefaultUser() throws Exception { + tested.setDefaultUser(null); + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testAfterPropertiesSet_noDefaultPassword() throws Exception { + tested.setDefaultPassword(null); + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessorTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessorTest.java new file mode 100644 index 00000000..07a904d5 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/control/AbstractRequestControlDirContextProcessorTest.java @@ -0,0 +1,144 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support.control; + +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import junit.framework.TestCase; + +import org.easymock.MockControl; + +public class AbstractRequestControlDirContextProcessorTest extends TestCase { + + private AbstractRequestControlDirContextProcessor tested; + + private MockControl requestControlControl; + + private Control requestControlMock; + + private MockControl requestControl2Control; + + private Control requestControl2Mock; + + private MockControl ldapContextControl; + + private LdapContext ldapContextMock; + + private MockControl dirContextControl; + + private DirContext dirContextMock; + + protected void setUp() throws Exception { + super.setUp(); + // Create requestControl mock + requestControlControl = MockControl.createControl(Control.class); + requestControlMock = (Control) requestControlControl.getMock(); + + // Create requestControl2 mock + requestControl2Control = MockControl.createControl(Control.class); + requestControl2Mock = (Control) requestControl2Control.getMock(); + + // Create ldapContext mock + ldapContextControl = MockControl.createControl(LdapContext.class); + ldapContextMock = (LdapContext) ldapContextControl.getMock(); + + // Create dirContext mock + dirContextControl = MockControl.createControl(DirContext.class); + dirContextMock = (DirContext) dirContextControl.getMock(); + + tested = new AbstractRequestControlDirContextProcessor() { + + public Control createRequestControl() { + return requestControlMock; + } + + public void postProcess(DirContext ctx) throws NamingException { + } + + }; + } + + protected void tearDown() throws Exception { + super.tearDown(); + + requestControlControl = null; + requestControlMock = null; + + requestControl2Control = null; + requestControl2Mock = null; + + ldapContextControl = null; + ldapContextMock = null; + + dirContextControl = null; + dirContextMock = null; + + } + + protected void replay() { + requestControlControl.replay(); + requestControl2Control.replay(); + ldapContextControl.replay(); + dirContextControl.replay(); + } + + protected void verify() { + requestControlControl.verify(); + requestControl2Control.verify(); + ldapContextControl.verify(); + dirContextControl.verify(); + } + + public void testPreProcess() throws NamingException { + ldapContextControl.setDefaultMatcher(MockControl.ARRAY_MATCHER); + ldapContextControl.expectAndDefaultReturn(ldapContextMock + .getRequestControls(), new Control[] { requestControl2Mock }); + ldapContextMock.setRequestControls(new Control[] { requestControl2Mock, + requestControlMock }); + + replay(); + + tested.preProcess(ldapContextMock); + + verify(); + } + + public void testPreProcess_NoExistingControls() throws NamingException { + ldapContextControl.setDefaultMatcher(MockControl.ARRAY_MATCHER); + ldapContextControl.expectAndDefaultReturn(ldapContextMock + .getRequestControls(), new Control[0]); + ldapContextMock + .setRequestControls(new Control[] { requestControlMock }); + + replay(); + + tested.preProcess(ldapContextMock); + + verify(); + } + + public void testPreProcess_NotLdapContext() throws Exception { + try { + tested.preProcess(dirContextMock); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultTest.java new file mode 100644 index 00000000..1401b74c --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support.control; + +import java.util.LinkedList; +import java.util.List; + +import com.gargoylesoftware.base.testing.EqualsTester; + +import junit.framework.TestCase; + +public class PagedResultTest extends TestCase { + public void testEquals() throws Exception { + List expectedList = new LinkedList(); + expectedList.add("dummy"); + List otherList = new LinkedList(); + otherList.add("different"); + + PagedResult originalObject = new PagedResult(expectedList, + new PagedResultsCookie(null)); + PagedResult identicalObject = new PagedResult(expectedList, + new PagedResultsCookie(null)); + PagedResult differentObject = new PagedResult(otherList, + new PagedResultsCookie(null)); + PagedResult subclassObject = new PagedResult(expectedList, + new PagedResultsCookie(null)) { + + }; + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsCookieTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsCookieTest.java new file mode 100644 index 00000000..39ea3c52 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsCookieTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support.control; + +import com.gargoylesoftware.base.testing.EqualsTester; + +import junit.framework.TestCase; + +public class PagedResultsCookieTest extends TestCase { + public void testEquals() { + byte[] expectedCookie = new byte[] { 1, 2 }; + byte[] differentCookie = new byte[] { 2, 3 }; + + PagedResultsCookie originalObject = new PagedResultsCookie( + expectedCookie); + PagedResultsCookie identicalObject = new PagedResultsCookie( + expectedCookie); + PagedResultsCookie differentObject = new PagedResultsCookie( + differentCookie); + PagedResultsCookie subclassObject = new PagedResultsCookie( + expectedCookie) { + + }; + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsRequestControlTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsRequestControlTest.java new file mode 100644 index 00000000..2cf0e4dc --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/control/PagedResultsRequestControlTest.java @@ -0,0 +1,188 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support.control; + +import java.io.IOException; + +import javax.naming.ldap.Control; +import javax.naming.ldap.LdapContext; + +import junit.framework.TestCase; + +import org.easymock.MockControl; + +import com.sun.jndi.ldap.Ber; +import com.sun.jndi.ldap.BerDecoder; +import com.sun.jndi.ldap.BerEncoder; +import com.sun.jndi.ldap.ctl.DirSyncResponseControl; +import com.sun.jndi.ldap.ctl.PagedResultsControl; +import com.sun.jndi.ldap.ctl.PagedResultsResponseControl; + +public class PagedResultsRequestControlTest extends TestCase { + + private MockControl ldapContextControl; + + private LdapContext ldapContextMock; + + protected void setUp() throws Exception { + super.setUp(); + + // Create ldapContext mock + ldapContextControl = MockControl.createControl(LdapContext.class); + ldapContextMock = (LdapContext) ldapContextControl.getMock(); + + } + + protected void tearDown() throws Exception { + super.tearDown(); + + ldapContextControl = null; + ldapContextMock = null; + + } + + protected void replay() { + ldapContextControl.replay(); + } + + protected void verify() { + ldapContextControl.verify(); + } + + public void testCreateRequestControl() throws Exception { + PagedResultsRequestControl tested = new PagedResultsRequestControl(20); + + PagedResultsControl control = (PagedResultsControl) tested + .createRequestControl(); + assertNotNull(control); + } + + public void testCreateRequestControl_CookieSet() throws Exception { + PagedResultsCookie cookie = new PagedResultsCookie(new byte[0]); + PagedResultsRequestControl tested = new PagedResultsRequestControl(20, + cookie); + + PagedResultsControl control = (PagedResultsControl) tested + .createRequestControl(); + assertNotNull(control); + } + + public void testPostProcess() throws Exception { + int resultSize = 50; + byte pageSize = 8; + + byte[] value = new byte[1]; + value[0] = pageSize; + byte[] cookie = encodeValue(resultSize, value); + PagedResultsResponseControl control = new PagedResultsResponseControl( + "dummy", true, cookie); + + ldapContextControl.expectAndDefaultReturn(ldapContextMock + .getResponseControls(), new Control[] { control }); + + PagedResultsRequestControl tested = new PagedResultsRequestControl(20); + + replay(); + + tested.postProcess(ldapContextMock); + + verify(); + + PagedResultsCookie returnedCookie = tested.getCookie(); + assertEquals(8, returnedCookie.getCookie()[0]); + assertEquals(20, tested.getPageSize()); + assertEquals(50, tested.getResultSize()); + } + + public void testPostProcess_InvalidResponseControl() throws Exception { + int resultSize = 50; + byte pageSize = 8; + + byte[] value = new byte[1]; + value[0] = pageSize; + byte[] cookie = encodeDirSyncValue(resultSize, value); + + // Using another response control to verify that it is ignored + DirSyncResponseControl control = new DirSyncResponseControl( + "dummy", true, cookie); + + ldapContextControl.expectAndDefaultReturn(ldapContextMock + .getResponseControls(), new Control[] { control }); + + PagedResultsRequestControl tested = new PagedResultsRequestControl(20); + + replay(); + + tested.postProcess(ldapContextMock); + + verify(); + + assertNull(tested.getCookie()); + assertEquals(20, tested.getPageSize()); + assertEquals(0, tested.getResultSize()); + } + + public void testBerDecoding() throws Exception { + byte[] value = new byte[1]; + value[0] = 8; + int pageSize = 20; + byte[] cookie = encodeValue(pageSize, value); + + BerDecoder ber = new BerDecoder(cookie, 0, cookie.length); + + ber.parseSeq(null); + int actualPageSize = ber.parseInt(); + byte[] actualValue = ber.parseOctetString(Ber.ASN_OCTET_STR, null); + + assertEquals("pageSize,", 20, actualPageSize); + assertEquals("value length", value.length, actualValue.length); + for (int i = 0; i < value.length; i++) { + assertEquals("value (index " + i + "),", value[i], actualValue[i]); + } + } + + private byte[] encodeValue(int pageSize, byte[] cookie) + throws IOException { + + // build the ASN.1 encoding + BerEncoder ber = new BerEncoder(10 + cookie.length); + + ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); + ber.encodeInt(pageSize); + ber.encodeOctetString(cookie, Ber.ASN_OCTET_STR); + ber.endSeq(); + + return ber.getTrimmedBuf(); + } + + /** + * Encode a value suitable for the DirSyncResponseControl used in a test. + */ + private byte[] encodeDirSyncValue(int pageSize, byte[] cookie) + throws IOException { + + // build the ASN.1 encoding + BerEncoder ber = new BerEncoder(10 + cookie.length); + + ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); + ber.encodeInt(1); // flag + ber.encodeInt(pageSize); // maxReturnLength + ber.encodeOctetString(cookie, Ber.ASN_OCTET_STR); + ber.endSeq(); + + return ber.getTrimmedBuf(); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/AbstractFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/AbstractFilterTest.java new file mode 100644 index 00000000..7fad9e46 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/AbstractFilterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.AbstractFilter; + +import junit.framework.TestCase; + +/** + * @author Adam Skogman + */ +public class AbstractFilterTest extends TestCase { + + /** + * Constructor for AbstractFilterTest. + * + * @param name + */ + public AbstractFilterTest(String name) { + super(name); + } + + /* + * Test for String encode() + */ + public void testEncode() { + + AbstractFilter af = new AbstractFilter() { + public StringBuffer encode(StringBuffer buff) { + return buff.append("foo"); + } + }; + + assertEquals("foo", af.encode()); + + } + + /* + * Test for toString() + */ + public void testToString() { + + AbstractFilter af = new AbstractFilter() { + public StringBuffer encode(StringBuffer buff) { + return buff.append("foo"); + } + }; + + assertEquals("foo", af.toString()); + + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/AndFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/AndFilterTest.java new file mode 100644 index 00000000..c1feccbc --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/AndFilterTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.AndFilter; +import org.springframework.ldap.support.filter.EqualsFilter; + +import com.gargoylesoftware.base.testing.EqualsTester; + +import junit.framework.TestCase; + +/** + * @author Adam Skogman + */ +public class AndFilterTest extends TestCase { + + /** + * Constructor for AndFilterTest. + * + * @param name + */ + public AndFilterTest(String name) { + super(name); + } + + public void testZero() { + AndFilter aq = new AndFilter(); + + assertEquals("", aq.encode()); + } + + public void testOne() { + AndFilter aq = new AndFilter().and(new EqualsFilter("a", "b")); + + assertEquals("(a=b)", aq.encode()); + } + + public void testTwo() { + AndFilter aq = new AndFilter().and(new EqualsFilter("a", "b")).and( + new EqualsFilter("c", "d")); + + assertEquals("(&(a=b)(c=d))", aq.encode()); + } + + public void testThree() { + AndFilter aq = new AndFilter().and(new EqualsFilter("a", "b")).and( + new EqualsFilter("c", "d")).and(new EqualsFilter("e", "f")); + + assertEquals("(&(a=b)(c=d)(e=f))", aq.encode()); + } + + public void testEquals() { + AndFilter originalObject = new AndFilter().and(new EqualsFilter("a", + "b")); + AndFilter identicalObject = new AndFilter().and(new EqualsFilter("a", + "b")); + AndFilter differentObject = new AndFilter().and(new EqualsFilter("b", + "b")); + AndFilter subclassObject = new AndFilter() { + }.and(new EqualsFilter("a", "b")); + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/EqualsFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/EqualsFilterTest.java new file mode 100644 index 00000000..58122f1e --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/EqualsFilterTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.EqualsFilter; + +import com.gargoylesoftware.base.testing.EqualsTester; + +import junit.framework.TestCase; + +/** + * @author Adam Skogman + */ +public class EqualsFilterTest extends TestCase { + + /** + * Constructor for EqualsQueryTest. + * + * @param name + */ + public EqualsFilterTest(String name) { + super(name); + } + + public void testEncode() { + + EqualsFilter eqq = new EqualsFilter("foo", "*bar(fie)"); + + StringBuffer buff = new StringBuffer(); + eqq.encode(buff); + + assertEquals("(foo=\\2abar\\28fie\\29)", buff.toString()); + + } + + public void testEncodeInt() { + + EqualsFilter eqq = new EqualsFilter("foo", 456); + + StringBuffer buff = new StringBuffer(); + eqq.encode(buff); + + assertEquals("(foo=456)", buff.toString()); + + } + + public void testEquals() { + EqualsFilter originalObject = new EqualsFilter("a", "b"); + EqualsFilter identicalObject = new EqualsFilter("a", "b"); + EqualsFilter differentObject = new EqualsFilter("b", "b"); + EqualsFilter subclassObject = new EqualsFilter("a", "b") { + }; + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilterTest.java new file mode 100644 index 00000000..6a483973 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/GreaterThanOrEqualsFilterTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.GreaterThanOrEqualsFilter; + +import junit.framework.TestCase; + +/** + * @author Mattias Arthursson + */ +public class GreaterThanOrEqualsFilterTest extends TestCase { + + /** + * Constructor for EqualsQueryTest. + * + * @param name + */ + public GreaterThanOrEqualsFilterTest(String name) { + super(name); + } + + public void testEncode() { + + GreaterThanOrEqualsFilter eqq = new GreaterThanOrEqualsFilter("foo", + "*bar(fie)"); + + StringBuffer buff = new StringBuffer(); + eqq.encode(buff); + + assertEquals("(foo>=\\2abar\\28fie\\29)", buff.toString()); + + } + + public void testEncodeInt() { + + GreaterThanOrEqualsFilter eqq = new GreaterThanOrEqualsFilter("foo", + 456); + + StringBuffer buff = new StringBuffer(); + eqq.encode(buff); + + assertEquals("(foo>=456)", buff.toString()); + + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilterTest.java new file mode 100644 index 00000000..3a152f45 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/LessThanOrEqualsFilterTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.LessThanOrEqualsFilter; + +import junit.framework.TestCase; + +/** + * @author Mattias Arthursson + */ +public class LessThanOrEqualsFilterTest extends TestCase { + + /** + * Constructor for EqualsQueryTest. + * + * @param name + */ + public LessThanOrEqualsFilterTest(String name) { + super(name); + } + + public void testEncode() { + + LessThanOrEqualsFilter eqq = new LessThanOrEqualsFilter("foo", + "*bar(fie)"); + + StringBuffer buff = new StringBuffer(); + eqq.encode(buff); + + assertEquals("(foo<=\\2abar\\28fie\\29)", buff.toString()); + + } + + public void testEncodeInt() { + + LessThanOrEqualsFilter eqq = new LessThanOrEqualsFilter("foo", 456); + + StringBuffer buff = new StringBuffer(); + eqq.encode(buff); + + assertEquals("(foo<=456)", buff.toString()); + + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/LikeFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/LikeFilterTest.java new file mode 100644 index 00000000..af3d9d1d --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/LikeFilterTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.LikeFilter; + +import junit.framework.TestCase; + +/** + * @author Anders Henja + */ +public class LikeFilterTest extends TestCase { + /** + * Constructor for LikeFilterTest. + * + * @param name + */ + public LikeFilterTest(String name) { + super(name); + } + + final public void testEncodeValue_blank() { + assertEquals("", new LikeFilter("", null).getEncodedValue()); + assertEquals(" ", new LikeFilter("", " ").getEncodedValue()); + } + + final public void testEncodeValue_normal() { + assertEquals("foo", new LikeFilter("", "foo").getEncodedValue()); + assertEquals("foo*bar", new LikeFilter("", "foo*bar").getEncodedValue()); + assertEquals("*foo*bar*", new LikeFilter("", "*foo*bar*") + .getEncodedValue()); + assertEquals("**foo**bar**", new LikeFilter("", "**foo**bar**") + .getEncodedValue()); + } + + final public void testEncodeValue_escape() { + assertEquals("*\\28*\\29*", new LikeFilter("", "*(*)*") + .getEncodedValue()); + assertEquals("*\\5c2a*", new LikeFilter("", "*\\2a*").getEncodedValue()); + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/NotFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/NotFilterTest.java new file mode 100644 index 00000000..58788e7c --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/NotFilterTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.EqualsFilter; +import org.springframework.ldap.support.filter.NotFilter; + +import com.gargoylesoftware.base.testing.EqualsTester; + +import junit.framework.TestCase; + +/** + * @author Mattias Arthursson + */ +public class NotFilterTest extends TestCase { + + public void testConstructor() { + EqualsFilter filter = new EqualsFilter("a", "b"); + NotFilter notFilter = new NotFilter(filter); + + assertEquals("(!(a=b))", notFilter.encode()); + } + + public void testEquals() { + EqualsFilter filter = new EqualsFilter("a", "b"); + NotFilter originalObject = new NotFilter(filter); + NotFilter identicalObject = new NotFilter(filter); + NotFilter differentObject = new NotFilter(new EqualsFilter("a", "a")); + NotFilter subclassObject = new NotFilter(filter) { + }; + + new EqualsTester(originalObject, identicalObject, differentObject, + subclassObject); + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/OrFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/OrFilterTest.java new file mode 100644 index 00000000..f5f5360d --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/OrFilterTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.EqualsFilter; +import org.springframework.ldap.support.filter.OrFilter; + +import junit.framework.TestCase; + +/** + * @author Adam Skogman + */ +public class OrFilterTest extends TestCase { + + /** + * Constructor for OrFilterTest. + * + * @param name + */ + public OrFilterTest(String name) { + super(name); + } + + public void testZero() { + OrFilter of = new OrFilter(); + + assertEquals("", of.encode()); + } + + public void testOne() { + OrFilter of = new OrFilter().or(new EqualsFilter("a", "b")); + + assertEquals("(a=b)", of.encode()); + } + + public void testTwo() { + OrFilter of = new OrFilter().or(new EqualsFilter("a", "b")).or( + new EqualsFilter("c", "d")); + + assertEquals("(|(a=b)(c=d))", of.encode()); + } + + public void testThree() { + OrFilter of = new OrFilter().or(new EqualsFilter("a", "b")).or( + new EqualsFilter("c", "d")).or(new EqualsFilter("e", "f")); + + assertEquals("(|(a=b)(c=d)(e=f))", of.encode()); + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilterTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilterTest.java new file mode 100644 index 00000000..d781c281 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/filter/WhitespaceWildcardsFilterTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.support.filter; + +import org.springframework.ldap.support.filter.WhitespaceWildcardsFilter; + +import junit.framework.TestCase; + +/** + * @author Adam Skogman + */ +public class WhitespaceWildcardsFilterTest extends TestCase { + + /** + * Constructor for WhitespaceWildcardsFilterTest. + * + * @param name + */ + public WhitespaceWildcardsFilterTest(String name) { + super(name); + } + + final public void testEncodeValue_blank() { + + // blank + assertEquals("*", new WhitespaceWildcardsFilter("", null) + .getEncodedValue()); + assertEquals("*", new WhitespaceWildcardsFilter("", " ") + .getEncodedValue()); + assertEquals("*", new WhitespaceWildcardsFilter("", " ") + .getEncodedValue()); + assertEquals("*", new WhitespaceWildcardsFilter("", "\t") + .getEncodedValue()); + + } + + final public void testEncodeValue_normal() { + + assertEquals("*foo*", new WhitespaceWildcardsFilter("", "foo") + .getEncodedValue()); + assertEquals("*foo*bar*", new WhitespaceWildcardsFilter("", "foo bar") + .getEncodedValue()); + assertEquals("*foo*bar*", + new WhitespaceWildcardsFilter("", " foo bar ") + .getEncodedValue()); + assertEquals("*foo*bar*", new WhitespaceWildcardsFilter("", + " \t foo \n bar \r ").getEncodedValue()); + } + + final public void testEncodeValue_escape() { + + assertEquals("*\\28\\2a\\29*", new WhitespaceWildcardsFilter("", "(*)") + .getEncodedValue()); + assertEquals("*\\2a*", new WhitespaceWildcardsFilter("", "*") + .getEncodedValue()); + assertEquals("*\\5c*", new WhitespaceWildcardsFilter("", " \\ ") + .getEncodedValue()); + + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/util/ListComparatorTest.java b/spring-ldap/src/test/java/org/springframework/ldap/util/ListComparatorTest.java new file mode 100644 index 00000000..ac456537 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/util/ListComparatorTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.util; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.ldap.util.ListComparator; + +import junit.framework.TestCase; + +/** + * Tests for ListComparator. + * + * @author Mattias Arthursson + */ +public class ListComparatorTest extends TestCase { + + private ListComparator tested; + + protected void setUp() throws Exception { + super.setUp(); + tested = new ListComparator(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testCompare_Equals() { + List list1 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0) }); + List list2 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0) }); + + int result = tested.compare(list1, list2); + assertEquals(0, result); + } + + public void testCompare_Less() { + List list1 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0) }); + List list2 = Arrays.asList(new Object[] { new Integer(0), + new Integer(1) }); + + int result = tested.compare(list1, list2); + assertTrue(result < 0); + } + + public void testCompare_Greater() { + List list1 = Arrays.asList(new Object[] { new Integer(0), + new Integer(1) }); + List list2 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0) }); + + int result = tested.compare(list1, list2); + assertTrue(result > 0); + } + + public void testCompare_Longer() { + List list1 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0), new Integer(0) }); + List list2 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0) }); + + int result = tested.compare(list1, list2); + assertTrue(result > 0); + } + + public void testCompare_Shorter() { + List list1 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0) }); + List list2 = Arrays.asList(new Object[] { new Integer(0), + new Integer(0), new Integer(0) }); + + int result = tested.compare(list1, list2); + assertTrue(result < 0); + } +} diff --git a/spring-ldap/src/test/resources/log4j.properties b/spring-ldap/src/test/resources/log4j.properties new file mode 100644 index 00000000..66b1c2ec --- /dev/null +++ b/spring-ldap/src/test/resources/log4j.properties @@ -0,0 +1,4 @@ +log4j.rootCategory=warn, stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout.ConversionPattern=%r [%t] %-5p\: %-15c{2} - %m%n +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout diff --git a/spring-ldap/xdocs/navigation.xml b/spring-ldap/xdocs/navigation.xml new file mode 100644 index 00000000..84927d4c --- /dev/null +++ b/spring-ldap/xdocs/navigation.xml @@ -0,0 +1,43 @@ + + + + + + + LdapTemplate + + + + + + + + + + + + + \ No newline at end of file

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