View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.tools.schema;
18  
19  
20  import java.io.*;
21  import java.util.List;
22  import java.util.ArrayList;
23  
24  import org.apache.velocity.app.Velocity;
25  import org.apache.velocity.VelocityContext;
26  
27  import org.apache.ldap.server.schema.bootstrap.BootstrapSchema;
28  import org.apache.ldap.server.schema.bootstrap.ProducerTypeEnum;
29  
30  
31  /***
32   * Generates Eve schema classses from OpenLDAP schema files.
33   *
34   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
35   * @version $Rev: 264732 $
36   */
37  public class DirectorySchemaTool
38  {
39      private static String basedir = System.getProperty( "basedir", "." );
40  
41      /*** property for dir where OpenLDAP schema files and deps file are stored */
42      public static final String SCHEMA_SRC_DIR_PROP = "maven.ldap.server.schema.src.dir";
43  
44      /*** property for dir where the generated class files are created */
45      public static final String SCHEMA_TARGET_DIR_PROP = "maven.ldap.server.schema.target.dir";
46  
47      /*** default dir where OpenLDAP schema files and deps file are kept */
48      public static final String SCHEMA_SRC_DIR_DEFAULT =
49              basedir + File.separator + "src" + File.separator + "main" 
50  		+ File.separator + "schema";
51  
52      /*** default dir where java src files are kept */
53      public static final String JAVA_SRC_DIR_DEFAULT =
54              basedir + File.separator + "src" + File.separator + "main" 
55  		+ File.separator + "java";
56  
57     /*** property for the name of the schema dependency file */
58      public static final String SCHEMA_DEP_FILE_DEFAULT = "schema.deps";
59  
60      /*** default dir where the generated class files are created */
61      public static final String SCHEMA_TARGET_DIR_DEFAULT =
62              basedir + File.separator + "target" + File.separator + "schema";
63  
64  
65      /*** the source directory where the schema OpenLDAP source files are kept */
66      private String schemaSrcDir = SCHEMA_SRC_DIR_DEFAULT;
67  
68      /*** the directory where we generate schema class files */
69      private String schemaTargetDir = SCHEMA_TARGET_DIR_DEFAULT;
70  
71      private String javaSrcDir = JAVA_SRC_DIR_DEFAULT;
72  
73      private BootstrapSchema schema;
74  
75      private OpenLdapSchemaParser parser;
76  
77  
78  
79      public DirectorySchemaTool() throws Exception
80      {
81          parser = new OpenLdapSchemaParser();
82  
83          Velocity.init();
84      }
85  
86  
87      public String getSchemaSrcDir()
88      {
89          return schemaSrcDir;
90      }
91  
92  
93      public void setSchemaSrcDir( String schemaSrcDir )
94      {
95          this.schemaSrcDir = schemaSrcDir;
96      }
97  
98  
99      public String getSchemaTargetDir()
100     {
101         return schemaTargetDir;
102     }
103 
104 
105     public void setSchemaTargetDir( String schemaTargetDir )
106     {
107         this.schemaTargetDir = schemaTargetDir;
108     }
109 
110 
111     public String getJavaSrcDir()
112     {
113         return javaSrcDir;
114     }
115 
116 
117     public void setJavaSrcDir( String javaSrcDir )
118     { 
119         this.javaSrcDir = javaSrcDir;
120     }
121 
122 
123     public BootstrapSchema getSchema()
124     {
125         return schema;
126     }
127 
128 
129     public void setSchema( BootstrapSchema schema )
130     {
131         this.schema = schema;
132     }
133 
134 
135     public void generate() throws Exception
136     {
137         if ( schema == null )
138         {
139             throw new NullPointerException( "the schema property must be set" );
140         }
141 
142         String filePath = schemaSrcDir + File.separator + schema.getSchemaName() + ".schema";
143 
144         InputStream in = new FileInputStream( filePath );
145 
146         parser.parse( in );
147 
148         generateSchema();
149 
150         generateAttributeTypes();
151 
152         generateObjectClasses();
153 
154         generateRest();
155     }
156 
157 
158     protected void generateSchema() throws Exception
159     {
160         StringBuffer schemaCapped = new StringBuffer();
161 
162         schemaCapped.append( Character.toUpperCase( schema.getSchemaName().charAt( 0 ) ) );
163 
164         schemaCapped.append( schema.getSchemaName().substring( 1, schema.getSchemaName().length() ) );
165 
166         VelocityContext context = new VelocityContext();
167 
168         context.put( "package", schema.getPackageName() );
169 
170         context.put( "classname", schemaCapped.toString() + "Schema" );
171 
172         context.put( "schema", schema.getSchemaName() );
173 
174         context.put( "owner", schema.getOwner() ) ;
175 
176         context.put( "deps", schema.getDependencies()  ) ;
177 
178         Reader fileIn = getResourceReader( "Schema.template" );
179 
180         Writer writer = getResourceWriter( schema.getUnqualifiedClassName() );
181 
182         Velocity.evaluate( context, writer, "LOG", fileIn );
183 
184         writer.flush();
185 
186         writer.close();
187     }
188 
189 
190     protected void generateRest() throws Exception
191     {
192         List types = new ArrayList();
193 
194         types.addAll( ProducerTypeEnum.list() );
195 
196         types.remove( ProducerTypeEnum.ATTRIBUTE_TYPE_PRODUCER );
197 
198         types.remove( ProducerTypeEnum.OBJECT_CLASS_PRODUCER );
199 
200         ProducerTypeEnum type = null;
201 
202         for ( int ii = 0; ii < types.size(); ii++ )
203         {
204             type = ( ProducerTypeEnum ) types.get( ii );
205 
206             if ( exists( type ) )
207             {
208                 continue;
209             }
210 
211 
212             VelocityContext context = new VelocityContext();
213 
214             context.put( "package", schema.getPackageName() );
215 
216             context.put( "classname", schema.getUnqualifiedClassName( type ) );
217 
218             context.put( "schema", schema.getSchemaName() );
219 
220             context.put( "owner", schema.getOwner() ) ;
221 
222             context.put( "type", type.getName().substring( 0, type.getName().length() - 8 ) ) ;
223 
224             String typeName = null;
225 
226             switch( type.getValue() )
227             {
228                 case( ProducerTypeEnum.COMPARATOR_PRODUCER_VAL ):
229 
230                     typeName = "ProducerTypeEnum.COMPARATOR_PRODUCER";
231 
232                     break;
233 
234                 case( ProducerTypeEnum.DIT_CONTENT_RULE_PRODUCER_VAL ):
235 
236                     typeName = "ProducerTypeEnum.DIT_CONTENT_RULE_PRODUCER";
237 
238                     break;
239 
240                 case( ProducerTypeEnum.DIT_STRUCTURE_RULE_PRODUCER_VAL ):
241 
242                     typeName = "ProducerTypeEnum.DIT_STRUCTURE_RULE_PRODUCER";
243 
244                     break;
245 
246                 case( ProducerTypeEnum.MATCHING_RULE_PRODUCER_VAL ):
247 
248                     typeName = "ProducerTypeEnum.MATCHING_RULE_PRODUCER";
249 
250                     break;
251 
252                 case( ProducerTypeEnum.MATCHING_RULE_USE_PRODUCER_VAL ):
253 
254                     typeName = "ProducerTypeEnum.MATCHING_RULE_USE_PRODUCER";
255 
256                     break;
257 
258                 case( ProducerTypeEnum.NAME_FORM_PRODUCER_VAL ):
259 
260                     typeName = "ProducerTypeEnum.NAME_FORM_PRODUCER";
261 
262                     break;
263 
264                 case( ProducerTypeEnum.NORMALIZER_PRODUCER_VAL ):
265 
266                     typeName = "ProducerTypeEnum.NORMALIZER_PRODUCER";
267 
268                     break;
269 
270                 case( ProducerTypeEnum.SYNTAX_CHECKER_PRODUCER_VAL ):
271 
272                     typeName = "ProducerTypeEnum.SYNTAX_CHECKER_PRODUCER";
273 
274                     break;
275 
276                 case( ProducerTypeEnum.SYNTAX_PRODUCER_VAL ):
277 
278                     typeName = "ProducerTypeEnum.SYNTAX_PRODUCER";
279 
280                     break;
281 
282                 case( ProducerTypeEnum.STATE_FACTORY_PRODUCER_VAL ):
283 
284                     typeName = "ProducerTypeEnum.STATE_FACTORY_PRODUCER";
285 
286                     break;
287 
288                 case( ProducerTypeEnum.OBJECT_FACTORY_PRODUCER_VAL ):
289 
290                     typeName = "ProducerTypeEnum.OBJECT_FACTORY_PRODUCER";
291 
292                     break;
293 
294                 default:
295 
296                     throw new IllegalStateException( "Unexpected producer: " + type.getName() );
297 
298             }
299 
300             context.put( "typeName", typeName ) ;
301 
302             runVelocity( context, "typeless.template", type );
303         }
304     }
305 
306 
307     protected void generateAttributeTypes() throws Exception
308     {
309         final ProducerTypeEnum type = ProducerTypeEnum.ATTRIBUTE_TYPE_PRODUCER;
310 
311         // check to see if the producer exists for this type
312         if ( exists( type ) )
313         {
314             return;
315         }
316 
317         int size = parser.getAttributeTypes().size();
318 
319         AttributeTypeLiteral[] attributeTypes = new AttributeTypeLiteral[size];
320 
321         attributeTypes = ( AttributeTypeLiteral[] ) parser.getAttributeTypes().values().toArray( attributeTypes );
322 
323         VelocityContext context = new VelocityContext();
324 
325         context.put( "package", schema.getPackageName() );
326 
327         context.put( "classname", schema.getUnqualifiedClassName( type ) );
328 
329         context.put( "schema", schema.getSchemaName() );
330 
331         context.put( "owner", schema.getOwner() ) ;
332 
333         context.put( "schemaDepCount", new Integer( schema.getDependencies().length ) );
334 
335         context.put( "schemaDeps", new String[] { "dep1", "dep2" }  ) ;
336 
337         context.put( "attrTypes", attributeTypes );
338 
339         runVelocity( context, "AttributeTypes.template", type );
340     }
341 
342 
343     protected void generateObjectClasses() throws Exception
344     {
345         final ProducerTypeEnum type = ProducerTypeEnum.OBJECT_CLASS_PRODUCER;
346 
347         // check to see if the producer exists for this type
348         if ( exists( type ) )
349         {
350             return;
351         }
352 
353         int size = parser.getObjectClassTypes().size();
354 
355         ObjectClassLiteral[] objectClasses = new ObjectClassLiteral[size];
356 
357         objectClasses = ( ObjectClassLiteral[] ) parser.getObjectClassTypes().values().toArray( objectClasses );
358 
359         VelocityContext context = new VelocityContext();
360 
361         context.put( "package", schema.getPackageName() );
362 
363         context.put( "classname", schema.getUnqualifiedClassName( type ) );
364 
365         context.put( "schema", schema.getSchemaName() );
366 
367         context.put( "owner", schema.getOwner() ) ;
368 
369         context.put( "schemaDepCount", new Integer( schema.getDependencies().length ) );
370 
371         context.put( "schemaDeps", new String[] { "dep1", "dep2" }  ) ;
372 
373         context.put( "objectClasses", objectClasses );
374 
375         runVelocity( context, "ObjectClasses.template", type );
376     }
377 
378 
379 
380     protected void runVelocity( VelocityContext context, String template, ProducerTypeEnum type )
381             throws Exception
382     {
383         Reader fileIn = getResourceReader( template );
384 
385         Writer writer = getResourceWriter( schema.getUnqualifiedClassName( type ) );
386 
387         Velocity.evaluate( context, writer, "LOG", fileIn );
388 
389         writer.flush();
390 
391         writer.close();
392     }
393 
394 
395     protected Reader getResourceReader( String res ) throws IOException
396     {
397         return new InputStreamReader( getClass().getResourceAsStream( res ) );
398     }
399 
400 
401     protected boolean mkdirs( String base, String path )
402     {
403         String[] comps = path.split( "/" );
404 
405         File file = new File( base );
406 
407         if ( ! file.exists() )
408         {
409             file.mkdirs();
410         }
411 
412         for ( int ii = 0; ii < comps.length; ii++ )
413         {
414             file = new File( file, comps[ii] );
415 
416             if ( ! file.exists() )
417             {
418                 file.mkdirs();
419             }
420         }
421 
422         return file.exists();
423     }
424 
425 
426     protected FileWriter getResourceWriter( String classname ) throws IOException
427     {
428         String pkg = schema.getPackageName();
429 
430         mkdirs( schemaTargetDir, pkg.replace( '.', File.separatorChar ) );
431 
432         File base = new File( schemaTargetDir );
433 
434         String relativePath = pkg.replace( '.', File.separatorChar );
435 
436         File dir = new File( base, relativePath );
437 
438         return new FileWriter( new File( dir, classname + ".java" ) );
439     }
440 
441 
442 
443     protected boolean exists( ProducerTypeEnum type )
444     {
445         String defaultClass = schema.getFullDefaultBaseClassName( type );
446 
447         // check to see if any of the classes are available in the java 
448         // source directory, if so we return true
449         File defaultFile = new File( getJavaSrcDir() + File.separator + getFilePath( defaultClass ) );
450           
451         return defaultFile.exists();
452     }
453 
454 
455     private String getFilePath( String fqcn )
456     {
457         String path = fqcn.replace( '.', File.separatorChar );
458 
459         path += ".java";
460 
461         return path;
462     }
463 }