📄 boundclass.java
字号:
/* * Copyright (c) 2003-2005, Dennis M. Sosnoski All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. Redistributions in binary * form must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials provided * with the distribution. Neither the name of JiBX nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */package org.jibx.binding.classes;import java.io.File;import java.util.HashMap;import org.apache.bcel.Constants;import org.apache.bcel.classfile.Utility;import org.apache.bcel.generic.Type;import org.jibx.binding.def.BindingDefinition;import org.jibx.runtime.JiBXException;/** * Bound class handler. Each instance controls and organizes information for a * class included in one or more binding definitions. * * @author Dennis M. Sosnoski * @version 1.0 */public class BoundClass{ // // Constants and such related to code generation. /** Class used for code munging when no specific class available. */ private static final String GENERIC_MUNGE_CLASS = BindingDefinition.GENERATE_PREFIX + "MungeAdapter"; /** Prefix used for access methods. */ private static final String ACCESS_PREFIX = BindingDefinition.GENERATE_PREFIX + "access_"; /** Empty argument type array. */ private static final Type[] EMPTY_TYPE_ARGS = {}; // // Static data. /** * Map from bound class name (or bound and munged combination) to binding * information. */ private static HashMap s_nameMap; /** Package of first modifiable class. */ private static String s_modifyPackage; /** Root for package of first modifiable class. */ private static File s_modifyRoot; /** Class used for code generation proxy with unmodifiable classes. */ private static MungedClass s_genericMunge; // // Actual instance data. /** Bound class file information. */ private final ClassFile m_boundClass; /** Class receiving code generated for target class. */ private final MungedClass m_mungedClass; /** * Map from field or method to load access method (lazy create, * <code>null</code> if not used). */ private HashMap m_loadMap; /** * Map from field or method to store access method (lazy create, * <code>null</code> if not used). */ private HashMap m_storeMap; /** * Constructor. * * @param bound target class file information * @param munge class file for class hosting generated code */ private BoundClass(ClassFile bound, MungedClass munge) { m_boundClass = bound; m_mungedClass = munge; } /** * Get bound class file information. * * @return class file information for bound class */ public ClassFile getClassFile() { return m_boundClass; } /** * Get bound class file name. * * @return name of bound class */ public String getClassName() { return m_boundClass.getName(); } /** * Get munged class file information. * * @return class file information for class being modified */ public ClassFile getMungedFile() { return m_mungedClass.getClassFile(); } /** * Check if class being changed directly. * * @return <code>true</code> if bound class is being modified, * <code>false</code> if using a surrogate */ public boolean isDirectAccess() { return m_boundClass == m_mungedClass.getClassFile(); } /** * Get load access method for member of this class. If the access method * does not already exist it's created by this call. If the access method * does exist but without access from the context class, the access * permission on the method is broadened (from package to protected or * public, or from protected to public). * * @param item field or method to be accessed * @param from context class from which access is required * @return the item itself if it's accessible from the required context, an * access method that is accessible if the item is not itself * @throws JiBXException on configuration error */ public ClassItem getLoadMethod(ClassItem item, ClassFile from) throws JiBXException { // initialize tracking information for access methods if first time if (m_loadMap == null) { m_loadMap = new HashMap(); } // check if a new access method needed BindingMethod method = (BindingMethod)m_loadMap.get(item); if (method == null) { // set up for constructing new method String name = ACCESS_PREFIX + "load_" + item.getName(); ClassFile cf = item.getClassFile(); Type type = Type.getType(Utility.getSignature(item.getTypeName())); MethodBuilder mb = new ExceptionMethodBuilder(name, type, EMPTY_TYPE_ARGS, cf, (short)0); // add the actual access method code mb.appendLoadLocal(0); if (item.isMethod()) { mb.addMethodExceptions(item); mb.appendCall(item); } else { mb.appendGetField(item); } mb.appendReturn(type); // track unique instance of this method method = m_mungedClass.getUniqueMethod(mb, true); m_loadMap.put(item, method); } // make sure method is accessible method.makeAccessible(from); return method.getItem(); } /** * Get store access method for member of this class. If the access method * does not already exist it's created by this call. If the access method * does exist but without access from the context class, the access * permission on the method is broadened (from package to protected or * public, or from protected to public). * * @param item field or method to be accessed * @param from context class from which access is required * @return the item itself if it's accessible from the required context, an * access method that is accessible if the item is not itself * @throws JiBXException on configuration error */ public ClassItem getStoreMethod(ClassItem item, ClassFile from) throws JiBXException { // initialize tracking information for access methods if first time if (m_storeMap == null) { m_storeMap = new HashMap(); } // check if a new access method needed BindingMethod method = (BindingMethod)m_storeMap.get(item); if (method == null) { // set up for constructing new method String name = ACCESS_PREFIX + "store_" + item.getName(); ClassFile cf = item.getClassFile(); Type type; if (item.isMethod()) { String sig = item.getSignature(); int start = sig.indexOf('('); int end = sig.indexOf(')'); type = Type.getType(sig.substring(start + 1, end)); } else { type = Type.getType(Utility.getSignature(item.getTypeName())); } MethodBuilder mb = new ExceptionMethodBuilder(name, Type.VOID, new Type[] { type }, cf, (short)0); // add the actual access method code mb.appendLoadLocal(0); mb.appendLoadLocal(1); if (item.isMethod()) { mb.addMethodExceptions(item); mb.appendCall(item); } else { mb.appendPutField(item);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -