All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cesecore.util.JBossUnmarshaller Maven / Gradle / Ivy

/*************************************************************************
 *                                                                       *
 *  CESeCore: CE Security Core                                           *
 *                                                                       *
 *  This software 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 any later version.                    *
 *                                                                       *
 *  See terms of license at gnu.org.                                     *
 *                                                                       *
 *************************************************************************/

package org.cesecore.util;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;

import org.apache.log4j.Logger;
import org.cesecore.config.CesecoreConfiguration;

/**
 * Helper class for extracting objects Serialized on JBoss under J2EE.
 * 
 * Used during upgrade from EJBCA 3.11.x to EJBCA 4.0.y.
 *
 * @version $Id: JBossUnmarshaller.java 23629 2016-06-08 11:53:37Z mikekushner $
 */
public final class JBossUnmarshaller {

    private static final Logger LOG = Logger.getLogger(JBossUnmarshaller.class);
    private static final String JBOSS_MARSHALL_CLASS = "org.jboss.invocation.MarshalledValue";
    private static boolean lookForJbossMarshaller = true;

    private JBossUnmarshaller() {
    }

    /**
     * Helper method for extracting objects Serialized on JBoss under J2EE.
     * 
     * The methods uses the fact that org.jboss.invocation.MarshalledValue is also a Serializable object and extracts the real object from the
     * MarshalledValue if this is passed as a parameter. Otherwise the object is returned in it's current form.
     * 
     * @param 
     *            Class that we are trying to extract.
     * @param t
     *            Class that we are trying to extract.
     * @param object
     *            An object implementing java.lang.Serializable interface
     * @return The unmarshalled or original object of type T or null if object is neither type T or jboss marshalled value
     * @throws ClassCastException if the object is JBOSS marshalled, but not of type t
     */
    @SuppressWarnings("unchecked")
    public static  T extractObject(final Class t, final Serializable object) throws ClassCastException {
        T ret = null;
        final String className = object.getClass().getName();
        if (JBOSS_MARSHALL_CLASS.equals(className)) {
        	try {
        		Method m = object.getClass().getMethod("get", new Class[0]);
        		ret = (T) m.invoke(object, new Object[0]);
        	} catch (SecurityException e) {
        		LOG.error("", e);
        	} catch (NoSuchMethodException e) {
        		LOG.error("", e);
        	} catch (IllegalArgumentException e) {
        		LOG.error("", e);
			} catch (IllegalAccessException e) {
        		LOG.error("", e);
			} catch (InvocationTargetException e) {
        		LOG.error("", e);
			}
        } else {
        	ret = (T) object;
        }
        return ret;
    }

    /**
     * Helper method for extracting hashMaps Serialized on JBoss under J2EE.
     * 
     * The method tries to extract a LinkedHashMap that was serialized. A complicating factor is that previously we used to use HashMap 
     * instead of LinkedhashMap, therefore we need this helper method to fall through to extracting a HashMap instead of a LinkedHashMap. 
     * 
     * @param 
     *            Class that we are trying to extract.
     * @param t
     *            Class that we are trying to extract.
     * @param object
     *            An object implementing java.lang.Serializable interface
     * @return The unmarshalled or original object of type T or null if object is neither type T or jboss marshalled value
     * @throws ClassCastException if the object is JBOSS marshalled, but not of type t
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public static LinkedHashMap extractLinkedHashMap(final Serializable object) {
		LinkedHashMap ret = null;
		// When the wrong class is given it can either return null, or throw an exception
		try {
			ret = JBossUnmarshaller.extractObject(LinkedHashMap.class, object);
			if (ret != null) {
				return ret;
			}
		} catch (ClassCastException e) {
			// NOPMD: pass through to the end line
		}
		// If this is an old record, before we switched to LinkedHashMap, we have to try that, we should get a ClassCastException or null from above...
		return new LinkedHashMap(JBossUnmarshaller.extractObject(HashMap.class, object));
	}

    /**
     * During upgrade from EJBCA 3.11.x to EJBCA 4.0.x on a 100% up-time cluster, we will have old EJB 2.1 CMP serialization on JBoss installations
     * together with new EJB 3.0 JPA pure Java serialization.
     * 
     * Until all nodes has been upgraded, we have to keep storing things as before, to not break the old installations. 
     * This is what the flag keepJbossSerializationIfUsed is used for.
     * 
     * @param object
     *            if the object that will be stored as a BLOB
     * @return either the pure object or a JBoss serialized version of the Object
     */
    public static Serializable serializeObject(final Serializable object) {
        Serializable ret = object;
		if (lookForJbossMarshaller && CesecoreConfiguration.isKeepJbossSerializationIfUsed()) {
            try {
                // Do "ret = new org.jboss.invocation.MarshalledValue(object)" with inflection, since we can't know
                // if we are running on a JBoss AS or not.
                ret = (Serializable) Class.forName(JBOSS_MARSHALL_CLASS).getConstructor(Object.class).newInstance(object);
            } catch (ClassNotFoundException e1) {
                LOG.debug(JBOSS_MARSHALL_CLASS + " does not exist. Assuming that this is a non-JBoss installation.");
                lookForJbossMarshaller = false; // Can only go from true to false, so there is no need for synchronization
            } catch (Exception e) {
                LOG.error("Unable to store as JBoss MarshalledValue.", e);
            }
        }
        return ret;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy