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

org.springframework.amqp.support.converter.DefaultClassMapper Maven / Gradle / Ivy

There is a newer version: 3.1.6
Show newest version
/*
 * Copyright 2002-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.springframework.amqp.support.converter;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.amqp.core.MessageProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ClassUtils;

/**
 * Maps to/from JSON using type information in the {@link MessageProperties};
 * the default name of the message property containing the type is '__TypeId__'.
 * An optional property {@link #setDefaultType(Class)}
 * is provided that allows mapping to a statically defined type, if no message property is
 * found in the message properties.
 * @author Mark Pollack
 * @author Gary Russell
 *
 */
public class DefaultClassMapper implements ClassMapper, InitializingBean {

	public static final String DEFAULT_CLASSID_FIELD_NAME = "__TypeId__";

	private volatile Map> idClassMapping = new HashMap>();

	private volatile Map, String> classIdMapping = new HashMap, String>();

	private final String defaultHashtableTypeId = "Hashtable";

	private volatile Class defaultHashtableClass = Hashtable.class;

	private volatile Class defaultType;

	/**
	 * The type returned by {@link #toClass(MessageProperties)} if no type information
	 * is found in the message properties.
	 * @param defaultType the defaultType to set
	 */
	public void setDefaultType(Class defaultType) {
		this.defaultType = defaultType;
	}

	public void setDefaultHashtableClass(Class defaultHashtableClass) {
		this.defaultHashtableClass = defaultHashtableClass;
	}

	public String getClassIdFieldName() {
		return DEFAULT_CLASSID_FIELD_NAME;
	}

	public void setIdClassMapping(Map> idClassMapping) {
		this.idClassMapping = idClassMapping;
	}

	private String fromClass(Class classOfObjectToConvert) {
		if (classIdMapping.containsKey(classOfObjectToConvert)) {
			return classIdMapping.get(classOfObjectToConvert);
		}
		if (Map.class.isAssignableFrom(classOfObjectToConvert)) {
			return this.defaultHashtableTypeId;
		}
		return classOfObjectToConvert.getName();
	}

	private Class toClass(String classId) {
		if (this.idClassMapping.containsKey(classId)) {
			return idClassMapping.get(classId);
		}
		if (classId.equals(this.defaultHashtableTypeId)) {
			return this.defaultHashtableClass;
		}
		try {
			return ClassUtils.forName(classId, getClass().getClassLoader());
		} catch (ClassNotFoundException e) {
			throw new MessageConversionException(
					"failed to resolve class name [" + classId + "]", e);
		} catch (LinkageError e) {
			throw new MessageConversionException(
					"failed to resolve class name [" + classId + "]", e);
		}
	}

	public void afterPropertiesSet() throws Exception {
		validateIdTypeMapping();
	}

	private void validateIdTypeMapping() {
		Map> finalIdClassMapping = new HashMap>();
		for (Entry> entry : idClassMapping.entrySet()) {
			String id = entry.getKey();
			Class clazz = entry.getValue();
			finalIdClassMapping.put(id, clazz);
			classIdMapping.put(clazz, id);
		}
		this.idClassMapping = finalIdClassMapping;
	}

	public void fromClass(Class clazz, MessageProperties properties) {
		properties.getHeaders().put(getClassIdFieldName(), fromClass(clazz));
	}

	public Class toClass(MessageProperties properties) {
		Map headers = properties.getHeaders();
		Object classIdFieldNameValue = headers.get(getClassIdFieldName());
		String classId = null;
		if (classIdFieldNameValue != null) {
			classId = classIdFieldNameValue.toString();
		}
		if (classId == null) {
			if (this.defaultType != null) {
				return this.defaultType;
			}
			else {
				throw new MessageConversionException(
						"failed to convert Message content. Could not resolve "
								+ getClassIdFieldName() + " in header " +
								"and no defaultType provided");
			}
		}
		return toClass(classId);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy