169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.tools.reflect;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.PrintStream;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalclass CompiledClass {
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String classname;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String metaobject;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String classobject;
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A bytecode translator for reflection.
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This translator directly modifies class files on a local disk so that
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the classes represented by those class files are reflective.
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * After the modification, the class files can be run with the standard JVM
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * without <code>javassist.tools.reflect.Loader</code>
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or any other user-defined class loader.
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>The modified class files are given as the command-line parameters,
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * which are a sequence of fully-qualified class names followed by options:
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>-m <i>classname</i></code> : specifies the class of the
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * metaobjects associated with instances of the class followed by
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * this option.  The default is <code>javassit.reflect.Metaobject</code>.
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>-c <i>classname</i></code> : specifies the class of the
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * class metaobjects associated with instances of the class followed by
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * this option.  The default is <code>javassit.reflect.ClassMetaobject</code>.
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If a class name is not followed by any options, the class indicated
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by that class name is not reflective.
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>For example,
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>% java Compiler Dog -m MetaDog -c CMetaDog Cat -m MetaCat Cow
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul>
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>modifies class files <code>Dog.class</code>, <code>Cat.class</code>,
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and <code>Cow.class</code>.
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The metaobject of a Dog object is a MetaDog object and the class
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * metaobject is a CMetaDog object.
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The metaobject of a Cat object is a MetaCat object but
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the class metaobject is a default one.
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Cow objects are not reflective.
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Note that if the super class is also made reflective, it must be done
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * before the sub class.
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Metaobject
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.ClassMetaobject
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.reflect.Reflection
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Compiler {
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static void main(String[] args) throws Exception {
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (args.length == 0) {
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            help(System.err);
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CompiledClass[] entries = new CompiledClass[args.length];
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = parse(args, entries);
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (n < 1) {
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            System.err.println("bad parameter.");
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        processClasses(entries, n);
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void processClasses(CompiledClass[] entries, int n)
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws Exception
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Reflection implementor = new Reflection();
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassPool pool = ClassPool.getDefault();
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        implementor.start(pool);
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass c = pool.get(entries[i].classname);
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (entries[i].metaobject != null
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        || entries[i].classobject != null) {
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String metaobj, classobj;
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (entries[i].metaobject == null)
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    metaobj = "javassist.tools.reflect.Metaobject";
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    metaobj = entries[i].metaobject;
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (entries[i].classobject == null)
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    classobj = "javassist.tools.reflect.ClassMetaobject";
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    classobj = entries[i].classobject;
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (!implementor.makeReflective(c, pool.get(metaobj),
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                              pool.get(classobj)))
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    System.err.println("Warning: " + c.getName()
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                + " is reflective.  It was not changed.");
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                System.err.println(c.getName() + ": " + metaobj + ", "
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                   + classobj);
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                System.err.println(c.getName() + ": not reflective");
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            implementor.onLoad(pool, entries[i].classname);
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            pool.get(entries[i].classname).writeFile();
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static int parse(String[] args, CompiledClass[] result) {
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = -1;
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < args.length; ++i) {
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String a = args[i];
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (a.equals("-m"))
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (n < 0 || i + 1 > args.length)
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return -1;
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    result[n].metaobject = args[++i];
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (a.equals("-c"))
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (n < 0 || i + 1 > args.length)
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return -1;
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    result[n].classobject = args[++i];
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (a.charAt(0) == '-')
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return -1;
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CompiledClass cc = new CompiledClass();
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cc.classname = a;
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cc.metaobject = null;
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cc.classobject = null;
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                result[++n] = cc;
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return n + 1;
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void help(PrintStream out) {
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println("Usage: java javassist.tools.reflect.Compiler");
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println("            (<class> [-m <metaobject>] [-c <class metaobject>])+");
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
163