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.tools.schema;
21
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.io.Reader;
30 import java.io.Writer;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 import org.apache.directory.server.schema.bootstrap.AbstractBootstrapSchema;
35 import org.apache.directory.server.schema.bootstrap.BootstrapSchema;
36 import org.apache.directory.server.schema.bootstrap.ProducerTypeEnum;
37 import org.apache.directory.shared.ldap.constants.SchemaConstants;
38 import org.apache.directory.shared.ldap.schema.parser.AttributeTypeLiteral;
39 import org.apache.directory.shared.ldap.schema.parser.ObjectClassLiteral;
40 import org.apache.directory.shared.ldap.schema.parser.OpenLdapSchemaParser;
41 import org.apache.maven.plugin.AbstractMojo;
42 import org.apache.maven.plugin.MojoExecutionException;
43 import org.apache.maven.project.MavenProject;
44 import org.apache.velocity.VelocityContext;
45 import org.apache.velocity.app.Velocity;
46
47
48
49
50
51
52
53
54
55
56
57 public class DirectorySchemaToolMojo extends AbstractMojo
58 {
59
60
61
62
63 private File sourceDirectory;
64
65
66
67
68
69 private File outputDirectory;
70
71
72
73
74
75 private String defaultPackage;
76
77
78
79
80
81 private String defaultOwner;
82
83
84
85
86
87 private Schema[] schemas;
88
89
90
91
92
93 private boolean verboseOutput;
94
95
96
97
98
99 private MavenProject project;
100
101
102 public DirectorySchemaToolMojo() throws Exception
103 {
104 Velocity.init();
105 }
106
107
108 private void generate( BootstrapSchema schema ) throws Exception
109 {
110 if ( schema == null )
111 {
112 throw new NullPointerException( "the schema property must be set" );
113 }
114
115 String filePath = sourceDirectory + File.separator + schema.getSchemaName() + ".schema";
116 InputStream in = new FileInputStream( filePath );
117 OpenLdapSchemaParser parser = new OpenLdapSchemaParser();
118 parser.parse( in );
119 generateSchema( schema );
120 generateAttributeTypes( parser, schema );
121 generateObjectClasses( parser, schema );
122 generateRest( schema );
123 }
124
125
126 protected void generateSchema( BootstrapSchema schema ) throws Exception
127 {
128 StringBuffer schemaCapped = new StringBuffer();
129 schemaCapped.append( Character.toUpperCase( schema.getSchemaName().charAt( 0 ) ) );
130 schemaCapped.append( schema.getSchemaName().substring( 1, schema.getSchemaName().length() ) );
131
132 VelocityContext context = new VelocityContext();
133 context.put( "package", schema.getPackageName() );
134 context.put( "classname", schemaCapped.toString() + "Schema" );
135 context.put( "schema", schema.getSchemaName() );
136 context.put( "owner", schema.getOwner() );
137 context.put( "deps", schema.getDependencies() );
138
139 Reader fileIn = getResourceReader( "Schema.template" );
140 Writer writer = getResourceWriter( schema.getPackageName(), schema.getUnqualifiedClassName() );
141 Velocity.evaluate( context, writer, "LOG", fileIn );
142
143 writer.flush();
144 writer.close();
145 }
146
147
148 protected void generateRest( BootstrapSchema schema ) throws Exception
149 {
150 List types = new ArrayList();
151 types.addAll( ProducerTypeEnum.getList() );
152 types.remove( ProducerTypeEnum.ATTRIBUTE_TYPE_PRODUCER );
153 types.remove( ProducerTypeEnum.OBJECT_CLASS_PRODUCER );
154
155 ProducerTypeEnum type = null;
156 for ( int ii = 0; ii < types.size(); ii++ )
157 {
158 type = ( ProducerTypeEnum ) types.get( ii );
159
160 if ( exists( schema.getFullDefaultBaseClassName( type ), type ) )
161 {
162 continue;
163 }
164
165 VelocityContext context = new VelocityContext();
166 context.put( "package", schema.getPackageName() );
167 context.put( "classname", schema.getUnqualifiedClassName( type ) );
168 context.put( "schema", schema.getSchemaName() );
169 context.put( "owner", schema.getOwner() );
170 context.put( "type", type.getName().substring( 0, type.getName().length() - 8 ) );
171
172 String typeName = null;
173
174 switch ( type )
175 {
176 case COMPARATOR_PRODUCER :
177 typeName = "ProducerTypeEnum.COMPARATOR_PRODUCER";
178 break;
179
180 case DIT_CONTENT_RULE_PRODUCER :
181 typeName = "ProducerTypeEnum.DIT_CONTENT_RULE_PRODUCER";
182 break;
183
184 case DIT_STRUCTURE_RULE_PRODUCER :
185 typeName = "ProducerTypeEnum.DIT_STRUCTURE_RULE_PRODUCER";
186 break;
187
188 case MATCHING_RULE_PRODUCER :
189 typeName = "ProducerTypeEnum.MATCHING_RULE_PRODUCER";
190 break;
191
192 case MATCHING_RULE_USE_PRODUCER :
193 typeName = "ProducerTypeEnum.MATCHING_RULE_USE_PRODUCER";
194 break;
195
196 case NAME_FORM_PRODUCER :
197 typeName = "ProducerTypeEnum.NAME_FORM_PRODUCER";
198 break;
199
200 case NORMALIZER_PRODUCER :
201 typeName = "ProducerTypeEnum.NORMALIZER_PRODUCER";
202 break;
203
204 case SYNTAX_CHECKER_PRODUCER :
205 typeName = "ProducerTypeEnum.SYNTAX_CHECKER_PRODUCER";
206 break;
207
208 case SYNTAX_PRODUCER :
209 typeName = "ProducerTypeEnum.SYNTAX_PRODUCER";
210 break;
211
212 default:
213 throw new IllegalStateException( "Unexpected producer: " + type.getName() );
214 }
215
216 context.put( "typeName", typeName );
217 runVelocity( schema.getPackageName(), schema.getUnqualifiedClassName( type ), context, "typeless.template",
218 type );
219 }
220 }
221
222
223 protected void generateAttributeTypes( OpenLdapSchemaParser parser, BootstrapSchema schema ) throws Exception
224 {
225 final ProducerTypeEnum type = ProducerTypeEnum.ATTRIBUTE_TYPE_PRODUCER;
226
227
228 if ( exists( schema.getFullDefaultBaseClassName( type ), type ) )
229 {
230 return;
231 }
232
233 int size = parser.getAttributeTypes().size();
234 AttributeTypeLiteral[] attributeTypes = new AttributeTypeLiteral[size];
235 attributeTypes = ( AttributeTypeLiteral[] ) parser.getAttributeTypes().toArray( attributeTypes );
236
237 VelocityContext context = new VelocityContext();
238 context.put( "package", schema.getPackageName() );
239 context.put( "classname", schema.getUnqualifiedClassName( type ) );
240 context.put( "schema", schema.getSchemaName() );
241 context.put( "owner", schema.getOwner() );
242 context.put( "schemaDepCount", new Integer( schema.getDependencies().length ) );
243 context.put( "schemaDeps", new String[]
244 { "dep1", "dep2" } );
245 context.put( "attrTypes", attributeTypes );
246 runVelocity( schema.getPackageName(), schema.getUnqualifiedClassName( type ), context,
247 "AttributeTypes.template", type );
248 }
249
250
251 protected void generateObjectClasses( OpenLdapSchemaParser parser, BootstrapSchema schema ) throws Exception
252 {
253 final ProducerTypeEnum type = ProducerTypeEnum.OBJECT_CLASS_PRODUCER;
254
255
256 if ( exists( schema.getFullDefaultBaseClassName( type ), type ) )
257 {
258 return;
259 }
260
261 int size = parser.getObjectClassTypes().size();
262 ObjectClassLiteral[] objectClasses = new ObjectClassLiteral[size];
263 objectClasses = ( ObjectClassLiteral[] ) parser.getObjectClassTypes().toArray( objectClasses );
264
265 VelocityContext context = new VelocityContext();
266 context.put( "package", schema.getPackageName() );
267 context.put( "classname", schema.getUnqualifiedClassName( type ) );
268 context.put( "schema", schema.getSchemaName() );
269 context.put( "owner", schema.getOwner() );
270 context.put( "schemaDepCount", new Integer( schema.getDependencies().length ) );
271 context.put( "schemaDeps", new String[]
272 { "dep1", "dep2" } );
273 context.put( SchemaConstants.OBJECT_CLASSES_AT, objectClasses );
274 runVelocity( schema.getPackageName(), schema.getUnqualifiedClassName( type ), context,
275 "ObjectClasses.template", type );
276 }
277
278
279 protected void runVelocity( String pkg, String uqcn, VelocityContext context, String template, ProducerTypeEnum type )
280 throws Exception
281 {
282 Reader fileIn = getResourceReader( template );
283 Writer writer = getResourceWriter( pkg, uqcn );
284 Velocity.evaluate( context, writer, "LOG", fileIn );
285 writer.flush();
286 writer.close();
287 }
288
289
290 protected Reader getResourceReader( String res ) throws IOException
291 {
292 return new InputStreamReader( getClass().getResourceAsStream( res ) );
293 }
294
295
296 protected boolean mkdirs( String base, String path )
297 {
298 String[] comps = path.split( "/" );
299 File file = new File( base );
300
301 if ( !file.exists() )
302 {
303 file.mkdirs();
304 }
305
306 for ( int ii = 0; ii < comps.length; ii++ )
307 {
308 file = new File( file, comps[ii] );
309
310 if ( !file.exists() )
311 {
312 file.mkdirs();
313 }
314 }
315
316 return file.exists();
317 }
318
319
320 protected FileWriter getResourceWriter( String pkg, String classname ) throws IOException
321 {
322 mkdirs( outputDirectory.getPath(), pkg.replace( '.', File.separatorChar ) );
323 File base = outputDirectory;
324 String relativePath = pkg.replace( '.', File.separatorChar );
325 File dir = new File( base, relativePath );
326 return new FileWriter( new File( dir, classname + ".java" ) );
327 }
328
329
330 protected boolean exists( String defaultClass, ProducerTypeEnum type )
331 {
332
333
334 File defaultFile = new File( project.getBuild().getSourceDirectory() + File.separator
335 + getFilePath( defaultClass ) );
336 return defaultFile.exists();
337 }
338
339
340 private String getFilePath( String fqcn )
341 {
342 String path = fqcn.replace( '.', File.separatorChar );
343 path += ".java";
344 return path;
345 }
346
347
348 private boolean isStale( BootstrapSchema schema )
349 {
350 String pkgPath = schema.getPackageName().replace( '.', File.separatorChar );
351 File dir = new File( outputDirectory, pkgPath );
352 File schemaClassFile = new File( dir, schema.getUnqualifiedClassName() + ".java" );
353
354 if ( !schemaClassFile.exists() )
355 {
356 return true;
357 }
358
359 File schemaFile = new File( sourceDirectory, schema.getSchemaName() + ".schema" );
360 return schemaFile.lastModified() > schemaClassFile.lastModified();
361 }
362
363
364 public void execute() throws MojoExecutionException
365 {
366
367 if ( schemas == null || schemas.length == 0 )
368 {
369 getLog().warn( "No schemas defined for directory plugin!" );
370 return;
371 }
372
373
374
375 for ( int ii = 0; ii < schemas.length; ii++ )
376 {
377 Schema schema = schemas[ii];
378
379 if ( schema.getName() == null )
380 {
381 String msg = ii + "th schema configuration element must specify a name.";
382 getLog().error( msg );
383 throw new MojoExecutionException( msg );
384 }
385
386 if ( schema.getPkg() == null )
387 {
388 schema.setPkg( defaultPackage );
389 }
390
391 if ( schema.getOwner() == null )
392 {
393 schema.setOwner( defaultOwner );
394 }
395 }
396
397
398 if ( verboseOutput )
399 {
400 report();
401 }
402
403
404 if ( !outputDirectory.exists() )
405 {
406 outputDirectory.mkdirs();
407 }
408
409
410 for ( int ii = 0; ii < schemas.length; ii++ )
411 {
412 try
413 {
414 BootstrapSchema bootstrapSchema = new AbstractBootstrapSchema( schemas[ii].getOwner(), schemas[ii]
415 .getName(), schemas[ii].getPkg(), schemas[ii].getDependencies() )
416 {
417 };
418
419 if ( isStale( bootstrapSchema ) )
420 {
421 getLog().info( "Generating " + schemas[ii].getName() + " schema." );
422 generate( bootstrapSchema );
423 }
424 else
425 {
426 getLog().info( schemas[ii].getName() + " schema is up to date." );
427 }
428 }
429 catch ( Exception e )
430 {
431 throw new MojoExecutionException( "Failed while generating sources for " + schemas[ii].getName(), e );
432 }
433 }
434
435 project.addCompileSourceRoot( outputDirectory.getPath() );
436 }
437
438
439 private void report()
440 {
441 getLog().info( "===================================================================" );
442 getLog().info( "[directory:generate]" );
443 getLog().info( "sourceDirectory = " + sourceDirectory );
444 getLog().info( "outputDirectory = " + outputDirectory );
445 getLog().info( "defaultPackage = " + defaultPackage );
446 getLog().info( "defaultOwner = " + defaultOwner );
447 getLog().info( "----------------------------- schemas -----------------------------" );
448
449 if ( schemas != null )
450 {
451 for ( int ii = 0; ii < schemas.length; ii++ )
452 {
453 getLog().info( "SCHEMA: " + schemas[ii].getName() );
454
455 if ( schemas[ii].getDependencies() != null )
456 {
457 StringBuffer buf = new StringBuffer();
458 for ( int jj = 0; jj < schemas[ii].getDependencies().length; jj++ )
459 {
460 buf.append( schemas[ii].getDependencies()[jj] );
461 buf.append( " " );
462 }
463 getLog().info( "DEPENDENCIES: " + buf.toString() );
464 }
465
466 getLog().info( "PACKAGE: " + schemas[ii].getPkg() );
467 getLog().info( "OWNER: " + schemas[ii].getOwner() );
468
469 if ( ii + 1 < schemas.length )
470 {
471 getLog().info( "" );
472 }
473 }
474 }
475
476 getLog().info( "===================================================================" );
477 }
478 }