Package com.ovea.jetty.session.serializer.jboss.serial.classmetamodel

Source Code of com.ovea.jetty.session.serializer.jboss.serial.classmetamodel.ClassMetamodelFactory$CacheLoaderReference

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package com.ovea.jetty.session.serializer.jboss.serial.classmetamodel;

import com.ovea.jetty.session.serializer.jboss.serial.util.ClassMetaConsts;
import com.ovea.jetty.session.serializer.jboss.serial.util.FastHashMap;
import com.ovea.jetty.session.serializer.jboss.serial.util.PartitionedWeakHashMap;

import java.io.*;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* $Id: ClassMetamodelFactory.java 326 2006-07-28 04:57:13Z csuconic $
*
* @author clebert suconic
*/
public class ClassMetamodelFactory implements ClassMetaConsts {
    /**
     * table mapping primitive type names to corresponding class objects.
     * This code was created by Carlos de Wolf on a fix of EJBTHREE-440.
     * By coincidence I needed to parse primitive values, and instead of reinventing the wheel I got the same code.
     */
    private static final HashMap primClasses = new HashMap(8, 1.0F);

    static {
        primClasses.put("boolean", boolean.class);
        primClasses.put("byte", byte.class);
        primClasses.put("char", char.class);
        primClasses.put("short", short.class);
        primClasses.put("int", int.class);
        primClasses.put("long", long.class);
        primClasses.put("float", float.class);
        primClasses.put("double", double.class);
        primClasses.put("void", void.class);
        primClasses.put("[Z", boolean[].class);
        primClasses.put("[B", byte[].class);
        primClasses.put("[C", char[].class);
        primClasses.put("[S", short[].class);
        primClasses.put("[I", int[].class);
        primClasses.put("[J", long[].class);
        primClasses.put("[F", float[].class);
        primClasses.put("[D", double[].class);
    }

    /**
     * We are caching the getClassLoader operation, to avoid locks on the WeakHashMap
     */
    private static class CacheLoaderReference {
        WeakReference currentClassLoader;
        Map currentHashMap;

        public ClassLoader getCurrentClassLoader() {
            if (currentClassLoader == null)
                return null;
            else
                return (ClassLoader) currentClassLoader.get();
        }

        public void setCurrentClassLoader(ClassLoader loader) {
            currentClassLoader = new WeakReference(loader);
        }

        public Map getCurrentMap() {
            return currentHashMap;
        }

        public void setCurrentMap(Map currentMap) {
            this.currentHashMap = currentMap;
        }
    }


    /**
     * Method for ObjectStreamClass.lookup
     */
    static Method methodLookup;

    /**
     * Method for ObjectStreamClass.getField
     */
    static Method methodGetField;


    /**
     * The HashMap for SystemclassLoader
     */
    private static Map systemClassLoaderMap = new FastHashMap();

    private static ObjectStreamClass lookup(Class clazz) throws IllegalAccessException, InvocationTargetException {
        return (ObjectStreamClass) methodLookup.invoke(null, new Object[]{clazz, Boolean.TRUE});
    }

    private static Field getField(Object source) throws IllegalAccessException, InvocationTargetException {
        return (Field) methodGetField.invoke(source, EMPTY_OBJECT_ARRAY);
    }

    static ThreadLocal cacheLoader = new ThreadLocal();

    static {
        try {
            methodLookup = ObjectStreamClass.class.getDeclaredMethod("lookup", new Class[]{Class.class, Boolean.TYPE});
            methodLookup.setAccessible(true);
        } catch (Throwable e) {
            e.printStackTrace();
        }

        try {
            methodGetField = ObjectStreamField.class.getDeclaredMethod("getField", new Class[]{});
            methodGetField.setAccessible(true);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }


    public static void clear(boolean elimiteClassLoadersCached) {
        Iterator iter = cache.values().iterator();
        while (iter.hasNext()) {
            Map map = (Map) iter.next();
            map.clear();
        }
        if (elimiteClassLoadersCached) cache.clear();
        systemClassLoaderMap.clear();
    }

    public static void clear() {
        clear(true);
    }

    public static Map getCache() {
        return cache;
    }

    /**
     * PartitionedWeakHashMap<ClassLoader,ConcurrentHashMap<String,ClassMetaData>>
     * (The current implementation is using FastHashMap instead of ConcurrentHashMap)
     * *
     */
    static PartitionedWeakHashMap cache = new PartitionedWeakHashMap();

    static ClassMetaData proxyMetaData = null;

    static {
        try {
            proxyMetaData = getClassMetaData("java.lang.reflect.Proxy", Thread.currentThread().getContextClassLoader(), true);
            proxyMetaData.setProxy(true);
        } catch (Exception e) {
            e.printStackTrace();
            ;
        }
    }

    private static Map getLoaderMap(ClassLoader loader) {
        if (loader == null) {
            return systemClassLoaderMap;
        }

        CacheLoaderReference loaderReference = (CacheLoaderReference) cacheLoader.get();
        if (loaderReference == null) {
            loaderReference = new CacheLoaderReference();
            cacheLoader.set(loaderReference);
        }

        if (loaderReference.getCurrentClassLoader() == loader) {
            return loaderReference.getCurrentMap();
        }


        Map hashMap = (Map) cache.get(loader);

        ClassLoader returnLoader = null;
        if (hashMap == null) {
            hashMap = new FastHashMap();
            cache.put(loader, hashMap);
            hashMap = (Map) cache.get(loader);
        }

        loaderReference.setCurrentClassLoader(loader);
        loaderReference.setCurrentMap(hashMap);
        return hashMap;
    }

    private static ClassMetaData getClassMetaData(String clazzName, ClassLoader loader, boolean checkSerializable) throws IOException {
        return getClassMetaData(clazzName, null, loader, checkSerializable);
    }


    private static Class resolveClassByName(String clazzName, ClassResolver resolver, ClassLoader loader) throws ClassNotFoundException {
        Class clazz = (Class) primClasses.get(clazzName);

        if (clazz == null) {
            if (resolver != null) {
                clazz = resolver.resolveClass(clazzName);
                if (clazz == null) {
                    clazz = Class.forName(clazzName, false, loader);
                }
            } else {
                clazz = Class.forName(clazzName, false, loader);
            }
        }
        return clazz;
    }

    public static ClassMetaData getClassMetaData(String clazzName, ClassResolver resolver, ClassLoader loader, boolean checkSerializable) throws IOException {
        try {
            Map loaderMap = getLoaderMap(loader);
            ClassMetaData classMetadata = (ClassMetaData) loaderMap.get(clazzName);
            if (classMetadata == null) {

                Class clazz = resolveClassByName(clazzName, resolver, loader);

                if (checkSerializable && !Serializable.class.isAssignableFrom(clazz)) {
                    throw new NotSerializableException(clazz.getName());
                }
                classMetadata = new ClassMetaData(clazz);

                loaderMap = getLoaderMap(loader);
                loaderMap.put(clazzName, classMetadata);
                classMetadata = (ClassMetaData) loaderMap.get(clazzName);
            }

            if (classMetadata.getClazz() == null) {
                // this never happens, so, this is just in case
                // The only possibility for that would be crossed classLoader operations.
                // I tried to replicate this scenario on a testcase and it was not possible.
                // So, I decided to have this verification here to be safe
                Class clazz = resolveClassByName(clazzName, resolver, loader);
                loaderMap.remove(clazzName);
                classMetadata = new ClassMetaData(clazz);
                loaderMap.put(clazz.getName(), classMetadata);
                classMetadata = (ClassMetaData) loaderMap.get(clazzName);
            }


            // It looks dummy but doing Class.isProxy is a very expensive operation, so we just do it on a cached basis
            if (classMetadata.isProxy()) {
                return proxyMetaData;
            } else {
                return classMetadata;
            }
        } catch (ClassNotFoundException e) {

            IOException ex = new IOException(e.getMessage());
            ex.initCause(e);
            throw ex;
        }

    }


    public static ClassMetaData getClassMetaData(Class clazz, boolean checkSerializable) throws IOException {
        if (checkSerializable && !Serializable.class.isAssignableFrom(clazz) && !clazz.isPrimitive()) {
            throw new NotSerializableException(clazz.getName());
        }
        Map loaderMap = getLoaderMap(clazz.getClassLoader());
        ClassMetaData classMetadata = (ClassMetaData) loaderMap.get(clazz.getName());
        if (classMetadata == null) {
            classMetadata = new ClassMetaData(clazz);
            loaderMap.put(clazz.getName(), classMetadata);
            classMetadata = (ClassMetaData) loaderMap.get(clazz.getName());
        }
        if (classMetadata.getClazz() == null) {
            // this never happens, so, this is just in case
            // The only possibility for that would be crossed classLoader operations.
            // I tried to replicate this scenario on a testcase and it was not possible.
            // So, I decided to have this verification here to be safe
            loaderMap.remove(clazz.getName());
            classMetadata = new ClassMetaData(clazz);
            loaderMap.put(clazz.getName(), classMetadata);
            classMetadata = (ClassMetaData) loaderMap.get(clazz.getName());
        }

        // It looks dummy but doing Class.isProxy is a very expensive operation, so we just do it on a cached basis
        if (classMetadata.isProxy()) {
            return proxyMetaData;
        } else {
            return classMetadata;
        }
    }


    public static boolean isImmutable(Class clazz) {
        return (clazz == Character.class || clazz == String.class ||
                clazz == Long.class ||
                clazz == Byte.class ||
                clazz == Double.class ||
                clazz == Float.class ||
                clazz == Integer.class ||
                clazz == Short.class ||
                clazz == Boolean.class ||
                clazz.isPrimitive());
    }

}
TOP

Related Classes of com.ovea.jetty.session.serializer.jboss.serial.classmetamodel.ClassMetamodelFactory$CacheLoaderReference

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.