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

com.tangosol.internal.util.invoke.lambda.StaticLambdaInfo Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2022, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * https://oss.oracle.com/licenses/upl.
 */

package com.tangosol.internal.util.invoke.lambda;

import com.tangosol.internal.util.invoke.Lambdas;

import com.tangosol.io.ExternalizableLite;
import com.tangosol.io.SerializationSupport;
import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;

import com.tangosol.util.Base;
import com.tangosol.util.ExternalizableHelper;
import com.tangosol.util.HashHelper;

import jakarta.json.bind.annotation.JsonbProperty;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import java.io.ObjectStreamException;

import java.lang.invoke.MethodHandleInfo;
import java.lang.invoke.SerializedLambda;

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Objects;

/**
 * Serialized form of a static lambda expression.
 * 

* The properties of this class represent the information that is present at the * lambda factory site, including static metafactory arguments such as the * identity of the primary functional interface method and the identity of the * implementation method, as well as dynamic metafactory arguments such as values * captured from the lexical scope at the time of lambda capture. * * @see SerializationSupport * @see com.tangosol.internal.util.invoke.Remotable#writeReplace() * @see Lambdas#ensureSerializable(Object) * * @author as 2014.07.02 * @author jf 2020.06.16 * * @since 14.1.1.0.2 */ public class StaticLambdaInfo implements ExternalizableLite, PortableObject, SerializationSupport { // ---- constructors ---------------------------------------------------- /** * Deserialization constructor. */ public StaticLambdaInfo() { } /** * Create a {@code StaticLambdaInfo} from the low-level information present at the * lambda factory site. * * @param clz lamdba class * @param function lambda function */ public StaticLambdaInfo(Class clz, T function) { SerializedLambda lambda = Lambdas.getSerializedLambda(function); m_sCapturingClass = lambda.getCapturingClass(); m_sFunctionalInterfaceClass = lambda.getFunctionalInterfaceClass(); m_sFunctionalInterfaceMethodName = lambda.getFunctionalInterfaceMethodName(); m_sFunctionalInterfaceMethodSignature = lambda.getFunctionalInterfaceMethodSignature(); m_nImplMethodKind = lambda.getImplMethodKind(); m_sImplClass = lambda.getImplClass(); m_sImplMethodName = lambda.getImplMethodName(); m_sImplMethodSignature = lambda.getImplMethodSignature(); m_sInstantiatedMethodType = lambda.getInstantiatedMethodType(); m_aoCapturedArgs = getCapturedArguments(lambda); } // ----- StaticLambdaInfo methods --------------------------------------- /** * Get the name of the class that captured this lambda. * * @return the name of the class that captured this lambda */ public String getCapturingClass() { return m_sCapturingClass; } /** * Get the name of the invoked type to which this lambda has been converted * * @return the name of the functional interface class to which this lambda * has been converted */ public String getFunctionalInterfaceClass() { return m_sFunctionalInterfaceClass; } /** * Get the name of the primary method for the functional interface to which * this lambda has been converted. * * @return the name of the primary methods of the functional interface */ public String getFunctionalInterfaceMethodName() { return m_sFunctionalInterfaceMethodName; } /** * Get the signature of the primary method for the functional interface to * which this lambda has been converted. * * @return the signature of the primary method of the functional interface */ public String getFunctionalInterfaceMethodSignature() { return m_sFunctionalInterfaceMethodSignature; } /** * Get the name of the class containing the implementation method. * * @return the name of the class containing the implementation method */ public String getImplClass() { return m_sImplClass; } /** * Get the name of the implementation method. * * @return the name of the implementation method */ public String getImplMethodName() { return m_sImplMethodName; } /** * Get the signature of the implementation method. * * @return the signature of the implementation method */ public String getImplMethodSignature() { return m_sImplMethodSignature; } /** * Get the method handle kind (see {@link MethodHandleInfo}) of the * implementation method. * * @return the method handle kind of the implementation method */ public int getImplMethodKind() { return m_nImplMethodKind; } /** * Get the signature of the primary functional interface method after type * variables are substituted with their instantiation from the capture * site. * * @return the signature of the primary functional interface method after * type variable processing */ public final String getInstantiatedMethodType() { return m_sInstantiatedMethodType; } /** * Get dynamic arguments to the lambda capture site. * * @return the dynamic arguments to the lambda capture site */ public Object[] getCapturedArgs() { return m_aoCapturedArgs; } /** * Get the count of dynamic arguments to the lambda capture site. * * @return the count of dynamic arguments to the lambda capture site */ public int getCapturedArgCount() { return m_aoCapturedArgs.length; } // ----- SerializationSupport interface --------------------------------- /** * {@inheritDoc} * * It provides deserialization support for {@link StaticLambdaInfo} * objects by converting this {@code StaticLambdaInfo} into a lambda. */ @Override public Object readResolve() throws ObjectStreamException { return createLambda(toSerializedLambda(Base.getContextClassLoader(this))); } // ----- ExternalizableLite interface ----------------------------------- @Override public void readExternal(DataInput in) throws IOException { m_sCapturingClass = ExternalizableHelper.readSafeUTF(in); m_sFunctionalInterfaceClass = ExternalizableHelper.readSafeUTF(in); m_sFunctionalInterfaceMethodName = ExternalizableHelper.readSafeUTF(in); m_sFunctionalInterfaceMethodSignature = ExternalizableHelper.readSafeUTF(in); m_nImplMethodKind = ExternalizableHelper.readInt(in); m_sImplClass = ExternalizableHelper.readSafeUTF(in); m_sImplMethodName = ExternalizableHelper.readSafeUTF(in); m_sImplMethodSignature = ExternalizableHelper.readSafeUTF(in); m_sInstantiatedMethodType = ExternalizableHelper.readSafeUTF(in); int cCapturedArgs = ExternalizableHelper.readInt(in); Base.azzert(cCapturedArgs < 256, "Unexpected number of captured arguments."); Object[] aoCapturedArgs = cCapturedArgs == 0 ? EMPTY_OBJECT_ARRAY : new Object[cCapturedArgs]; for (int i = 0; i < cCapturedArgs; i++) { aoCapturedArgs[i] = ExternalizableHelper.readObject(in); } m_aoCapturedArgs = aoCapturedArgs; } @Override public void writeExternal(DataOutput out) throws IOException { Object[] aoCapturedArgs = m_aoCapturedArgs; int cCapturedArgs = aoCapturedArgs == null ? 0 : aoCapturedArgs.length; ExternalizableHelper.writeSafeUTF(out, m_sCapturingClass); ExternalizableHelper.writeSafeUTF(out, m_sFunctionalInterfaceClass); ExternalizableHelper.writeSafeUTF(out, m_sFunctionalInterfaceMethodName); ExternalizableHelper.writeSafeUTF(out, m_sFunctionalInterfaceMethodSignature); ExternalizableHelper.writeInt (out, m_nImplMethodKind); ExternalizableHelper.writeSafeUTF(out, m_sImplClass); ExternalizableHelper.writeSafeUTF(out, m_sImplMethodName); ExternalizableHelper.writeSafeUTF(out, m_sImplMethodSignature); ExternalizableHelper.writeSafeUTF(out, m_sInstantiatedMethodType); ExternalizableHelper.writeInt (out, cCapturedArgs); for (int i = 0; i < cCapturedArgs; i++) { ExternalizableHelper.writeObject(out, m_aoCapturedArgs[i]); } } // ---- PortableObject interface ---------------------------------------- @Override public void readExternal(PofReader reader) throws IOException { m_sCapturingClass = reader.readString(0); m_sFunctionalInterfaceClass = reader.readString(1); m_sFunctionalInterfaceMethodName = reader.readString(2); m_sFunctionalInterfaceMethodSignature = reader.readString(3); m_nImplMethodKind = reader.readInt(4); m_sImplClass = reader.readString(5); m_sImplMethodName = reader.readString(6); m_sImplMethodSignature = reader.readString(7); m_sInstantiatedMethodType = reader.readString(8); m_aoCapturedArgs = reader.readArray(9, Object[]::new); } @Override public void writeExternal(PofWriter writer) throws IOException { writer.writeString(0, m_sCapturingClass); writer.writeString(1, m_sFunctionalInterfaceClass); writer.writeString(2, m_sFunctionalInterfaceMethodName); writer.writeString(3, m_sFunctionalInterfaceMethodSignature); writer.writeInt(4, m_nImplMethodKind); writer.writeString(5, m_sImplClass); writer.writeString(6, m_sImplMethodName); writer.writeString(7, m_sImplMethodSignature); writer.writeString(8, m_sInstantiatedMethodType); writer.writeObjectArray(9, m_aoCapturedArgs); } // ---- Object methods -------------------------------------------------- @Override public boolean equals(Object oThat) { if (this == oThat) { return true; } if (oThat == null || getClass() != oThat.getClass()) { return false; } StaticLambdaInfo info = (StaticLambdaInfo) oThat; return m_nImplMethodKind == info.m_nImplMethodKind && Base.equals(m_sCapturingClass, info.m_sCapturingClass) && Base.equals(m_sFunctionalInterfaceClass,info.m_sFunctionalInterfaceClass) && Base.equals(m_sFunctionalInterfaceMethodName, m_sFunctionalInterfaceMethodName) && Base.equals(m_sFunctionalInterfaceMethodSignature, m_sFunctionalInterfaceMethodSignature) && Base.equals(m_sImplClass, m_sImplClass) && Base.equals(m_sImplMethodName, m_sImplMethodName) && Base.equals(m_sImplMethodSignature, m_sImplMethodSignature) && Base.equals(m_sInstantiatedMethodType, m_sInstantiatedMethodType); } @Override public int hashCode() { int nResult = HashHelper.hash(m_sCapturingClass.hashCode(), 31); nResult = HashHelper.hash(m_sFunctionalInterfaceClass.hashCode(), nResult); nResult = HashHelper.hash(m_sFunctionalInterfaceMethodName.hashCode(), nResult); nResult = HashHelper.hash(m_sFunctionalInterfaceMethodSignature.hashCode(), nResult); nResult = HashHelper.hash(m_sImplClass.hashCode(), nResult); nResult = HashHelper.hash(m_sImplMethodName.hashCode(), nResult); nResult = HashHelper.hash( m_sImplMethodSignature.hashCode(), nResult); nResult = HashHelper.hash(m_nImplMethodKind, nResult); nResult = HashHelper.hash( m_sInstantiatedMethodType.hashCode(), nResult); return nResult; } @Override public String toString() { return "StaticLambdaInfo{" + "capturingClass='" + m_sCapturingClass + '\'' + ", functionalInterfaceClass='" + m_sFunctionalInterfaceClass + '\'' + ", functionalInterfaceMethodName='" + m_sFunctionalInterfaceMethodName + '\'' + ", functionalInterfaceMethodSignature='" + m_sFunctionalInterfaceMethodSignature + '\'' + ", implClass='" + m_sImplClass + '\'' + ", implMethodName='" + m_sImplMethodName + '\'' + ", implMethodSignature='" + m_sImplMethodSignature + '\'' + ", implMethodKind=" + m_nImplMethodKind + ", instantiatedMethodType='" + m_sInstantiatedMethodType + '\'' + ", capturedArgs=" + Arrays.toString(m_aoCapturedArgs) + '}'; } // ---- helpers --------------------------------------------------------- /** * Create a lambda from the provided {@link SerializedLambda}. * * @param serializedLambda Java serialization wire format for static lambda * * @return lambda created from {@link SerializedLambda} * * @throws IllegalArgumentException if parameter is null * @throws IllegalStateException if an issue arose in creating the lambda * * @since 14.1.1.0.2 */ protected static Object createLambda(SerializedLambda serializedLambda) { Objects.requireNonNull(serializedLambda); try { Method methReadResolve = AccessController.doPrivileged((PrivilegedExceptionAction) () -> { Method m = SerializedLambda.class.getDeclaredMethod("readResolve"); m.setAccessible(true); return m; }); return methReadResolve.invoke(serializedLambda); } catch (Exception e) { throw new RuntimeException("Exception resolving static lambda " + serializedLambda, e); } } /** * Return captured arguments as an array; * * @param lambda serialized lambda containing captured arguments * * @return captured arguments as an array */ private static Object[] getCapturedArguments(SerializedLambda lambda) { Object[] args = new Object[lambda.getCapturedArgCount()]; for (int i = 0; i < args.length; i++) { args[i] = lambda.getCapturedArg(i); } return args; } /** * Convert this object to a SerializedLambda instance. * * @param loader class loader to use * * @return a SerializedLambda instance */ protected SerializedLambda toSerializedLambda(ClassLoader loader) { String sName = m_sCapturingClass.replace('/', '.'); try { return new SerializedLambda( loader.loadClass(sName), m_sFunctionalInterfaceClass, m_sFunctionalInterfaceMethodName, m_sFunctionalInterfaceMethodSignature, m_nImplMethodKind, m_sImplClass, m_sImplMethodName, m_sImplMethodSignature, m_sInstantiatedMethodType, m_aoCapturedArgs); } catch (ClassNotFoundException e) { throw new RuntimeException("Failed to deserialize static lambda " + m_sImplClass + "$" + m_sImplMethodName + m_sImplMethodSignature + " due to missing context class " + sName + ".", e); } } // ----- constants ------------------------------------------------------ /** * For Java serialization. */ private static final long serialVersionUID = 1L; /** * Empty object array. */ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; // ---- data members ---------------------------------------------------- /** * The name of the capturing class. */ @JsonbProperty("capturingClass") protected String m_sCapturingClass; /** * The name of the functional interface class. */ @JsonbProperty("functionalInterfaceClass") protected String m_sFunctionalInterfaceClass; /** * The name of the functional interface method. */ @JsonbProperty("functionalInterfaceMethodName") protected String m_sFunctionalInterfaceMethodName; /** * The signature of the functional interface method. */ @JsonbProperty("functionalInterfaceMethodSignature") protected String m_sFunctionalInterfaceMethodSignature; /** * The name of the implementation class. */ @JsonbProperty("implClass") protected String m_sImplClass; /** * The name of the implementation method. */ @JsonbProperty("implMethodName") protected String m_sImplMethodName; /** * The signature of the implementation method. */ @JsonbProperty("implMethodSignature") protected String m_sImplMethodSignature; /** * The kind of implementation method. */ @JsonbProperty("implMethodKind") protected int m_nImplMethodKind; /** * The signature of the instantiated method. */ @JsonbProperty("instantiatedMethodType") protected String m_sInstantiatedMethodType; /** * Captured arguments. */ @JsonbProperty("capturedArgs") protected Object[] m_aoCapturedArgs; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy