⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 persttranslator.java

📁 这个是perst-269.zip下面的SOURCECODE,和大家分享了。
💻 JAVA
字号:
package org.garret.perst.jassist;

import javassist.*;
import javassist.expr.*;

/**
 * This class is designed to be used with 
 * <A href="http://www.csg.is.titech.ac.jp/~chiba/javassist/">JAssist</A> to provide transparent 
 * persistence  by preprocessing protect class files. This translator automatically
 * made persistent capable all class matching specifying name patterns. With this 
 * translator it is not required for application classes to be derived from Persistent class
 * and provide empty default constructor. 
 * Example of usage:
 * <pre>
 * package com.mycompany.mypackage;
 * import org.garret.perst.jassist.PerstTranslator;
 * import javassist.*;
 * public class MyApp { 
 *     public static void main(String[] args) { 
 *         Translatator trans = new PerstTranslator(new String[]{"com.mycompany.*"});
 *         ClassPool pool = ClassPool.getDefault(trans);
 *         Loader cl = new Loader(pool);
 *         cl.run("Main", args);
 *     }
 * }
 * </pre>
 * In this example all classes from <code>com.mycompany.mypackage</code> except 
 * MyApp will be loaded by JAssist class loader and automatically made persistent capable.
 */
public class PerstTranslator implements Translator { 
    protected boolean isPersistent(String className) { 
        for (int i = 0; i < classNamePatterns.length; i++) { 
            String pattern = classNamePatterns[i];
            if (className.equals(pattern) 
                || (pattern.endsWith("*") 
                    && className.startsWith(pattern.substring(0, pattern.length()-1))
                    && !className.endsWith("LoadFactory")
                    && !className.startsWith("org.garret.perst")))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * Create Perst translator which made all classes persistent capable 
     * (excluding <code>java.*</code> and <code>org.garret.perst.*</code> 
     * packages)
     */
    public PerstTranslator() { 
        this(new String[]{"*"});
    }

    /**
     * Create Perst translator with specified list of class name patterns.
     * Classes which fully qualified name matchs one of the patterns are made persistent capable.
     */
    public PerstTranslator(String[] classNamePatterns) { 
        this.classNamePatterns = classNamePatterns;
    }

    public void start(ClassPool pool) throws NotFoundException { 
        persistent = pool.get("org.garret.perst.Persistent");
        persistentInterface = pool.get("org.garret.perst.IPersistent");
        factory = pool.get("org.garret.perst.impl.LoadFactory");
        object = pool.get("java.lang.Object");
        isRecursive = persistent.getDeclaredMethod("recursiveLoading"); 
        constructorParams = new CtClass[]{pool.get("org.garret.perst.impl.ClassDescriptor")};
        serializable = pool.get("org.garret.perst.impl.FastSerializable");
        pack = serializable.getDeclaredMethod("pack");
        unpack = serializable.getDeclaredMethod("unpack");
        create = factory.getDeclaredMethod("create");
    }

    private boolean addSerializeMethods(CtClass cc, boolean callSuper)
        throws NotFoundException, CannotCompileException
    {        
        CtField[] fields = cc.getDeclaredFields();
        int size = 0;
        StringBuffer sb = new StringBuffer();
        sb.append(callSuper ? "{$2=super.pack($1, $2);$1.extend($2" : "{$1.extend($2");
        for (int i = 0; i < fields.length; i++) { 
            CtField f = fields[i];
            if ((f.getModifiers() & (Modifier.STATIC|Modifier.TRANSIENT)) == 0) { 
                CtClass type = f.getType();
                if (type.isPrimitive()) { 
                    if (type == CtClass.booleanType || type == CtClass.byteType) { 
                        size += 1; 
                    } else if (type == CtClass.charType || type == CtClass.shortType) { 
                        size += 2;
                    } else if (type == CtClass.longType || type == CtClass.doubleType) { 
                        size += 8;
                    } else { 
                        size += 4;
                    }
                } else if (type.getName().equals("java.lang.String")) {
                    sb.append("+org.garret.perst.impl.Bytes#sizeof(");
                    sb.append(f.getName());
                    sb.append(",$3)");
                } else { 
                    return false;
                }
            }
        }
        cc.addInterface(serializable);
        
        CtMethod m = new CtMethod(pack, cc, null);
        sb.append('+');
        sb.append(size);
        sb.append(");");
        for (int i = 0; i < fields.length; i++) { 
            CtField f = fields[i];
            if ((f.getModifiers() & (Modifier.STATIC|Modifier.TRANSIENT)) == 0) { 
                CtClass type = f.getType();
                String name = f.getName();
                if (type == CtClass.booleanType) { 
                    sb.append("$1.arr[$2++]=(byte)(");
                    sb.append(name);
                    sb.append("?1:0);");
                } else if (type == CtClass.charType) { 
                    sb.append("org.garret.perst.impl.Bytes#pack2($1.arr,$2,(short)");
                    sb.append(name);
                    sb.append(");$2+=2;");
                } else if (type == CtClass.byteType) { 
                    sb.append("$1.arr[$2++]=");
                    sb.append(name);
                    sb.append(";");
                } else if (type == CtClass.shortType) { 
                    sb.append("org.garret.perst.impl.Bytes#pack2($1.arr,$2,");
                    sb.append(name);
                    sb.append(");$2+=2;");
                } else if (type == CtClass.intType) { 
                    sb.append("org.garret.perst.impl.Bytes#pack4($1.arr,$2,");
                    sb.append(name);
                    sb.append(");$2+=4;");
                } else if (type == CtClass.longType) { 
                    sb.append("org.garret.perst.impl.Bytes#pack8($1.arr,$2,");
                    sb.append(name);
                    sb.append(");$2+=8;");
                } else if (type == CtClass.doubleType) { 
                    sb.append("org.garret.perst.impl.Bytes#packF8($1.arr,$2,");
                    sb.append(name);
                    sb.append(");$2+=8;");
                } else if (type == CtClass.floatType) { 
                    sb.append("org.garret.perst.impl.Bytes#packF4($1.arr,$2,");
                    sb.append(name);
                    sb.append(");$2+=4;");
               } else { 
                    sb.append("$2=org.garret.perst.impl.Bytes#packStr($1.arr,$2,");
                    sb.append(name);
                    sb.append(",$3);");
                }
            }
        }
        sb.append("return $2;}");
        m.setBody(sb.toString());
        cc.addMethod(m);

        m = new CtMethod(unpack, cc, null);
        sb = new StringBuffer();
        sb.append(callSuper ? "{$2=super.unpack($1, $2);" : "{");
        for (int i = 0; i < fields.length; i++) { 
            CtField f = fields[i];
            if ((f.getModifiers() & (Modifier.STATIC|Modifier.TRANSIENT)) == 0) { 
                CtClass type = f.getType();
                String name = f.getName();
                sb.append(name);
                sb.append('=');
                if (type == CtClass.booleanType) { 
                    sb.append("$1[$2++]!=0;");
                } else if (type == CtClass.charType) { 
                    sb.append("(char)org.garret.perst.impl.Bytes#unpack2($1,$2);$2+=2;");
                } else if (type == CtClass.byteType) { 
                    sb.append("$1[$2++];");
                } else if (type == CtClass.shortType) { 
                    sb.append("org.garret.perst.impl.Bytes#unpack2($1,$2);$2+=2;");
                } else if (type == CtClass.intType) { 
                    sb.append("org.garret.perst.impl.Bytes#unpack4($1,$2);$2+=4;");
                } else if (type == CtClass.longType) { 
                    sb.append("org.garret.perst.impl.Bytes#unpack8($1,$2);$2+=8;");
                } else if (type == CtClass.doubleType) { 
                    sb.append("org.garret.perst.impl.Bytes#unpackF8($1,$2);$2+=8;");
                } else if (type == CtClass.floatType) { 
                    sb.append("org.garret.perst.impl.Bytes#unpackF4($1,$2);$2+=4;");
               } else { 
                    sb.append("org.garret.perst.impl.Bytes#unpackStr($1,$2,$3);$2+=org.garret.perst.impl.Bytes#sizeof($1,$2);");
                }
            }
        }
        sb.append("return $2;}");
        m.setBody(sb.toString());
        cc.addMethod(m);
        return true;
    }

    private void preprocessMethods(CtClass cc, boolean insertLoad, boolean wrapFieldAccess)  throws CannotCompileException 
    {
        CtMethod[] methods = cc.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) { 
            CtMethod m = methods[i];            
            if (wrapFieldAccess) { 
                m.instrument(new ExprEditor() { 
                    public void edit(FieldAccess fa) throws CannotCompileException { 
                        try { 
                            if ((fa.getField().getModifiers() & (Modifier.TRANSIENT|Modifier.STATIC)) == 0
                                && fa.getField().getDeclaringClass().subtypeOf(persistentInterface))
                            {
                                if (fa.isWriter()) { 
                                    fa.replace("{ $0.loadAndModify(); $proceed($$); }");
                                }
                                // isSelfReader is my extension of JAssist, if you 
                                // use original version of JAssist comment the 
                                // branch below or replace "else if" with "else".
                                // In first case Perst will not be able to handle
                                // access to foreign (non-this) fields. You should use
                                // getter/setter methods instead. 
                                // In second case access to foreign fields still will be possible,
                                // but with significant degradation of performance and 
                                // increased code size, because in this case before ALL access
                                // to fields of persistent capable object call of load() method
                                // will be inserted.
                                else if (!fa.isSelfReader()) 
                                { 
                                    fa.replace("{ $0.load(); $_ = $proceed($$); }");
                                }
                            }
                        } catch (NotFoundException x) {}
                    }
                });
            }
            if (insertLoad 
                && !"recursiveLoading".equals(m.getName())
                && (m.getModifiers() & (Modifier.STATIC|Modifier.ABSTRACT)) == 0)  
            { 
                m.insertBefore("load();");
            }
        }
    }


    public void onLoad(ClassPool pool, String className)
        throws NotFoundException, CannotCompileException
    {
        onWrite(pool, className);
    }

    public void onWrite(ClassPool pool, String className)
        throws NotFoundException, CannotCompileException 
    {
        CtClass cc = pool.get(className);
        try {
            if (isPersistent(className)) {                
                CtClass base = cc.getSuperclass();
                CtConstructor cons = new CtConstructor(constructorParams, cc);            
                if (base.subclassOf(persistent) || base == object) { 
                    cons.setBody(null);
                    cc.addConstructor(cons);
                    if (base == object) { 
                        cc.setSuperclass(persistent);                    
                    }
                } else { 
                    if (!isPersistent(base.getName())) { 
                        throw new NotFoundException("Base class " + base.getName()
                                                    + " was not declared as peristent");
                    } 
                    cons.setBody("super($0);");
                    cc.addConstructor(cons);
                }
                preprocessMethods(cc, true, true);
                if (base == persistent || base == object) { 
                    CtMethod m = new CtMethod(isRecursive, cc, null);
                    m.setBody("return false;");
                    cc.addMethod(m);
                    addSerializeMethods(cc, false);
                } else if (base.subtypeOf(serializable)) { 
                    addSerializeMethods(cc, true);
                }
                if ((cc.getModifiers() & Modifier.PRIVATE) == 0) { 
                    CtClass f = pool.makeClass(className + "LoadFactory");
                    f.addInterface(factory);
                    CtMethod c = new CtMethod(create, f, null);
                    c.setBody("return new " + className + "($1);");
                    f.addMethod(c);
                    CtNewConstructor.defaultConstructor(f);
                }
            } else { 
                preprocessMethods(cc, 
                                  cc.subtypeOf(persistent) && cc != persistent, 
                                  !className.startsWith("org.garret.perst")); 
            }
        } catch(Exception x) { x.printStackTrace(); }
    }

    CtClass       persistent;
    CtClass       persistentInterface;
    CtClass       object;
    CtClass       factory;
    CtClass[]     constructorParams;
    CtMethod      create;
    CtMethod      isRecursive;
    String[]      classNamePatterns;
    CtClass       serializable;
    CtMethod      pack;
    CtMethod      unpack;
}
            

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -