1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.sp;
21
22
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import javax.naming.NamingException;
28
29 import org.apache.directory.server.constants.ApacheSchemaConstants;
30 import org.apache.directory.server.core.DirectoryService;
31 import org.apache.directory.server.core.entry.ServerEntry;
32 import org.apache.directory.server.core.filtering.EntryFilteringCursor;
33 import org.apache.directory.server.core.interceptor.context.ListSuffixOperationContext;
34 import org.apache.directory.shared.ldap.entry.EntryAttribute;
35 import org.apache.directory.shared.ldap.entry.Value;
36 import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
37 import org.apache.directory.shared.ldap.constants.SchemaConstants;
38 import org.apache.directory.shared.ldap.filter.AndNode;
39 import org.apache.directory.shared.ldap.filter.BranchNode;
40 import org.apache.directory.shared.ldap.filter.EqualityNode;
41 import org.apache.directory.shared.ldap.filter.SearchScope;
42 import org.apache.directory.shared.ldap.message.AliasDerefMode;
43 import org.apache.directory.shared.ldap.name.LdapDN;
44
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class LdapClassLoader extends ClassLoader
64 {
65 private static final Logger log = LoggerFactory.getLogger( LdapClassLoader.class );
66 public static String defaultSearchContextsConfig = "cn=classLoaderDefaultSearchContext,ou=configuration,ou=system";
67
68 private LdapDN defaultSearchDn;
69 private DirectoryService directoryService;
70
71
72 public LdapClassLoader( DirectoryService directoryService ) throws NamingException
73 {
74 super( LdapClassLoader.class.getClassLoader() );
75 this.directoryService = directoryService;
76 defaultSearchDn = new LdapDN( defaultSearchContextsConfig );
77 defaultSearchDn.normalize( directoryService.getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
78 }
79
80
81 private byte[] findClassInDIT( List<LdapDN> searchContexts, String name ) throws ClassNotFoundException
82 {
83
84 BranchNode filter = new AndNode( );
85 filter.addNode( new EqualityNode<String>( "fullyQualifiedJavaClassName",
86 new ClientStringValue( name ) ) );
87 filter.addNode( new EqualityNode<String>( SchemaConstants.OBJECT_CLASS_AT,
88 new ClientStringValue( ApacheSchemaConstants.JAVA_CLASS_OC ) ) );
89
90 try
91 {
92 for ( LdapDN base : searchContexts )
93 {
94 EntryFilteringCursor cursor = null;
95 try
96 {
97 cursor = directoryService.getAdminSession()
98 .search( base, SearchScope.SUBTREE, filter, AliasDerefMode.DEREF_ALWAYS, null );
99
100 cursor.beforeFirst();
101 if ( cursor.next() )
102 {
103 log.debug( "Class {} found under {} search context.", name, base );
104 ServerEntry classEntry = cursor.get();
105
106 if ( cursor.next() )
107 {
108 ServerEntry other = cursor.get();
109 log.warn( "More than one class found on classpath at locations: {} \n\tand {}",
110 classEntry, other );
111 }
112
113 return classEntry.get( "javaClassByteCode" ).getBytes();
114 }
115 }
116 finally
117 {
118 if ( cursor != null )
119 {
120 cursor.close();
121 }
122 }
123 }
124 }
125 catch ( Exception e )
126 {
127 log.error( "Exception while searching the DIT for class: " + name, e );
128 }
129
130 throw new ClassNotFoundException();
131 }
132
133
134 public Class<?> findClass( String name ) throws ClassNotFoundException
135 {
136 byte[] classBytes = null;
137
138 try
139 {
140
141
142
143
144
145 ServerEntry configEntry = null;
146
147 try
148 {
149 configEntry = directoryService.getAdminSession().lookup( defaultSearchDn );
150 }
151 catch ( NamingException e )
152 {
153 log.debug( "No configuration data found for class loader default search contexts." );
154 }
155
156 if ( configEntry != null )
157 {
158 List<LdapDN> searchContexts = new ArrayList<LdapDN>();
159 EntryAttribute attr = configEntry.get( "classLoaderDefaultSearchContext" );
160
161 for ( Value<?> val : attr )
162 {
163 LdapDN dn = new LdapDN( ( String ) val.get() );
164 dn.normalize( directoryService.getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
165 searchContexts.add( dn );
166 }
167
168 try
169 {
170 classBytes = findClassInDIT( searchContexts, name );
171
172 log.debug( "Class " + name + " found under default search contexts." );
173 }
174 catch ( ClassNotFoundException e )
175 {
176 log.debug( "Class " + name + " could not be found under default search contexts." );
177 }
178 }
179
180 if ( classBytes == null )
181 {
182 List<LdapDN> namingContexts = new ArrayList<LdapDN>();
183
184
185
186 Iterator<String> suffixes =
187 directoryService.getPartitionNexus().listSuffixes(
188 new ListSuffixOperationContext( directoryService.getAdminSession() ) );
189
190 while ( suffixes.hasNext() )
191 {
192 LdapDN dn = new LdapDN( suffixes.next() );
193 dn.normalize( directoryService.getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
194 namingContexts.add( dn );
195 }
196
197 classBytes = findClassInDIT( namingContexts, name );
198 }
199 }
200 catch ( ClassNotFoundException e )
201 {
202 String msg = "Class " + name + " not found in DIT.";
203 log.debug( msg );
204 throw new ClassNotFoundException( msg );
205 }
206 catch ( Exception e )
207 {
208 String msg = "Encountered failure while searching directory for class: " + name;
209 log.error( msg + e );
210 throw new ClassNotFoundException( msg );
211 }
212
213 return defineClass( name, classBytes, 0, classBytes.length );
214 }
215 }