View Javadoc

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