Home | History | Annotate | Download | only in reflect
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 
     16 package javassist.tools.reflect;
     17 
     18 import javassist.CtClass;
     19 import javassist.ClassPool;
     20 import java.io.PrintStream;
     21 
     22 class CompiledClass {
     23     public String classname;
     24     public String metaobject;
     25     public String classobject;
     26 }
     27 
     28 /**
     29  * A bytecode translator for reflection.
     30  *
     31  * <p>This translator directly modifies class files on a local disk so that
     32  * the classes represented by those class files are reflective.
     33  * After the modification, the class files can be run with the standard JVM
     34  * without <code>javassist.tools.reflect.Loader</code>
     35  * or any other user-defined class loader.
     36  *
     37  * <p>The modified class files are given as the command-line parameters,
     38  * which are a sequence of fully-qualified class names followed by options:
     39  *
     40  * <p><code>-m <i>classname</i></code> : specifies the class of the
     41  * metaobjects associated with instances of the class followed by
     42  * this option.  The default is <code>javassit.reflect.Metaobject</code>.
     43  *
     44  * <p><code>-c <i>classname</i></code> : specifies the class of the
     45  * class metaobjects associated with instances of the class followed by
     46  * this option.  The default is <code>javassit.reflect.ClassMetaobject</code>.
     47  *
     48  * <p>If a class name is not followed by any options, the class indicated
     49  * by that class name is not reflective.
     50  *
     51  * <p>For example,
     52  * <ul><pre>% java Compiler Dog -m MetaDog -c CMetaDog Cat -m MetaCat Cow
     53  * </pre></ul>
     54  *
     55  * <p>modifies class files <code>Dog.class</code>, <code>Cat.class</code>,
     56  * and <code>Cow.class</code>.
     57  * The metaobject of a Dog object is a MetaDog object and the class
     58  * metaobject is a CMetaDog object.
     59  * The metaobject of a Cat object is a MetaCat object but
     60  * the class metaobject is a default one.
     61  * Cow objects are not reflective.
     62  *
     63  * <p>Note that if the super class is also made reflective, it must be done
     64  * before the sub class.
     65  *
     66  * @see javassist.tools.reflect.Metaobject
     67  * @see javassist.tools.reflect.ClassMetaobject
     68  * @see javassist.tools.reflect.Reflection
     69  */
     70 public class Compiler {
     71 
     72     public static void main(String[] args) throws Exception {
     73         if (args.length == 0) {
     74             help(System.err);
     75             return;
     76         }
     77 
     78         CompiledClass[] entries = new CompiledClass[args.length];
     79         int n = parse(args, entries);
     80 
     81         if (n < 1) {
     82             System.err.println("bad parameter.");
     83             return;
     84         }
     85 
     86         processClasses(entries, n);
     87     }
     88 
     89     private static void processClasses(CompiledClass[] entries, int n)
     90         throws Exception
     91     {
     92         Reflection implementor = new Reflection();
     93         ClassPool pool = ClassPool.getDefault();
     94         implementor.start(pool);
     95 
     96         for (int i = 0; i < n; ++i) {
     97             CtClass c = pool.get(entries[i].classname);
     98             if (entries[i].metaobject != null
     99                                         || entries[i].classobject != null) {
    100                 String metaobj, classobj;
    101 
    102                 if (entries[i].metaobject == null)
    103                     metaobj = "javassist.tools.reflect.Metaobject";
    104                 else
    105                     metaobj = entries[i].metaobject;
    106 
    107                 if (entries[i].classobject == null)
    108                     classobj = "javassist.tools.reflect.ClassMetaobject";
    109                 else
    110                     classobj = entries[i].classobject;
    111 
    112                 if (!implementor.makeReflective(c, pool.get(metaobj),
    113                                               pool.get(classobj)))
    114                     System.err.println("Warning: " + c.getName()
    115                                 + " is reflective.  It was not changed.");
    116 
    117                 System.err.println(c.getName() + ": " + metaobj + ", "
    118                                    + classobj);
    119             }
    120             else
    121                 System.err.println(c.getName() + ": not reflective");
    122         }
    123 
    124         for (int i = 0; i < n; ++i) {
    125             implementor.onLoad(pool, entries[i].classname);
    126             pool.get(entries[i].classname).writeFile();
    127         }
    128     }
    129 
    130     private static int parse(String[] args, CompiledClass[] result) {
    131         int n = -1;
    132         for (int i = 0; i < args.length; ++i) {
    133             String a = args[i];
    134             if (a.equals("-m"))
    135                 if (n < 0 || i + 1 > args.length)
    136                     return -1;
    137                 else
    138                     result[n].metaobject = args[++i];
    139             else if (a.equals("-c"))
    140                 if (n < 0 || i + 1 > args.length)
    141                     return -1;
    142                 else
    143                     result[n].classobject = args[++i];
    144             else if (a.charAt(0) == '-')
    145                 return -1;
    146             else {
    147                 CompiledClass cc = new CompiledClass();
    148                 cc.classname = a;
    149                 cc.metaobject = null;
    150                 cc.classobject = null;
    151                 result[++n] = cc;
    152             }
    153         }
    154 
    155         return n + 1;
    156     }
    157 
    158     private static void help(PrintStream out) {
    159         out.println("Usage: java javassist.tools.reflect.Compiler");
    160         out.println("            (<class> [-m <metaobject>] [-c <class metaobject>])+");
    161     }
    162 }
    163