cls, Type type) throws IOException, ClassNotFoundException {
+ return (T) readObject();
+ }
+
+ public InputStream getInputStream() {
+ return getObjectInputStream();
+ }
+}
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java
new file mode 100644
index 000000000..c697991eb
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.dubbo.common.serialize.java;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.StreamCorruptedException;
+import java.lang.reflect.Proxy;
+
+/**
+ * @author: yuanyuan
+ * @date: 2023/12/28 8:28 下午
+ */
+public class ClassLoaderObjectInputStream extends ObjectInputStream {
+
+ private ClassLoader classLoader;
+
+ /**
+ * Constructs a new ClassLoaderObjectInputStream.
+ *
+ * @param classLoader the ClassLoader from which classes should be loaded
+ * @param inputStream the InputStream to work on
+ * @throws IOException in case of an I/O error
+ * @throws StreamCorruptedException if the stream is corrupted
+ */
+ public ClassLoaderObjectInputStream(final ClassLoader classLoader, final InputStream inputStream)
+ throws IOException,
+ StreamCorruptedException {
+ super(inputStream);
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Resolve a class specified by the descriptor using the
+ * specified ClassLoader or the super ClassLoader.
+ *
+ * @param objectStreamClass descriptor of the class
+ * @return the Class object described by the ObjectStreamClass
+ * @throws IOException in case of an I/O error
+ * @throws ClassNotFoundException if the Class cannot be found
+ */
+ @Override
+ protected Class> resolveClass(final ObjectStreamClass objectStreamClass) throws IOException,
+ ClassNotFoundException {
+
+ try {
+ return Class.forName(objectStreamClass.getName(), false, classLoader);
+ } catch (final ClassNotFoundException cnfe) {
+ // delegate to super class loader which can resolve primitives
+ return super.resolveClass(objectStreamClass);
+ }
+ }
+
+ /**
+ * Create a proxy class that implements the specified interfaces using
+ * the specified ClassLoader or the super ClassLoader.
+ *
+ * @param interfaces the interfaces to implement
+ * @return a proxy class implementing the interfaces
+ * @throws IOException in case of an I/O error
+ * @throws ClassNotFoundException if the Class cannot be found
+ * @see ObjectInputStream#resolveProxyClass(String[])
+ * @since 2.1
+ */
+ @Override
+ protected Class> resolveProxyClass(final String[] interfaces) throws IOException,
+ ClassNotFoundException {
+ final Class>[] interfaceClasses = new Class[interfaces.length];
+ for (int i = 0; i < interfaces.length; i++) {
+ interfaceClasses[i] = Class.forName(interfaces[i], false, classLoader);
+ }
+ try {
+ return Proxy.getProxyClass(classLoader, interfaceClasses);
+ } catch (final IllegalArgumentException e) {
+ return super.resolveProxyClass(interfaces);
+ }
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+}
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/common/serialize/java/JavaSerialization.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/common/serialize/java/JavaSerialization.java
new file mode 100644
index 000000000..c7d6f8415
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/common/serialize/java/JavaSerialization.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.dubbo.common.serialize.java;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.Serialization;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import static org.apache.dubbo.common.serialize.Constants.JAVA_SERIALIZATION_ID;
+
+/**
+ * Java serialization implementation
+ *
+ *
+ * e.g. <dubbo:protocol serialization="java" />
+ *
+ */
+public class JavaSerialization implements Serialization {
+
+ @Override
+ public byte getContentTypeId() {
+ return JAVA_SERIALIZATION_ID;
+ }
+
+ @Override
+ public String getContentType() {
+ return "x-application/java";
+ }
+
+ @Override
+ public ObjectOutput serialize(URL url, OutputStream out) throws IOException {
+ return new JavaObjectOutput(out);
+ }
+
+ @Override
+ public ObjectInput deserialize(URL url, InputStream is) throws IOException {
+ return new ClassLoaderJavaObjectInput(new ClassLoaderObjectInputStream(null, is));
+ }
+
+}
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
new file mode 100644
index 000000000..b3e345746
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.dubbo.config.spring.context;
+
+import org.apache.dubbo.config.DubboShutdownHook;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+
+import com.alibaba.spring.context.OnceApplicationContextEventListener;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ApplicationContextEvent;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.Ordered;
+
+/**
+ * The {@link ApplicationListener} for {@link DubboBootstrap}'s lifecycle when the {@link ContextRefreshedEvent}
+ * and {@link ContextClosedEvent} raised
+ *
+ * @since 2.7.5
+ */
+public class DubboBootstrapApplicationListener extends OnceApplicationContextEventListener
+ implements
+ Ordered {
+
+ /**
+ * The bean name of {@link DubboBootstrapApplicationListener}
+ *
+ * @since 2.7.6
+ */
+ public static final String BEAN_NAME = "dubboBootstrapApplicationListener";
+
+ private final DubboBootstrap dubboBootstrap;
+
+ public DubboBootstrapApplicationListener() {
+ this.dubboBootstrap = DubboBootstrap.getInstance();
+ }
+
+ public DubboBootstrapApplicationListener(ApplicationContext applicationContext) {
+ super(applicationContext);
+ this.dubboBootstrap = DubboBootstrap.getInstance();
+ DubboBootstrapStartStopListenerSpringAdapter.applicationContext = applicationContext;
+ }
+
+ @Override
+ public void onApplicationContextEvent(ApplicationContextEvent event) {
+ // patch begin
+ if (this.getClass().getClassLoader() != Thread.currentThread().getContextClassLoader()) {
+ return;
+ }
+ // patch end
+
+ if (DubboBootstrapStartStopListenerSpringAdapter.applicationContext == null) {
+ DubboBootstrapStartStopListenerSpringAdapter.applicationContext = event
+ .getApplicationContext();
+ }
+ if (event instanceof ContextRefreshedEvent) {
+ onContextRefreshedEvent((ContextRefreshedEvent) event);
+ } else if (event instanceof ContextClosedEvent) {
+ onContextClosedEvent((ContextClosedEvent) event);
+ }
+ }
+
+ private void onContextRefreshedEvent(ContextRefreshedEvent event) {
+ dubboBootstrap.start();
+ }
+
+ private void onContextClosedEvent(ContextClosedEvent event) {
+ DubboShutdownHook.getDubboShutdownHook().run();
+ }
+
+ @Override
+ public int getOrder() {
+ return LOWEST_PRECEDENCE;
+ }
+}
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
new file mode 100644
index 000000000..e2e5df0ae
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.dubbo.rpc.protocol.dubbo;
+
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.serialize.Cleanable;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.java.ClassLoaderJavaObjectInput;
+import org.apache.dubbo.common.serialize.java.ClassLoaderObjectInputStream;
+import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.Codec;
+import org.apache.dubbo.remoting.Decodeable;
+import org.apache.dubbo.remoting.exchange.Request;
+import org.apache.dubbo.remoting.transport.CodecSupport;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.MethodDescriptor;
+import org.apache.dubbo.rpc.model.ServiceDescriptor;
+import org.apache.dubbo.rpc.model.ServiceRepository;
+import org.apache.dubbo.rpc.support.RpcUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.dubbo.common.URL.buildKey;
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;
+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;
+import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument;
+
+public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Decodeable {
+
+ private static final Logger log = LoggerFactory.getLogger(DecodeableRpcInvocation.class);
+
+ private Channel channel;
+
+ private byte serializationType;
+
+ private InputStream inputStream;
+
+ private Request request;
+
+ private volatile boolean hasDecoded;
+
+ public DecodeableRpcInvocation(Channel channel, Request request, InputStream is, byte id) {
+ Assert.notNull(channel, "channel == null");
+ Assert.notNull(request, "request == null");
+ Assert.notNull(is, "inputStream == null");
+ this.channel = channel;
+ this.request = request;
+ this.inputStream = is;
+ this.serializationType = id;
+ }
+
+ @Override
+ public void decode() throws Exception {
+ if (!hasDecoded && channel != null && inputStream != null) {
+ try {
+ decode(channel, inputStream);
+ } catch (Throwable e) {
+ if (log.isWarnEnabled()) {
+ log.warn("Decode rpc invocation failed: " + e.getMessage(), e);
+ }
+ request.setBroken(true);
+ request.setData(e);
+ } finally {
+ hasDecoded = true;
+ }
+ }
+ }
+
+ @Override
+ public void encode(Channel channel, OutputStream output, Object message) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ private void checkSerializationTypeFromRemote() {
+
+ }
+
+ @Override
+ public Object decode(Channel channel, InputStream input) throws IOException {
+ ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)
+ .deserialize(channel.getUrl(), input);
+ this.put(SERIALIZATION_ID_KEY, serializationType);
+
+ String dubboVersion = in.readUTF();
+ request.setVersion(dubboVersion);
+ setAttachment(DUBBO_VERSION_KEY, dubboVersion);
+
+ String path = in.readUTF();
+ setAttachment(PATH_KEY, path);
+ String version = in.readUTF();
+ setAttachment(VERSION_KEY, version);
+
+ setMethodName(in.readUTF());
+
+ String desc = in.readUTF();
+ setParameterTypesDesc(desc);
+
+ try {
+ if (ConfigurationUtils.getSystemConfiguration().getBoolean(
+ SERIALIZATION_SECURITY_CHECK_KEY, false)) {
+ CodecSupport.checkSerialization(path, version, serializationType);
+ }
+ Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;
+ Class>[] pts = DubboCodec.EMPTY_CLASS_ARRAY;
+ if (desc.length() > 0) {
+ // if (RpcUtils.isGenericCall(path, getMethodName()) || RpcUtils.isEcho(path, getMethodName())) {
+ // pts = ReflectUtils.desc2classArray(desc);
+ // } else {
+ ServiceRepository repository = ApplicationModel.getServiceRepository();
+ ServiceDescriptor serviceDescriptor = repository.lookupService(path);
+ if (serviceDescriptor != null) {
+ MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(
+ getMethodName(), desc);
+ if (methodDescriptor != null) {
+ pts = methodDescriptor.getParameterClasses();
+ this.setReturnTypes(methodDescriptor.getReturnTypes());
+ }
+ }
+ if (pts == DubboCodec.EMPTY_CLASS_ARRAY) {
+ if (!RpcUtils.isGenericCall(desc, getMethodName())
+ && !RpcUtils.isEcho(desc, getMethodName())) {
+ throw new IllegalArgumentException("Service not found:" + path + ", "
+ + getMethodName());
+ }
+ pts = ReflectUtils.desc2classArray(desc);
+ }
+ // }
+
+ // patch begin
+ if (in instanceof ClassLoaderJavaObjectInput) {
+ InputStream is = ((ClassLoaderJavaObjectInput) in).getInputStream();
+ if (is instanceof ClassLoaderObjectInputStream) {
+ ClassLoader cl = serviceDescriptor.getServiceInterfaceClass()
+ .getClassLoader();
+ ((ClassLoaderObjectInputStream) is).setClassLoader(cl);
+ }
+ }
+ // patch end
+
+ args = new Object[pts.length];
+ for (int i = 0; i < args.length; i++) {
+ try {
+ args[i] = in.readObject(pts[i]);
+ } catch (Exception e) {
+ if (log.isWarnEnabled()) {
+ log.warn("Decode argument failed: " + e.getMessage(), e);
+ }
+ }
+ }
+ }
+ setParameterTypes(pts);
+
+ Map map = in.readAttachments();
+ if (map != null && map.size() > 0) {
+ Map attachment = getObjectAttachments();
+ if (attachment == null) {
+ attachment = new HashMap<>();
+ }
+ attachment.putAll(map);
+ setObjectAttachments(attachment);
+ }
+
+ //decode argument ,may be callback
+ for (int i = 0; i < args.length; i++) {
+ args[i] = decodeInvocationArgument(channel, this, pts, i, args[i]);
+ }
+
+ setArguments(args);
+ String targetServiceName = buildKey(getAttachment(PATH_KEY), getAttachment(GROUP_KEY),
+ getAttachment(VERSION_KEY));
+ setTargetServiceUniqueName(targetServiceName);
+ } catch (ClassNotFoundException e) {
+ throw new IOException(StringUtils.toString("Read invocation data failed.", e));
+ } finally {
+ if (in instanceof Cleanable) {
+ ((Cleanable) in).cleanup();
+ }
+ }
+ return this;
+ }
+
+}
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
new file mode 100644
index 000000000..aba61d1e9
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.dubbo.rpc.protocol.dubbo;
+
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.serialize.Cleanable;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.java.ClassLoaderJavaObjectInput;
+import org.apache.dubbo.common.serialize.java.ClassLoaderObjectInputStream;
+import org.apache.dubbo.common.utils.ArrayUtils;
+import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.Codec;
+import org.apache.dubbo.remoting.Decodeable;
+import org.apache.dubbo.remoting.exchange.Response;
+import org.apache.dubbo.remoting.transport.CodecSupport;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.support.RpcUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Type;
+
+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;
+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;
+
+public class DecodeableRpcResult extends AppResponse implements Codec, Decodeable {
+
+ private static final Logger log = LoggerFactory.getLogger(DecodeableRpcResult.class);
+
+ private Channel channel;
+
+ private byte serializationType;
+
+ private InputStream inputStream;
+
+ private Response response;
+
+ private Invocation invocation;
+
+ private volatile boolean hasDecoded;
+
+ public DecodeableRpcResult(Channel channel, Response response, InputStream is,
+ Invocation invocation, byte id) {
+ Assert.notNull(channel, "channel == null");
+ Assert.notNull(response, "response == null");
+ Assert.notNull(is, "inputStream == null");
+ this.channel = channel;
+ this.response = response;
+ this.inputStream = is;
+ this.invocation = invocation;
+ this.serializationType = id;
+ }
+
+ @Override
+ public void encode(Channel channel, OutputStream output, Object message) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object decode(Channel channel, InputStream input) throws IOException {
+ if (log.isDebugEnabled()) {
+ Thread thread = Thread.currentThread();
+ log.debug("Decoding in thread -- [" + thread.getName() + "#" + thread.getId() + "]");
+ }
+
+ ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)
+ .deserialize(channel.getUrl(), input);
+
+ // patch begin
+ if (in instanceof ClassLoaderJavaObjectInput) {
+ InputStream is = ((ClassLoaderJavaObjectInput) in).getInputStream();
+ if (is instanceof ClassLoaderObjectInputStream) {
+ ClassLoader cl = invocation.getInvoker().getInterface().getClassLoader();
+ ((ClassLoaderObjectInputStream) is).setClassLoader(cl);
+ }
+ }
+ // patch end
+
+ byte flag = in.readByte();
+ switch (flag) {
+ case DubboCodec.RESPONSE_NULL_VALUE:
+ break;
+ case DubboCodec.RESPONSE_VALUE:
+ handleValue(in);
+ break;
+ case DubboCodec.RESPONSE_WITH_EXCEPTION:
+ handleException(in);
+ break;
+ case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
+ handleAttachment(in);
+ break;
+ case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS:
+ handleValue(in);
+ handleAttachment(in);
+ break;
+ case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
+ handleException(in);
+ handleAttachment(in);
+ break;
+ default:
+ throw new IOException(
+ "Unknown result flag, expect '0' '1' '2' '3' '4' '5', but received: " + flag);
+ }
+ if (in instanceof Cleanable) {
+ ((Cleanable) in).cleanup();
+ }
+ return this;
+ }
+
+ @Override
+ public void decode() throws Exception {
+ if (!hasDecoded && channel != null && inputStream != null) {
+ try {
+ if (invocation != null) {
+ if (ConfigurationUtils.getSystemConfiguration().getBoolean(
+ SERIALIZATION_SECURITY_CHECK_KEY, false)) {
+ Object serializationTypeObj = invocation.get(SERIALIZATION_ID_KEY);
+ if (serializationTypeObj != null) {
+ if ((byte) serializationTypeObj != serializationType) {
+ throw new IOException(
+ "Unexpected serialization id:"
+ + serializationType
+ + " received from network, please check if the peer send the right id.");
+ }
+ }
+ }
+ }
+ decode(channel, inputStream);
+ } catch (Throwable e) {
+ if (log.isWarnEnabled()) {
+ log.warn("Decode rpc result failed: " + e.getMessage(), e);
+ }
+ response.setStatus(Response.CLIENT_ERROR);
+ response.setErrorMessage(StringUtils.toString(e));
+ } finally {
+ hasDecoded = true;
+ }
+ }
+ }
+
+ private void handleValue(ObjectInput in) throws IOException {
+ try {
+ Type[] returnTypes;
+ if (invocation instanceof RpcInvocation) {
+ returnTypes = ((RpcInvocation) invocation).getReturnTypes();
+ } else {
+ returnTypes = RpcUtils.getReturnTypes(invocation);
+ }
+ Object value = null;
+ if (ArrayUtils.isEmpty(returnTypes)) {
+ // This almost never happens?
+ value = in.readObject();
+ } else if (returnTypes.length == 1) {
+ value = in.readObject((Class>) returnTypes[0]);
+ } else {
+ value = in.readObject((Class>) returnTypes[0], returnTypes[1]);
+ }
+ setValue(value);
+ } catch (ClassNotFoundException e) {
+ rethrow(e);
+ }
+ }
+
+ private void handleException(ObjectInput in) throws IOException {
+ try {
+ setException(in.readThrowable());
+ } catch (ClassNotFoundException e) {
+ rethrow(e);
+ }
+ }
+
+ private void handleAttachment(ObjectInput in) throws IOException {
+ try {
+ addObjectAttachments(in.readAttachments());
+ } catch (ClassNotFoundException e) {
+ rethrow(e);
+ }
+ }
+
+ private void rethrow(Exception e) throws IOException {
+ throw new IOException(StringUtils.toString("Read response data failed.", e));
+ }
+}
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/services/org.apache.dubbo.common.context.FrameworkExt b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/services/org.apache.dubbo.common.context.FrameworkExt
new file mode 100644
index 000000000..686e6684e
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/services/org.apache.dubbo.common.context.FrameworkExt
@@ -0,0 +1,2 @@
+com.alipay.sofa.serverless.support.dubbo.ServerlessConfigManager
+com.alipay.sofa.serverless.support.dubbo.ServerlessServiceRepository
\ No newline at end of file
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/services/org.apache.dubbo.rpc.Filter b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/services/org.apache.dubbo.rpc.Filter
new file mode 100644
index 000000000..186964048
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/services/org.apache.dubbo.rpc.Filter
@@ -0,0 +1 @@
+com.alipay.sofa.serverless.support.dubbo.ConsumerRedefinePathFilter
\ No newline at end of file
diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/spring.factories b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..0b5e76a75
--- /dev/null
+++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.7/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.context.ApplicationListener=\
+ com.alipay.sofa.serverless.support.dubbo.BizDubboBootstrapListener
\ No newline at end of file