src/share/jaxws_classes/com/sun/xml/internal/bind/v2/bytecode/ClassTailor.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.bind.v2.bytecode;
    28 import java.io.ByteArrayOutputStream;
    29 import java.io.DataInputStream;
    30 import java.io.DataOutputStream;
    31 import java.io.IOException;
    32 import java.io.InputStream;
    33 import java.util.logging.Level;
    34 import java.util.logging.Logger;
    36 import com.sun.xml.internal.bind.Util;
    38 /**
    39  * Replaces a few constant pool tokens from a class "template" and then loads it into the VM.
    40  *
    41  * @author Kohsuke Kawaguchi
    42  */
    43 public final class ClassTailor {
    45     private ClassTailor() {} // no instanciation please
    47     private static final Logger logger = Util.getClassLogger();
    49     /**
    50      * Returns the class name in the JVM format (such as "java/lang/String")
    51      */
    52     public static String toVMClassName( Class c ) {
    53         assert !c.isPrimitive();
    54         if(c.isArray())
    55             // I have no idea why it is designed like this, but javap says so.
    56             return toVMTypeName(c);
    57         return c.getName().replace('.','/');
    58     }
    60     public static String toVMTypeName( Class c ) {
    61         if(c.isArray()) {
    62             // TODO: study how an array type is encoded.
    63             return '['+toVMTypeName(c.getComponentType());
    64         }
    65         if(c.isPrimitive()) {
    66             if(c==Boolean.TYPE)     return "Z";
    67             if(c==Character.TYPE)   return "C";
    68             if(c==Byte.TYPE)        return "B";
    69             if(c==Double.TYPE)      return "D";
    70             if(c==Float.TYPE)       return "F";
    71             if(c==Integer.TYPE)     return "I";
    72             if(c==Long.TYPE)        return "J";
    73             if(c==Short.TYPE)       return "S";
    75             throw new IllegalArgumentException(c.getName());
    76         }
    77         return 'L'+c.getName().replace('.','/')+';';
    78     }
    82     public static byte[] tailor( Class templateClass, String newClassName, String... replacements ) {
    83         String vmname = toVMClassName(templateClass);
    84         return tailor(
    85             SecureLoader.getClassClassLoader(templateClass).getResourceAsStream(vmname+".class"),
    86             vmname, newClassName, replacements );
    87     }
    90     /**
    91      * Customizes a class file by replacing constant pools.
    92      *
    93      * @param image
    94      *      The image of the template class.
    95      * @param replacements
    96      *      A list of pair of strings that specify the substitution
    97      *      {@code String[]{search_0, replace_0, search_1, replace_1, ..., search_n, replace_n }}
    98      *
    99      *      The search strings found in the constant pool will be replaced by the corresponding
   100      *      replacement string.
   101      */
   102     public static byte[] tailor( InputStream image, String templateClassName, String newClassName, String... replacements ) {
   103         DataInputStream in = new DataInputStream(image);
   105         try {
   106             ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
   107             DataOutputStream out = new DataOutputStream(baos);
   109             // skip until the constant pool count
   110             long l = in.readLong();
   111             out.writeLong(l);
   113             // read the constant pool size
   114             short count = in.readShort();
   115             out.writeShort(count);
   117             // replace constant pools
   118             for( int i=0; i<count; i++ ) {
   119                 byte tag = in.readByte();
   120                 out.writeByte(tag);
   121                 switch(tag) {
   122                 case 0:
   123                     // this isn't described in the spec,
   124                     // but class files often seem to have this '0' tag.
   125                     // we can apparently just ignore it, but not sure
   126                     // what this really means.
   127                     break;
   129                 case 1: // CONSTANT_UTF8
   130                     {
   131                         String value = in.readUTF();
   132                         if(value.equals(templateClassName))
   133                             value = newClassName;
   134                         else {
   135                             for( int j=0; j<replacements.length; j+=2 )
   136                                 if(value.equals(replacements[j])) {
   137                                     value = replacements[j+1];
   138                                     break;
   139                                 }
   140                         }
   141                         out.writeUTF(value);
   142                     }
   143                 break;
   145                 case 3: // CONSTANT_Integer
   146                 case 4: // CONSTANT_Float
   147                     out.writeInt(in.readInt());
   148                     break;
   150                 case 5: // CONSTANT_Long
   151                 case 6: // CONSTANT_Double
   152                     i++; // doubles and longs take two entries
   153                     out.writeLong(in.readLong());
   154                     break;
   156                 case 7: // CONSTANT_Class
   157                 case 8: // CONSTANT_String
   158                     out.writeShort(in.readShort());
   159                     break;
   161                 case 9: // CONSTANT_Fieldref
   162                 case 10: // CONSTANT_Methodref
   163                 case 11: // CONSTANT_InterfaceMethodref
   164                 case 12: // CONSTANT_NameAndType
   165                     out.writeInt(in.readInt());
   166                     break;
   168                 default:
   169                     throw new IllegalArgumentException("Unknown constant type "+tag);
   170                 }
   171             }
   173             // then copy the rest
   174             byte[] buf = new byte[512];
   175             int len;
   176             while((len=in.read(buf))>0)
   177                 out.write(buf,0,len);
   179             in.close();
   180             out.close();
   182             // by now we got the properly tailored class file image
   183             return baos.toByteArray();
   185         } catch( IOException e ) {
   186             // never happen
   187             logger.log(Level.WARNING,"failed to tailor",e);
   188             return null;
   189         }
   190     }
   191 }

mercurial