1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.model.schema.parsers;
21
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.nio.charset.Charset;
28 import java.nio.file.Files;
29 import java.nio.file.Paths;
30 import java.text.ParseException;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35
36 import org.apache.commons.lang.exception.ExceptionUtils;
37 import org.apache.directory.api.i18n.I18n;
38 import org.apache.directory.api.ldap.model.schema.AttributeType;
39 import org.apache.directory.api.ldap.model.schema.MutableAttributeType;
40 import org.apache.directory.api.ldap.model.schema.ObjectClass;
41 import org.apache.directory.api.ldap.model.schema.SchemaObject;
42 import org.apache.directory.api.ldap.model.schema.syntaxCheckers.OpenLdapObjectIdentifierMacro;
43
44 import antlr.RecognitionException;
45 import antlr.TokenStreamException;
46
47
48
49
50
51
52
53 public class OpenLdapSchemaParser extends AbstractSchemaParser<SchemaObject>
54 {
55
56
57 private List<Object> schemaDescriptions;
58
59
60 private List<MutableAttributeType> attributeTypes;
61
62
63 private List<ObjectClass> objectClasses;
64
65
66 private Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros;
67
68
69 private boolean isResolveObjectIdentifierMacros;
70
71
72
73
74
75
76
77 public OpenLdapSchemaParser() throws IOException
78 {
79 super( null, null, null, null );
80 isResolveObjectIdentifierMacros = true;
81 super.setQuirksMode( true );
82 }
83
84
85 @Override
86 protected SchemaObject doParse() throws RecognitionException, TokenStreamException
87 {
88 throw new UnsupportedOperationException( "OpenLdapSchemaParser is not a normal schema parser" );
89 }
90
91
92
93
94
95 public void clear()
96 {
97 }
98
99
100
101
102
103
104
105 public List<MutableAttributeType> getAttributeTypes()
106 {
107 return attributeTypes;
108 }
109
110
111
112
113
114
115
116 public List<ObjectClass> getObjectClassTypes()
117 {
118 return objectClasses;
119 }
120
121
122
123
124
125
126
127 public Map<String, OpenLdapObjectIdentifierMacro> getObjectIdentifierMacros()
128 {
129 return objectIdentifierMacros;
130 }
131
132
133
134
135
136
137
138
139 private void afterParse() throws ParseException
140 {
141 objectClasses = new ArrayList<>();
142 attributeTypes = new ArrayList<>();
143 objectIdentifierMacros = new HashMap<>();
144
145
146 for ( Object obj : schemaDescriptions )
147 {
148 if ( obj instanceof OpenLdapObjectIdentifierMacro )
149 {
150 OpenLdapObjectIdentifierMacro oid = ( OpenLdapObjectIdentifierMacro ) obj;
151 objectIdentifierMacros.put( oid.getName(), oid );
152 }
153 else if ( obj instanceof AttributeType )
154 {
155 MutableAttributeType attributeType = ( MutableAttributeType ) obj;
156
157 attributeTypes.add( attributeType );
158 }
159 else if ( obj instanceof ObjectClass )
160 {
161 ObjectClass objectClass = ( ObjectClass ) obj;
162
163 objectClasses.add( objectClass );
164 }
165 }
166
167 if ( isResolveObjectIdentifierMacros() )
168 {
169
170 for ( OpenLdapObjectIdentifierMacro oid : objectIdentifierMacros.values() )
171 {
172 resolveObjectIdentifierMacro( oid );
173 }
174
175
176 for ( ObjectClass objectClass : objectClasses )
177 {
178 objectClass.setOid( getResolveOid( objectClass.getOid() ) );
179 }
180
181
182 for ( MutableAttributeType attributeType : attributeTypes )
183 {
184 attributeType.setOid( getResolveOid( attributeType.getOid() ) );
185 attributeType.setSyntaxOid( getResolveOid( attributeType.getSyntaxOid() ) );
186 }
187
188 }
189 }
190
191
192 private String getResolveOid( String oid )
193 {
194 if ( oid != null && oid.indexOf( ':' ) != -1 )
195 {
196
197 String[] nameAndSuffix = oid.split( ":" );
198 if ( objectIdentifierMacros.containsKey( nameAndSuffix[0] ) )
199 {
200 OpenLdapObjectIdentifierMacro macro = objectIdentifierMacros.get( nameAndSuffix[0] );
201 return macro.getResolvedOid() + "." + nameAndSuffix[1];
202 }
203 }
204 return oid;
205 }
206
207
208 private void resolveObjectIdentifierMacro( OpenLdapObjectIdentifierMacro macro ) throws ParseException
209 {
210 String rawOidOrNameSuffix = macro.getRawOidOrNameSuffix();
211
212 if ( macro.isResolved() )
213 {
214
215 return;
216 }
217 else if ( rawOidOrNameSuffix.indexOf( ':' ) != -1 )
218 {
219
220 String[] nameAndSuffix = rawOidOrNameSuffix.split( ":" );
221 if ( objectIdentifierMacros.containsKey( nameAndSuffix[0] ) )
222 {
223 OpenLdapObjectIdentifierMacro parentMacro = objectIdentifierMacros.get( nameAndSuffix[0] );
224 resolveObjectIdentifierMacro( parentMacro );
225 macro.setResolvedOid( parentMacro.getResolvedOid() + "." + nameAndSuffix[1] );
226 }
227 else
228 {
229 throw new ParseException( I18n.err( I18n.ERR_04257, nameAndSuffix[0] ), 0 );
230 }
231
232 }
233 else
234 {
235
236 if ( objectIdentifierMacros.containsKey( rawOidOrNameSuffix ) )
237 {
238 OpenLdapObjectIdentifierMacro parentMacro = objectIdentifierMacros.get( rawOidOrNameSuffix );
239 resolveObjectIdentifierMacro( parentMacro );
240 macro.setResolvedOid( parentMacro.getResolvedOid() );
241 }
242 else
243 {
244 macro.setResolvedOid( rawOidOrNameSuffix );
245 }
246 }
247 }
248
249
250
251
252
253
254
255
256
257 @Override
258 public SchemaObject parse( String schemaObject ) throws ParseException
259 {
260 if ( schemaObject == null || ( schemaObject.trim().length() == 0 ) )
261 {
262 throw new ParseException( I18n.err( I18n.ERR_04258 ), 0 );
263 }
264
265
266 reset( schemaObject );
267 invokeParser( schemaObject );
268
269 if ( !schemaDescriptions.isEmpty() )
270 {
271 for ( Object obj : schemaDescriptions )
272 {
273 if ( obj instanceof SchemaObject )
274 {
275 return ( SchemaObject ) obj;
276 }
277 }
278 }
279 return null;
280 }
281
282
283 private void invokeParser( String subject ) throws ParseException
284 {
285 try
286 {
287 monitor.startedParse( "starting parse on:\n" + subject );
288 schemaDescriptions = parser.openLdapSchema();
289 afterParse();
290 monitor.finishedParse( "Done parsing!" );
291 }
292 catch ( RecognitionException re )
293 {
294 String msg = "Parser failure on:\n\t" + subject;
295 msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( re );
296 throw new ParseException( msg, re.getColumn() );
297 }
298 catch ( TokenStreamException tse )
299 {
300 String msg = "Parser failure on:\n\t" + subject;
301 msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( tse );
302 throw new ParseException( msg, 0 );
303 }
304 }
305
306
307
308
309
310
311
312
313
314 public void parse( InputStream schemaIn ) throws IOException, ParseException
315 {
316 InputStreamReader in = new InputStreamReader( schemaIn, Charset.defaultCharset() );
317 lexer.prepareNextInput( in );
318 parser.resetState();
319
320 invokeParser( "schema input stream ==> " + schemaIn.toString() );
321 }
322
323
324
325
326
327
328
329
330
331 public void parse( File schemaFile ) throws IOException, ParseException
332 {
333 InputStreamReader in = new InputStreamReader(
334 Files.newInputStream( Paths.get( schemaFile.getPath() ) ), Charset.defaultCharset() );
335 lexer.prepareNextInput( in );
336 parser.resetState();
337
338 invokeParser( "schema file ==> " + schemaFile.getAbsolutePath() );
339 }
340
341
342
343
344
345
346
347 public boolean isResolveObjectIdentifierMacros()
348 {
349 return isResolveObjectIdentifierMacros;
350 }
351
352
353
354
355
356
357
358 public void setResolveObjectIdentifierMacros( boolean resolveObjectIdentifierMacros )
359 {
360 this.isResolveObjectIdentifierMacros = resolveObjectIdentifierMacros;
361 }
362
363 }