View Javadoc

1   /*
2    * Copyright 2005 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  
18  package org.apache.jdo.impl.enhancer.meta.prop;
19  
20  import java.io.IOException;
21  import java.io.PrintWriter;
22  import java.io.InputStream;
23  import java.io.FileInputStream;
24  
25  import java.util.Iterator;
26  import java.util.Properties;
27  
28  import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataFatalError;
29  import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataUserException;
30  import org.apache.jdo.impl.enhancer.meta.ExtendedMetaData;
31  import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataBaseModel;
32  
33  
34  
35  
36  /***
37   * Provides the JDO meta information based on properties.
38   */
39  public class EnhancerMetaDataPropertyImpl
40      extends EnhancerMetaDataBaseModel
41      implements ExtendedMetaData
42  {
43      /***
44       * The model instance.
45       */
46      final private MetaDataProperties model;
47      
48      /***
49       * Creates an instance.
50       */
51      public EnhancerMetaDataPropertyImpl(PrintWriter out,
52                                          boolean verbose,
53                                          Properties properties)
54         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
55      {
56          super(out, verbose);
57          affirm(properties != null);
58          model = new MetaDataProperties(properties);
59          initModel();
60          affirm(model != null);
61          printMessage(getI18N("enhancer.metadata.using_properties",
62                               "<unnamed>"));
63      }
64  
65      /***
66       *  Creates an instance.
67       */
68      public EnhancerMetaDataPropertyImpl(PrintWriter out,
69                                          boolean verbose,
70                                          String fileName)
71         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
72      {
73          super(out, verbose);
74          affirm(fileName != null);
75  
76          InputStream stream = null;
77          try {
78              stream = new FileInputStream(fileName);
79              final Properties properties = new Properties();
80              properties.load(stream);
81              model = new MetaDataProperties(properties);
82              initModel();
83          } catch (IOException ex) {
84              final String msg
85                  = getI18N("enhancer.metadata.io_error", ex.getMessage());
86              throw new EnhancerMetaDataFatalError(msg, ex);
87          } finally {
88              if (stream != null) {
89                  try {
90                      stream.close();
91                  } catch (IOException ex) {
92                      final String msg
93                          = getI18N("enhancer.metadata.io_error",
94                                    ex.getMessage());
95                      throw new EnhancerMetaDataFatalError(msg, ex);
96                  }
97              }
98          }
99          affirm(model != null);
100         printMessage(getI18N("enhancer.metadata.using_properties", fileName));
101     }
102 
103     // ----------------------------------------------------------------------
104     
105     /***
106      * Initializes the model.
107      */
108     private void initModel()
109     {
110         // we'd like to have all classes (and fields) parsed and
111         // cached in order to early report errors with the properties
112         final String[] classNames = model.getKnownClassNames();
113         affirm(classNames != null);
114         for (int i = classNames.length - 1; i >= 0; i--) {
115             final JDOClass clazz = getJDOClass(classNames[i]);
116             affirm(clazz != null);
117         }
118     }
119 
120     /*** 
121      * Returns the JVM-qualified name of the specified field's declaring
122      * class. The method first checks whether the class of the specified
123      * classPath (the JVM-qualified name) declares such a field. If yes,
124      * classPath is returned. Otherwise, it checks its superclasses. The
125      * method returns <code>null</code> for an unkown field.
126      * @param classPath the non-null JVM-qualified name of the class
127      * @param fieldName the non-null name of the field
128      * @return the JVM-qualified name of the declararing class of the
129      * field, or <code>null</code> if there is no such field.
130      */
131     public String getDeclaringClass(String classPath, String fieldName)
132         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
133     {
134         String declaringClass = null;
135         JDOField field = getJDOField(classPath, fieldName);
136         if (field != null) {
137             // this class declares the filed => return classPath
138             declaringClass = classPath;
139         } else {
140             String superclass = getSuperClass(classPath);
141             if (superclass != null) {
142                 declaringClass = getDeclaringClass(superclass, fieldName);
143             }
144         }
145         return declaringClass;
146     }
147 
148     /***
149      * Declares a field to the JDO model passing its type information.
150      */
151     public void declareField(String classPath,
152                              String fieldName,
153                              String signature)
154         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
155     {
156         affirm(isPersistenceCapableClass(classPath));
157         // nothing to be done: the properties-based model doesn't
158         // support default calculation of persistence modifiers
159     }
160     
161     /***
162      * Returns whether a class is known to be persistence-capable.
163      */
164     public boolean isPersistenceCapableClass(String classPath)
165         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
166     {
167         final JDOClass clazz = getJDOClass(classPath);
168         return (clazz != null ? clazz.isPersistent() : false);
169     }
170 
171     /***
172      * Returns whether a class implements java.io.Serializable.
173      * @param classPath the non-null JVM-qualified name of the class
174      * @return true if this class is serializable; otherwise false
175      */
176     public boolean isSerializableClass(String classPath)
177         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
178     {
179         final JDOClass clazz = getJDOClass(classPath);
180         return (clazz != null ? clazz.isSerializable() : false);
181     }
182     
183     /***
184      * Returns the name of the persistence-capable root class of a class.
185      */
186 //@olsen: use the inherited method
187 /*
188     public String getPersistenceCapableRootClass(String classPath)
189         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
190     {
191         String pcRootClass = null;
192         for (String clazz = classPath;
193              clazz != null;
194              clazz = getSuperClass(clazz))  {
195             if (isPersistenceCapableClass(clazz)) {
196                 pcRootClass = clazz;
197             }
198         }
199         return pcRootClass;
200     }
201 */
202 
203     /***
204      * Returns the name of the persistence-capable superclass of a class.
205      */
206     public String getPersistenceCapableSuperClass(String classPath)
207         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
208     {
209         for (String clazz = getSuperClass(classPath);
210              clazz != null;
211              clazz = getSuperClass(clazz))  {
212             if (isPersistenceCapableClass(clazz)) {
213                 return clazz;
214             }
215         }
216         return null;
217     }
218 
219     /***
220      *  Returns the superclass of a class.
221      */
222     public final String getSuperClass(String classname)
223     {
224         final JDOClass clazz = getJDOClass(classname);
225         return (clazz != null ? clazz.getSuperClassName() : null);
226     }
227 
228     /***
229      * Returns the name of the key class of a persistence-capable class.
230      */
231     public String getKeyClass(String classPath)
232         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
233     {
234         final JDOClass clazz = getJDOClass(classPath);
235         return (clazz != null ? clazz.getOidClassName() : null);
236     }
237 
238     /***
239      * Returns whether a field of a class is known to be non-managed.
240      */
241     public boolean isKnownNonManagedField(String classPath,
242                                           String fieldName,
243                                           String fieldSig)
244     {
245         final JDOClass clazz = getJDOClass(classPath);
246         if (clazz == null) {
247             return true;
248         }
249         final JDOField field = getJDOField(clazz, fieldName);
250         return (field != null ? field.isKnownTransient() : false);
251     }    
252 
253     /***
254      * Returns whether a field of a class is transient transactional
255      * or persistent.
256      */
257     public boolean isManagedField(String classPath, String fieldName)
258     {
259         final JDOField field = getJDOField(classPath, fieldName);
260         return (field != null
261                 ? (field.isPersistent() | field.isTransactional()) : false);
262     }
263 
264     /***
265      * Returns whether a field of a class is known to be persistent.
266      */
267     public boolean isPersistentField(String classPath, String fieldName)
268         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
269     {
270         final JDOField field = getJDOField(classPath, fieldName);
271         return (field != null ? field.isPersistent() : false);
272     }
273 
274     /***
275      * Returns whether a field of a class is known to be transactional.
276      */
277     public boolean isTransactionalField(String classPath, String fieldName)
278         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
279     {
280         final JDOField field = getJDOField(classPath, fieldName);
281         return (field != null ? field.isTransactional() : false);
282     }
283 
284     /***
285      * Returns whether a field of a class is known to be Primary Key.
286      */
287     public boolean isKeyField(String classPath, String fieldName)
288         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
289     {
290         final JDOField field = getJDOField(classPath, fieldName);
291         return (field != null ? field.isKey() : false);
292     }
293 
294     /***
295      * Returns whether a field of a class is known to be part of the
296      * Default Fetch Group.
297      */
298     public boolean isDefaultFetchGroupField(String classPath, String fieldName)
299         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
300     {
301         final JDOField field = getJDOField(classPath, fieldName);
302         return (field != null ? field.isInDefaultFetchGroup() : false);
303     }
304 
305     /***
306      * Returns the unique field index of a declared, persistent field of a
307      * class.
308      */
309     public int getFieldNumber(String classPath, String fieldName)
310         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
311     {
312         final JDOClass clazz = getJDOClass(classPath);
313         return (clazz != null ? clazz.getIndexOfField(fieldName) : -1);
314     }
315 
316     /***
317      * Returns an array of field names of all declared, persistent fields
318      * of a class.
319      */
320     public String[] getManagedFields(String classname)
321     {
322         final JDOClass clazz = getJDOClass(classname);
323         return (clazz != null ? clazz.getManagedFieldNames() : new String[]{});
324     }
325 
326     /***
327      *  Not member of EnhancerMetaData Interface.
328      */
329     public final String[] getKnownClasses()
330     {
331         return model.getKnownClassNames();
332     }
333 
334     /***
335      *  Gets all known fields of a class.
336      */
337     public final String[] getKnownFields(String classname)
338     {
339         final JDOClass clazz = getJDOClass(classname);
340         return (clazz != null ? clazz.getFieldNames() : new String[]{});
341     }
342 
343 
344     /***
345      *  Gets the access modifier of a class.
346      */
347     public final int getClassModifiers(String classname)
348     {
349         final JDOClass clazz = getJDOClass(classname);
350         return (clazz != null ? clazz.getModifiers() : 0);
351     }
352 
353     /***
354      *  Gets the access modifier of a field.
355      */
356     public final int getFieldModifiers(String classname,
357                                        String fieldname)
358     {
359         final JDOField field = getJDOField(classname, fieldname);
360         return (field != null ? field.getModifiers() : 0);
361     }
362 
363     public final String getFieldType(String classname,
364                                      String fieldname)
365     {
366         final JDOField field = getJDOField(classname, fieldname);
367         return (field != null ? field.getType() : null);
368     }
369 
370     public final String[] getFieldType(String classname,
371                                         String[] fieldnames)
372     {
373         final int n = (fieldnames != null ? fieldnames.length : 0);
374         final String[] types = new String[n];
375         for (int i = 0; i < n; i++) {
376             types[i] = getFieldType(classname, fieldnames[i]);
377         }
378         return types;
379     }
380 
381     public final int[] getFieldModifiers(String classname,
382                                           String[] fieldnames)
383         throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
384     {
385         final int n = (fieldnames != null ? fieldnames.length : 0);
386         final int[] mods = new int[n];
387         for (int i = 0; i < n; i++) {
388             mods[i] = getFieldModifiers(classname, fieldnames[i]);
389         }
390         return mods;
391     }
392 
393     private final JDOClass getJDOClass(String classname)
394         throws EnhancerMetaDataUserException
395     {
396         return model.getJDOClass(classname);
397     }
398 
399     private final JDOField getJDOField(JDOClass clazz,
400                                        String fieldname)
401     {
402         return (clazz != null ? clazz.getField(fieldname) : null);
403     }
404 
405     private final JDOField getJDOField(String classname,
406                                        String fieldname)
407     {
408         final JDOClass clazz = getJDOClass(classname);
409         return getJDOField(clazz, fieldname);
410     }
411 
412     // ----------------------------------------------------------------------
413     
414     public static void main(String[] argv)
415     {
416         final PrintWriter out = new PrintWriter(System.out, true);
417         
418         if (argv.length != 1) {
419             System.err.println("No property file specified.");
420             return;
421         }
422 
423         final Properties p = new Properties();
424         try {
425             java.io.InputStream in =
426                 new java.io.FileInputStream(new java.io.File(argv[0]));
427             p.load(in);
428             in.close();
429             out.println("PROPERTIES: " + p);
430             out.println("############");
431             MetaDataProperties props = new MetaDataProperties(p);
432         } catch (Throwable ex) {
433             ex.printStackTrace(System.err);
434         }
435 
436         final EnhancerMetaDataPropertyImpl jdo
437             = new EnhancerMetaDataPropertyImpl(out, true, p);
438         final String[] classes = jdo.getKnownClasses();
439         for (int k = 0; k < classes.length; k++) {
440             final String clazz = classes[k];
441             out.println("CLAZZ: " + clazz);
442             out.println("\tpersistent: "
443                         + jdo.isPersistenceCapableClass(clazz));
444             out.println("\tpersistent root: "
445                         + jdo.isPersistenceCapableRootClass(clazz));
446             out.println("\tpersistent root class: "
447                         + jdo.getPersistenceCapableRootClass(clazz));
448             out.println("\tpersistent super class: "
449                         + jdo.getPersistenceCapableSuperClass(clazz));
450             out.println("\tkey class: "
451                         + jdo.getKeyClass(clazz));
452 
453             final String[] fields = jdo.getKnownFields(clazz);
454             for (int j = 0; j < fields.length; j++) {
455                 final String field = fields[j];
456                 out.println("FIELD: " + field);
457                 out.println("\tpersistent field: "
458                             + jdo.isPersistentField(clazz, field));
459                 out.println("\tpk field: "
460                             + jdo.isKeyField(clazz, field));
461                 out.println("\tdfg field: "
462                             + jdo.isDefaultFetchGroupField(clazz, field));
463                 out.println("\tnumber: "
464                             + jdo.getFieldNumber(clazz, field));
465 
466                 final String[] names = jdo.getManagedFields(clazz);
467                 final int n = (fields != null ? names.length : 0);
468                 out.println("managed fields: number: " + n);
469                 for (int i = 0; i < n; i++) {
470                     final String name = names[i];
471                     out.println(i + ": " + name +
472                                 " number: "
473                                 + jdo.getFieldNumber(clazz, name) +
474                                 " pk: "
475                                 + jdo.isKeyField(clazz, name) +
476                                 " dfg: "
477                                 + jdo.isDefaultFetchGroupField(clazz, name));
478                 }
479             }
480         }
481     }
482 }