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

com.liferay.portal.kernel.util.MethodKey Maven / Gradle / Ivy

/**
 * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
 *
 * This library 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 library 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.
 */

package com.liferay.portal.kernel.util;

import com.liferay.portal.kernel.io.Deserializer;
import com.liferay.portal.kernel.io.Serializer;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import java.lang.reflect.Method;

import java.nio.ByteBuffer;

import java.util.Arrays;

/**
 * Provides a serializable loose representation for {@link Method}, considering
 * the declaring class, name, and parameter types of the {@link Method}, while
 * ignoring its return type and exceptions. This means the compiler generated
 * bridging method is considered logically the same as it source counterpart. On
 * deserialization for a generic {@link Method}, the {@link Method} that is
 * resolved (bridge method or source method) is runtime environment dependent.
 * Whether it is resolved to a bridge method or source method is of no
 * consequence, as a force cast is performed on the method's return value,
 * assuring the same result.
 *
 * @author Brian Wing Shun Chan
 * @author Shuyang Zhou
 */
public class MethodKey implements Externalizable {

	/**
	 * The empty constructor is required by {@link java.io.Externalizable}. Do
	 * not use this for any other purpose.
	 */
	public MethodKey() {
	}

	public MethodKey(
		Class declaringClass, String methodName,
		Class... parameterTypes) {

		_declaringClass = declaringClass;
		_methodName = methodName;
		_parameterTypes = parameterTypes;
	}

	public MethodKey(Method method) {
		this(
			method.getDeclaringClass(), method.getName(),
			method.getParameterTypes());
	}

	/**
	 * @deprecated As of 6.2.0, replaced by {@link #MethodKey(Class, String,
	 *             Class...)}
	 */
	public MethodKey(
		String declaringClassName, String methodName,
		Class... parameterTypes) {

		Thread currentThread = Thread.currentThread();

		ClassLoader classLoader = currentThread.getContextClassLoader();

		try {
			_declaringClass = classLoader.loadClass(declaringClassName);
		}
		catch (ClassNotFoundException cnfe) {
			throw new RuntimeException(cnfe);
		}

		_methodName = methodName;
		_parameterTypes = parameterTypes;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (!(obj instanceof MethodKey)) {
			return false;
		}

		MethodKey methodKey = (MethodKey)obj;

		if ((_declaringClass == methodKey._declaringClass) &&
			Validator.equals(_methodName, methodKey._methodName) &&
			Arrays.equals(_parameterTypes, methodKey._parameterTypes)) {

			return true;
		}

		return false;
	}

	public Class getDeclaringClass() {
		return _declaringClass;
	}

	public Method getMethod() throws NoSuchMethodException {
		return MethodCache.get(this);
	}

	public String getMethodName() {
		return _methodName;
	}

	public Class[] getParameterTypes() {
		return _parameterTypes;
	}

	@Override
	public int hashCode() {

		// Using the same hash algorithm as java.lang.reflect.Method

		return _declaringClass.getName().hashCode() ^ _methodName.hashCode();
	}

	@Override
	public void readExternal(ObjectInput objectInput)
		throws ClassNotFoundException, IOException {

		int size = objectInput.readInt();

		byte[] data = new byte[size];

		objectInput.readFully(data);

		Deserializer deserializer = new Deserializer(ByteBuffer.wrap(data));

		_declaringClass = deserializer.readObject();
		_methodName = deserializer.readString();

		int parameterTypesLength = deserializer.readInt();

		_parameterTypes = new Class[parameterTypesLength];

		for (int i = 0; i < parameterTypesLength; i++) {
			_parameterTypes[i] = deserializer.readObject();
		}
	}

	@Override
	public String toString() {
		if (_toString != null) {
			return _toString;
		}

		StringBundler sb = new StringBundler(4 + _parameterTypes.length * 2);

		sb.append(_declaringClass.getName());
		sb.append(StringPool.PERIOD);
		sb.append(_methodName);
		sb.append(StringPool.OPEN_PARENTHESIS);

		for (Class parameterType : _parameterTypes) {
			sb.append(parameterType.getName());
			sb.append(StringPool.COMMA);
		}

		sb.setIndex(sb.index() - 1);

		sb.append(StringPool.CLOSE_PARENTHESIS);

		_toString = sb.toString();

		return _toString;
	}

	public MethodKey transform(ClassLoader classLoader)
		throws ClassNotFoundException {

		Class declaringClass = classLoader.loadClass(
			_declaringClass.getName());

		Class[] parameterTypes = new Class[_parameterTypes.length];

		for (int i = 0; i < _parameterTypes.length; i++) {
			parameterTypes[i] = classLoader.loadClass(
				_parameterTypes[i].getName());
		}

		return new MethodKey(declaringClass, _methodName, parameterTypes);
	}

	@Override
	public void writeExternal(ObjectOutput objectOutput) throws IOException {
		Serializer serializer = new Serializer();

		serializer.writeObject(_declaringClass);
		serializer.writeString(_methodName);
		serializer.writeInt(_parameterTypes.length);

		for (Class parameterType : _parameterTypes) {
			serializer.writeObject(parameterType);
		}

		ByteBuffer byteBuffer = serializer.toByteBuffer();

		objectOutput.writeInt(byteBuffer.remaining());
		objectOutput.write(
			byteBuffer.array(), byteBuffer.position(), byteBuffer.remaining());
	}

	private static final long serialVersionUID = 1L;

	private Class _declaringClass;
	private String _methodName;
	private Class[] _parameterTypes;

	// Transient cache

	private String _toString;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy