From c16993ce1b1435718a812f65211f997fc272932b Mon Sep 17 00:00:00 2001 From: 60038 Date: Wed, 25 Oct 2023 17:46:09 +0800 Subject: [PATCH 1/5] fix(support springboot1): override method to avoid no default method support in interface override method to avoid no default method support in interface In previous spring framework , BeanPostProcessor not use default method in interface. We should override this method to avoid cause AbstractMethodError in this case. --- .../common/service/ArkAutowiredBeanPostProcessor.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java index 8743e55be..6cb975532 100644 --- a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java +++ b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java @@ -134,4 +134,9 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro return bean; } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } } From 855cd70981415299ff5dee18718342bd0a3968a0 Mon Sep 17 00:00:00 2001 From: qixiaobo Date: Sat, 4 Nov 2023 23:06:09 +0800 Subject: [PATCH 2/5] fix(support springboot1): override method to avoid no default method support in interface override method to avoid no default method support in interface In previous spring framework , BeanPostProcessor not use default method in interface. We should override this method to avoid cause AbstractMethodError in this case. --- .../common/service/ArkAutowiredBeanPostProcessor.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java index 8743e55be..6cb975532 100644 --- a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java +++ b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java @@ -134,4 +134,9 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro return bean; } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } } From 13a30177494fe6e782cadff99b830e3c6008f07f Mon Sep 17 00:00:00 2001 From: qixiaobo Date: Sat, 4 Nov 2023 23:12:36 +0800 Subject: [PATCH 3/5] fix(support springboot1): override method to avoid no default method support in interface override method to avoid no default method support in interface In previous spring framework , BeanPostProcessor not use default method in interface. We should override this method to avoid cause AbstractMethodError in this case. Fix format problem --- .../common/service/ArkAutowiredBeanPostProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java index 6cb975532..af40c503e 100644 --- a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java +++ b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/service/ArkAutowiredBeanPostProcessor.java @@ -136,7 +136,8 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro } @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { return bean; } } From 1c1bb05f9dd9847a94091e3b7501bebb9c5e7c10 Mon Sep 17 00:00:00 2001 From: qixiaobo Date: Fri, 10 Nov 2023 12:31:17 +0800 Subject: [PATCH 4/5] feat(ark-serverless): support dubbo 2.6 add classsloader support with serialize --- .../sofa-serverless-adapter-ext/pom.xml | 1 + .../sofa-serverless-adapter-dubbo2.6/pom.xml | 23 + .../alibaba/dubbo/common/ClassLoaderUtil.java | 89 ++ .../common/extension/ExtensionLoader.java | 1028 +++++++++++++++++ .../java/ClassLoaderJavaObjectInput.java | 83 ++ .../java/ClassLoaderObjectInputStream.java | 98 ++ .../serialize/java/JavaSerialization.java | 54 + .../dubbo/config/model/ApplicationModel.java | 102 ++ .../extension/SpringExtensionFactory.java | 107 ++ .../dubbo/DecodeableRpcInvocation.java | 160 +++ .../protocol/dubbo/DecodeableRpcResult.java | 174 +++ 11 files changed, 1919 insertions(+) create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java create mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml b/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml index 2307f769d..d9fd7776d 100644 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml @@ -13,5 +13,6 @@ pom sofa-serverless-adapter-log4j2 + sofa-serverless-adapter-dubbo2.6 diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml new file mode 100644 index 000000000..d8244fb2b --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.alipay.sofa.serverless + sofa-serverless-adapter-ext + ${revision} + ../pom.xml + + sofa-serverless-adapter-dubbo2.6 + ${revision} + + + + com.alibaba + dubbo + 2.6.12 + + + + \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java new file mode 100644 index 000000000..e1cc41b54 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java @@ -0,0 +1,89 @@ +/* + * 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 com.alibaba.dubbo.common; + +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.config.model.ApplicationModel; +import com.alibaba.dubbo.config.model.ConsumerModel; +import com.alibaba.dubbo.config.model.ProviderModel; +import com.alibaba.dubbo.config.spring.ReferenceBean; +import com.alibaba.dubbo.config.spring.ServiceBean; +import org.springframework.context.ApplicationContext; + +import java.lang.reflect.Field; + +public class ClassLoaderUtil { + static Field serviceBeanApplicationContextField; + static Field referenceBeanApplicationContextField; + private static final Logger log = LoggerFactory.getLogger(ClassLoaderUtil.class); + + static { + try { + serviceBeanApplicationContextField = ServiceBean.class + .getDeclaredField("applicationContext"); + serviceBeanApplicationContextField.setAccessible(true); + referenceBeanApplicationContextField = ReferenceBean.class + .getDeclaredField("applicationContext"); + referenceBeanApplicationContextField.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public static ClassLoader getClassLoaderByPath(String path) { + ProviderModel providerModel = null; + for (ProviderModel iter : ApplicationModel.allProviderModels()) { + if (iter.getServiceName().contains(path)) { + providerModel = iter; + break; + } + } + if (providerModel == null) { + log.warn("can not find classloader by path:" + path); + return ClassLoader.getSystemClassLoader(); + } + ServiceBean serviceBean = (ServiceBean) providerModel.getMetadata(); + try { + ApplicationContext applicationContext = (ApplicationContext) serviceBeanApplicationContextField + .get(serviceBean); + ClassLoader classLoader = applicationContext.getClassLoader(); + Thread.currentThread().setContextClassLoader(classLoader); + return classLoader; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static ClassLoader getClassLoaderByServiceNameAndApplication(String serviceName, + String application) { + ConsumerModel consumerModel = ApplicationModel.getConsumerModel(ApplicationModel + .getConsumerModelKey(serviceName, application)); + if (consumerModel == null) + return ClassLoader.getSystemClassLoader(); + ReferenceBean referenceBean = (ReferenceBean) consumerModel.getMetadata(); + try { + ApplicationContext applicationContext = (ApplicationContext) referenceBeanApplicationContextField + .get(referenceBean); + ClassLoader classLoader = applicationContext.getClassLoader(); + Thread.currentThread().setContextClassLoader(classLoader); + return classLoader; + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java new file mode 100644 index 000000000..2165fa14c --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java @@ -0,0 +1,1028 @@ +/* + * 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 com.alibaba.dubbo.common.extension; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.support.ActivateComparator; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import com.alibaba.dubbo.common.utils.ConfigUtils; +import com.alibaba.dubbo.common.utils.Holder; +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.rpc.Protocol; +import com.alibaba.dubbo.rpc.ProxyFactory; +import com.alibaba.dubbo.rpc.cluster.Cluster; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Pattern; + +/** + * Load dubbo extensions + *
    + *
  • auto inject dependency extension
  • + *
  • auto wrap extension in wrapper
  • + *
  • default extension is an adaptive instance
  • + *
+ * + * @see Service Provider in Java 5 + * @see SPI + * @see Adaptive + * @see Activate + */ +public class ExtensionLoader { + + private static final Logger logger = LoggerFactory + .getLogger(ExtensionLoader.class); + + private static final String SERVICES_DIRECTORY = "META-INF/services/"; + + private static final String DUBBO_DIRECTORY = "META-INF/dubbo/"; + + private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + + "internal/"; + + private static final Pattern NAME_SEPARATOR = Pattern + .compile("\\s*[,]+\\s*"); + + private static final ConcurrentMap, ExtensionLoader> EXTENSION_LOADERS = new ConcurrentHashMap<>(); + private static final ConcurrentMap, ExtensionLoader>> EXTENSION_LOADERS_SUPPORT_CLASSLOADER = new ConcurrentHashMap<>(); + + static { + EXTENSION_LOADERS_SUPPORT_CLASSLOADER.put(findClassLoader(), EXTENSION_LOADERS); + } + + private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap, Object>(); + + // ============================== + + private final Class type; + + private final ExtensionFactory objectFactory; + + private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap, String>(); + + private final Holder>> cachedClasses = new Holder>>(); + + private final Map cachedActivates = new ConcurrentHashMap(); + private final ConcurrentMap> cachedInstances = new ConcurrentHashMap>(); + private final Holder cachedAdaptiveInstance = new Holder(); + private volatile Class cachedAdaptiveClass = null; + private String cachedDefaultName; + private volatile Throwable createAdaptiveInstanceError; + + private Set> cachedWrapperClasses; + + private Map exceptions = new ConcurrentHashMap(); + + private ExtensionLoader(Class type) { + this.type = type; + objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader + .getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); + } + + private static boolean withExtensionAnnotation(Class type) { + return type.isAnnotationPresent(SPI.class); + } + + @SuppressWarnings("unchecked") + public static ExtensionLoader getExtensionLoader(Class type) { + if (type == null) + throw new IllegalArgumentException("Extension type == null"); + if (!type.isInterface()) { + throw new IllegalArgumentException("Extension type(" + type + ") is not interface!"); + } + if (!withExtensionAnnotation(type)) { + throw new IllegalArgumentException("Extension type(" + type + + ") is not extension, because WITHOUT @" + + SPI.class.getSimpleName() + " Annotation!"); + } + ClassLoader classLoader = findClassLoader(); + ConcurrentMap, ExtensionLoader> classExtensionLoaderConcurrentMap = EXTENSION_LOADERS_SUPPORT_CLASSLOADER + .get(classLoader); + if (classExtensionLoaderConcurrentMap == null) { + EXTENSION_LOADERS_SUPPORT_CLASSLOADER.putIfAbsent(classLoader, + new ConcurrentHashMap<>()); + classExtensionLoaderConcurrentMap = EXTENSION_LOADERS_SUPPORT_CLASSLOADER + .get(classLoader); + //TO avoid static init only once like ReferenceConfig + ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + + ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension(); + + ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + } + // + ExtensionLoader loader = (ExtensionLoader) classExtensionLoaderConcurrentMap + .get(type); + if (loader == null) { + classExtensionLoaderConcurrentMap.putIfAbsent(type, new ExtensionLoader(type)); + loader = (ExtensionLoader) classExtensionLoaderConcurrentMap.get(type); + } + return loader; + } + + private static ClassLoader findClassLoader() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader != null) + return classLoader; + return ExtensionLoader.class.getClassLoader(); + } + + public String getExtensionName(T extensionInstance) { + return getExtensionName(extensionInstance.getClass()); + } + + public String getExtensionName(Class extensionClass) { + return cachedNames.get(extensionClass); + } + + /** + * This is equivalent to {@code getActivateExtension(url, key, null)} + * + * @param url url + * @param key url parameter key which used to get extension point names + * @return extension list which are activated. + * @see #getActivateExtension(URL, String, String) + */ + public List getActivateExtension(URL url, String key) { + return getActivateExtension(url, key, null); + } + + /** + * This is equivalent to {@code getActivateExtension(url, values, null)} + * + * @param url url + * @param values extension point names + * @return extension list which are activated + * @see #getActivateExtension(URL, String[], String) + */ + public List getActivateExtension(URL url, String[] values) { + return getActivateExtension(url, values, null); + } + + /** + * This is equivalent to {@code getActivateExtension(url, url.getParameter(key).split(","), null)} + * + * @param url url + * @param key url parameter key which used to get extension point names + * @param group group + * @return extension list which are activated. + * @see #getActivateExtension(URL, String[], String) + */ + public List getActivateExtension(URL url, String key, String group) { + String value = url.getParameter(key); + return getActivateExtension(url, value == null || value.length() == 0 ? null + : Constants.COMMA_SPLIT_PATTERN.split(value), group); + } + + /** + * Get activate extensions. + * + * @param url url + * @param values extension point names + * @param group group + * @return extension list which are activated + * @see Activate + */ + public List getActivateExtension(URL url, String[] values, String group) { + List exts = new ArrayList(); + List names = values == null ? new ArrayList(0) : Arrays.asList(values); + if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { + getExtensionClasses(); + for (Map.Entry entry : cachedActivates.entrySet()) { + String name = entry.getKey(); + Activate activate = entry.getValue(); + if (isMatchGroup(group, activate.group())) { + T ext = getExtension(name); + if (!names.contains(name) + && !names.contains(Constants.REMOVE_VALUE_PREFIX + name) + && isActive(activate, url)) { + exts.add(ext); + } + } + } + Collections.sort(exts, ActivateComparator.COMPARATOR); + } + List usrs = new ArrayList(); + for (int i = 0; i < names.size(); i++) { + String name = names.get(i); + if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX) + && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) { + if (Constants.DEFAULT_KEY.equals(name)) { + if (!usrs.isEmpty()) { + exts.addAll(0, usrs); + usrs.clear(); + } + } else { + T ext = getExtension(name); + usrs.add(ext); + } + } + } + if (!usrs.isEmpty()) { + exts.addAll(usrs); + } + return exts; + } + + private boolean isMatchGroup(String group, String[] groups) { + if (group == null || group.length() == 0) { + return true; + } + if (groups != null && groups.length > 0) { + for (String g : groups) { + if (group.equals(g)) { + return true; + } + } + } + return false; + } + + private boolean isActive(Activate activate, URL url) { + String[] keys = activate.value(); + if (keys.length == 0) { + return true; + } + for (String key : keys) { + for (Map.Entry entry : url.getParameters().entrySet()) { + String k = entry.getKey(); + String v = entry.getValue(); + if ((k.equals(key) || k.endsWith("." + key)) && ConfigUtils.isNotEmpty(v)) { + return true; + } + } + } + return false; + } + + /** + * Get extension's instance. Return null if extension is not found or is not initialized. Pls. note + * that this method will not trigger extension load. + *

+ * In order to trigger extension load, call {@link #getExtension(String)} instead. + * + * @see #getExtension(String) + */ + @SuppressWarnings("unchecked") + public T getLoadedExtension(String name) { + if (name == null || name.length() == 0) + throw new IllegalArgumentException("Extension name == null"); + Holder holder = cachedInstances.get(name); + if (holder == null) { + cachedInstances.putIfAbsent(name, new Holder()); + holder = cachedInstances.get(name); + } + return (T) holder.get(); + } + + /** + * Return the list of extensions which are already loaded. + *

+ * Usually {@link #getSupportedExtensions()} should be called in order to get all extensions. + * + * @see #getSupportedExtensions() + */ + public Set getLoadedExtensions() { + return Collections.unmodifiableSet(new TreeSet(cachedInstances.keySet())); + } + + /** + * Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException} + * will be thrown. + */ + @SuppressWarnings("unchecked") + public T getExtension(String name) { + if (name == null || name.length() == 0) + throw new IllegalArgumentException("Extension name == null"); + if ("true".equals(name)) { + return getDefaultExtension(); + } + Holder holder = cachedInstances.get(name); + if (holder == null) { + cachedInstances.putIfAbsent(name, new Holder()); + holder = cachedInstances.get(name); + } + Object instance = holder.get(); + if (instance == null) { + synchronized (holder) { + instance = holder.get(); + if (instance == null) { + instance = createExtension(name); + holder.set(instance); + } + } + } + return (T) instance; + } + + /** + * Return default extension, return null if it's not configured. + */ + public T getDefaultExtension() { + getExtensionClasses(); + if (null == cachedDefaultName || cachedDefaultName.length() == 0 + || "true".equals(cachedDefaultName)) { + return null; + } + return getExtension(cachedDefaultName); + } + + public boolean hasExtension(String name) { + if (name == null || name.length() == 0) + throw new IllegalArgumentException("Extension name == null"); + try { + this.getExtensionClass(name); + return true; + } catch (Throwable t) { + return false; + } + } + + public Set getSupportedExtensions() { + Map> clazzes = getExtensionClasses(); + return Collections.unmodifiableSet(new TreeSet(clazzes.keySet())); + } + + /** + * Return default extension name, return null if not configured. + */ + public String getDefaultExtensionName() { + getExtensionClasses(); + return cachedDefaultName; + } + + /** + * Register new extension via API + * + * @param name extension name + * @param clazz extension class + * @throws IllegalStateException when extension with the same name has already been registered. + */ + public void addExtension(String name, Class clazz) { + getExtensionClasses(); // load classes + + if (!type.isAssignableFrom(clazz)) { + throw new IllegalStateException("Input type " + clazz + "not implement Extension " + + type); + } + if (clazz.isInterface()) { + throw new IllegalStateException("Input type " + clazz + "can not be interface!"); + } + + if (!clazz.isAnnotationPresent(Adaptive.class)) { + if (StringUtils.isBlank(name)) { + throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); + } + if (cachedClasses.get().containsKey(name)) { + throw new IllegalStateException("Extension name " + name + + " already existed(Extension " + type + ")!"); + } + + cachedNames.put(clazz, name); + cachedClasses.get().put(name, clazz); + } else { + if (cachedAdaptiveClass != null) { + throw new IllegalStateException("Adaptive Extension already existed(Extension " + + type + ")!"); + } + + cachedAdaptiveClass = clazz; + } + } + + /** + * Replace the existing extension via API + * + * @param name extension name + * @param clazz extension class + * @throws IllegalStateException when extension to be placed doesn't exist + * @deprecated not recommended any longer, and use only when test + */ + @Deprecated + public void replaceExtension(String name, Class clazz) { + getExtensionClasses(); // load classes + + if (!type.isAssignableFrom(clazz)) { + throw new IllegalStateException("Input type " + clazz + "not implement Extension " + + type); + } + if (clazz.isInterface()) { + throw new IllegalStateException("Input type " + clazz + "can not be interface!"); + } + + if (!clazz.isAnnotationPresent(Adaptive.class)) { + if (StringUtils.isBlank(name)) { + throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); + } + if (!cachedClasses.get().containsKey(name)) { + throw new IllegalStateException("Extension name " + name + + " not existed(Extension " + type + ")!"); + } + + cachedNames.put(clazz, name); + cachedClasses.get().put(name, clazz); + cachedInstances.remove(name); + } else { + if (cachedAdaptiveClass == null) { + throw new IllegalStateException("Adaptive Extension not existed(Extension " + type + + ")!"); + } + + cachedAdaptiveClass = clazz; + cachedAdaptiveInstance.set(null); + } + } + + @SuppressWarnings("unchecked") + public T getAdaptiveExtension() { + Object instance = cachedAdaptiveInstance.get(); + if (instance == null) { + if (createAdaptiveInstanceError == null) { + synchronized (cachedAdaptiveInstance) { + instance = cachedAdaptiveInstance.get(); + if (instance == null) { + try { + instance = createAdaptiveExtension(); + cachedAdaptiveInstance.set(instance); + } catch (Throwable t) { + createAdaptiveInstanceError = t; + throw new IllegalStateException("fail to create adaptive instance: " + + t.toString(), t); + } + } + } + } else { + throw new IllegalStateException("fail to create adaptive instance: " + + createAdaptiveInstanceError.toString(), + createAdaptiveInstanceError); + } + } + + return (T) instance; + } + + private IllegalStateException findException(String name) { + for (Map.Entry entry : exceptions.entrySet()) { + if (entry.getKey().toLowerCase().contains(name.toLowerCase())) { + return entry.getValue(); + } + } + StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + + name); + + int i = 1; + for (Map.Entry entry : exceptions.entrySet()) { + if (i == 1) { + buf.append(", possible causes: "); + } + + buf.append("\r\n("); + buf.append(i++); + buf.append(") "); + buf.append(entry.getKey()); + buf.append(":\r\n"); + buf.append(StringUtils.toString(entry.getValue())); + } + return new IllegalStateException(buf.toString()); + } + + @SuppressWarnings("unchecked") + private T createExtension(String name) { + Class clazz = getExtensionClasses().get(name); + if (clazz == null) { + throw findException(name); + } + try { + T instance = (T) EXTENSION_INSTANCES.get(clazz); + if (instance == null) { + EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); + instance = (T) EXTENSION_INSTANCES.get(clazz); + } + injectExtension(instance); + Set> wrapperClasses = cachedWrapperClasses; + if (wrapperClasses != null && !wrapperClasses.isEmpty()) { + for (Class wrapperClass : wrapperClasses) { + instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance( + instance)); + } + } + return instance; + } catch (Throwable t) { + throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type + + ") could not be instantiated: " + t.getMessage(), t); + } + } + + private T injectExtension(T instance) { + try { + if (objectFactory != null) { + for (Method method : instance.getClass().getMethods()) { + if (method.getName().startsWith("set") + && method.getParameterTypes().length == 1 + && Modifier.isPublic(method.getModifiers())) { + Class pt = method.getParameterTypes()[0]; + try { + String property = method.getName().length() > 3 ? method.getName() + .substring(3, 4).toLowerCase() + + method.getName() + .substring(4) + : ""; + Object object = objectFactory.getExtension(pt, property); + if (object != null) { + method.invoke(instance, object); + } + } catch (Exception e) { + logger.error( + "fail to inject via method " + method.getName() + " of interface " + + type.getName() + ": " + e.getMessage(), e); + } + } + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + return instance; + } + + private Class getExtensionClass(String name) { + if (type == null) + throw new IllegalArgumentException("Extension type == null"); + if (name == null) + throw new IllegalArgumentException("Extension name == null"); + Class clazz = getExtensionClasses().get(name); + if (clazz == null) + throw new IllegalStateException("No such extension \"" + name + "\" for " + + type.getName() + "!"); + return clazz; + } + + private Map> getExtensionClasses() { + Map> classes = cachedClasses.get(); + if (classes == null) { + synchronized (cachedClasses) { + classes = cachedClasses.get(); + if (classes == null) { + classes = loadExtensionClasses(); + cachedClasses.set(classes); + } + } + } + return classes; + } + + // synchronized in getExtensionClasses + private Map> loadExtensionClasses() { + final SPI defaultAnnotation = type.getAnnotation(SPI.class); + if (defaultAnnotation != null) { + String value = defaultAnnotation.value(); + if ((value = value.trim()).length() > 0) { + String[] names = NAME_SEPARATOR.split(value); + if (names.length > 1) { + throw new IllegalStateException( + "more than 1 default extension name on extension " + type.getName() + ": " + + Arrays.toString(names)); + } + if (names.length == 1) + cachedDefaultName = names[0]; + } + } + + Map> extensionClasses = new HashMap>(); + loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY); + loadDirectory(extensionClasses, DUBBO_DIRECTORY); + loadDirectory(extensionClasses, SERVICES_DIRECTORY); + return extensionClasses; + } + + private void loadDirectory(Map> extensionClasses, String dir) { + String fileName = dir + type.getName(); + try { + Enumeration urls; + ClassLoader classLoader = findClassLoader(); + if (classLoader != null) { + urls = classLoader.getResources(fileName); + } else { + urls = ClassLoader.getSystemResources(fileName); + } + if (urls != null) { + while (urls.hasMoreElements()) { + java.net.URL resourceURL = urls.nextElement(); + loadResource(extensionClasses, classLoader, resourceURL); + } + } + } catch (Throwable t) { + logger.error("Exception when load extension class(interface: " + type + + ", description file: " + fileName + ").", t); + } + } + + private void loadResource(Map> extensionClasses, ClassLoader classLoader, + java.net.URL resourceURL) { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader( + resourceURL.openStream(), "utf-8")); + try { + String line; + while ((line = reader.readLine()) != null) { + final int ci = line.indexOf('#'); + if (ci >= 0) + line = line.substring(0, ci); + line = line.trim(); + if (line.length() > 0) { + try { + String name = null; + int i = line.indexOf('='); + if (i > 0) { + name = line.substring(0, i).trim(); + line = line.substring(i + 1).trim(); + } + if (line.length() > 0) { + loadClass(extensionClasses, resourceURL, + Class.forName(line, true, classLoader), name); + } + } catch (Throwable t) { + IllegalStateException e = new IllegalStateException( + "Failed to load extension class(interface: " + type + + ", class line: " + line + ") in " + resourceURL + + ", cause: " + t.getMessage(), t); + exceptions.put(line, e); + } + } + } + } finally { + reader.close(); + } + } catch (Throwable t) { + logger.error("Exception when load extension class(interface: " + type + + ", class file: " + resourceURL + ") in " + resourceURL, t); + } + } + + private void loadClass(Map> extensionClasses, java.net.URL resourceURL, + Class clazz, String name) throws NoSuchMethodException { + if (!type.isAssignableFrom(clazz)) { + throw new IllegalStateException("Error when load extension class(interface: " + type + + ", class line: " + clazz.getName() + "), class " + + clazz.getName() + "is not subtype of interface."); + } + if (clazz.isAnnotationPresent(Adaptive.class)) { + if (cachedAdaptiveClass == null) { + cachedAdaptiveClass = clazz; + } else if (!cachedAdaptiveClass.equals(clazz)) { + throw new IllegalStateException("More than 1 adaptive class found: " + + cachedAdaptiveClass.getClass().getName() + ", " + + clazz.getClass().getName()); + } + } else if (isWrapperClass(clazz)) { + Set> wrappers = cachedWrapperClasses; + if (wrappers == null) { + cachedWrapperClasses = new ConcurrentHashSet>(); + wrappers = cachedWrapperClasses; + } + wrappers.add(clazz); + } else { + clazz.getConstructor(); + if (name == null || name.length() == 0) { + name = findAnnotationName(clazz); + if (name.length() == 0) { + throw new IllegalStateException("No such extension name for the class " + + clazz.getName() + " in the config " + + resourceURL); + } + } + String[] names = NAME_SEPARATOR.split(name); + if (names != null && names.length > 0) { + Activate activate = clazz.getAnnotation(Activate.class); + if (activate != null) { + cachedActivates.put(names[0], activate); + } + for (String n : names) { + if (!cachedNames.containsKey(clazz)) { + cachedNames.put(clazz, n); + } + Class c = extensionClasses.get(n); + if (c == null) { + extensionClasses.put(n, clazz); + } else if (c != clazz) { + throw new IllegalStateException("Duplicate extension " + type.getName() + + " name " + n + " on " + c.getName() + + " and " + clazz.getName()); + } + } + } + } + } + + private boolean isWrapperClass(Class clazz) { + try { + clazz.getConstructor(type); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + @SuppressWarnings("deprecation") + private String findAnnotationName(Class clazz) { + com.alibaba.dubbo.common.Extension extension = clazz + .getAnnotation(com.alibaba.dubbo.common.Extension.class); + if (extension == null) { + String name = clazz.getSimpleName(); + if (name.endsWith(type.getSimpleName())) { + name = name.substring(0, name.length() - type.getSimpleName().length()); + } + return name.toLowerCase(); + } + return extension.value(); + } + + @SuppressWarnings("unchecked") + private T createAdaptiveExtension() { + try { + return injectExtension((T) getAdaptiveExtensionClass().newInstance()); + } catch (Exception e) { + throw new IllegalStateException("Can not create adaptive extension " + type + + ", cause: " + e.getMessage(), e); + } + } + + private Class getAdaptiveExtensionClass() { + getExtensionClasses(); + if (cachedAdaptiveClass != null) { + return cachedAdaptiveClass; + } + return cachedAdaptiveClass = createAdaptiveExtensionClass(); + } + + private Class createAdaptiveExtensionClass() { + String code = createAdaptiveExtensionClassCode(); + ClassLoader classLoader = findClassLoader(); + com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader( + com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); + return compiler.compile(code, classLoader); + } + + private String createAdaptiveExtensionClassCode() { + StringBuilder codeBuilder = new StringBuilder(); + Method[] methods = type.getMethods(); + boolean hasAdaptiveAnnotation = false; + for (Method m : methods) { + if (m.isAnnotationPresent(Adaptive.class)) { + hasAdaptiveAnnotation = true; + break; + } + } + // no need to generate adaptive class since there's no adaptive method found. + if (!hasAdaptiveAnnotation) + throw new IllegalStateException("No adaptive method on extension " + type.getName() + + ", refuse to create the adaptive class!"); + + codeBuilder.append("package ").append(type.getPackage().getName()).append(";"); + codeBuilder.append("\nimport ").append(ExtensionLoader.class.getName()).append(";"); + codeBuilder.append("\npublic class ").append(type.getSimpleName()).append("$Adaptive") + .append(" implements ").append(type.getCanonicalName()).append(" {"); + + for (Method method : methods) { + Class rt = method.getReturnType(); + Class[] pts = method.getParameterTypes(); + Class[] ets = method.getExceptionTypes(); + + Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class); + StringBuilder code = new StringBuilder(512); + if (adaptiveAnnotation == null) { + code.append("throw new UnsupportedOperationException(\"method ") + .append(method.toString()).append(" of interface ").append(type.getName()) + .append(" is not adaptive method!\");"); + } else { + int urlTypeIndex = -1; + for (int i = 0; i < pts.length; ++i) { + if (pts[i].equals(URL.class)) { + urlTypeIndex = i; + break; + } + } + // found parameter in URL type + if (urlTypeIndex != -1) { + // Null Point check + String s = String + .format( + "\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");", + urlTypeIndex); + code.append(s); + + s = String.format("\n%s url = arg%d;", URL.class.getName(), urlTypeIndex); + code.append(s); + } + // did not find parameter in URL type + else { + String attribMethod = null; + + // find URL getter method + LBL_PTS: for (int i = 0; i < pts.length; ++i) { + Method[] ms = pts[i].getMethods(); + for (Method m : ms) { + String name = m.getName(); + if ((name.startsWith("get") || name.length() > 3) + && Modifier.isPublic(m.getModifiers()) + && !Modifier.isStatic(m.getModifiers()) + && m.getParameterTypes().length == 0 + && m.getReturnType() == URL.class) { + urlTypeIndex = i; + attribMethod = name; + break LBL_PTS; + } + } + } + if (attribMethod == null) { + throw new IllegalStateException( + "fail to create adaptive class for interface " + + type.getName() + + ": not found url parameter or url attribute in parameters of method " + + method.getName()); + } + + // Null point check + String s = String + .format( + "\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");", + urlTypeIndex, pts[urlTypeIndex].getName()); + code.append(s); + s = String + .format( + "\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");", + urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod); + code.append(s); + + s = String.format("%s url = arg%d.%s();", URL.class.getName(), urlTypeIndex, + attribMethod); + code.append(s); + } + + String[] value = adaptiveAnnotation.value(); + // value is not set, use the value generated from class name as the key + if (value.length == 0) { + char[] charArray = type.getSimpleName().toCharArray(); + StringBuilder sb = new StringBuilder(128); + for (int i = 0; i < charArray.length; i++) { + if (Character.isUpperCase(charArray[i])) { + if (i != 0) { + sb.append("."); + } + sb.append(Character.toLowerCase(charArray[i])); + } else { + sb.append(charArray[i]); + } + } + value = new String[] { sb.toString() }; + } + + boolean hasInvocation = false; + for (int i = 0; i < pts.length; ++i) { + if (pts[i].getName().equals("com.alibaba.dubbo.rpc.Invocation")) { + // Null Point check + String s = String + .format( + "\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", + i); + code.append(s); + s = String.format("\nString methodName = arg%d.getMethodName();", i); + code.append(s); + hasInvocation = true; + break; + } + } + + String defaultExtName = cachedDefaultName; + String getNameCode = null; + for (int i = value.length - 1; i >= 0; --i) { + if (i == value.length - 1) { + if (null != defaultExtName) { + if (!"protocol".equals(value[i])) + if (hasInvocation) + getNameCode = String.format( + "url.getMethodParameter(methodName, \"%s\", \"%s\")", + value[i], defaultExtName); + else + getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", + value[i], defaultExtName); + else + getNameCode = String.format( + "( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", + defaultExtName); + } else { + if (!"protocol".equals(value[i])) + if (hasInvocation) + getNameCode = String.format( + "url.getMethodParameter(methodName, \"%s\", \"%s\")", + value[i], defaultExtName); + else + getNameCode = String.format("url.getParameter(\"%s\")", + value[i]); + else + getNameCode = "url.getProtocol()"; + } + } else { + if (!"protocol".equals(value[i])) + if (hasInvocation) + getNameCode = String.format( + "url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], + defaultExtName); + else + getNameCode = String.format("url.getParameter(\"%s\", %s)", + value[i], getNameCode); + else + getNameCode = String + .format("url.getProtocol() == null ? (%s) : url.getProtocol()", + getNameCode); + } + } + code.append("\nString extName = ").append(getNameCode).append(";"); + // check extName == null? + String s = String + .format( + "\nif(extName == null) " + + "throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");", + type.getName(), Arrays.toString(value)); + code.append(s); + + s = String.format( + "\n%s extension = (% 0) { + codeBuilder.append(", "); + } + codeBuilder.append(pts[i].getCanonicalName()); + codeBuilder.append(" "); + codeBuilder.append("arg").append(i); + } + codeBuilder.append(")"); + if (ets.length > 0) { + codeBuilder.append(" throws "); + for (int i = 0; i < ets.length; i++) { + if (i > 0) { + codeBuilder.append(", "); + } + codeBuilder.append(ets[i].getCanonicalName()); + } + } + codeBuilder.append(" {"); + codeBuilder.append(code.toString()); + codeBuilder.append("\n}"); + } + codeBuilder.append("\n}"); + if (logger.isDebugEnabled()) { + logger.debug(codeBuilder.toString()); + } + return codeBuilder.toString(); + } + + @Override + public String toString() { + return this.getClass().getName() + "[" + type.getName() + "]"; + } + +} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java new file mode 100644 index 000000000..4cc4671f4 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java @@ -0,0 +1,83 @@ +/* + * 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 com.alibaba.dubbo.common.serialize.java; + +import com.alibaba.dubbo.common.serialize.nativejava.NativeJavaObjectInput; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.lang.reflect.Type; + +public class ClassLoaderJavaObjectInput extends NativeJavaObjectInput { + public final static int MAX_BYTE_ARRAY_LENGTH = 8 * 1024 * 1024; + + public ClassLoaderJavaObjectInput(InputStream is) throws IOException { + super( + (ObjectInputStream) (is instanceof ObjectInputStream ? is : new ObjectInputStream(is))); + } + + @Override + public byte[] readBytes() throws IOException { + int len = getObjectInputStream().readInt(); + if (len < 0) + return null; + if (len == 0) + return new byte[0]; + if (len > MAX_BYTE_ARRAY_LENGTH) + throw new IOException("Byte array length too large. " + len); + + byte[] b = new byte[len]; + getObjectInputStream().readFully(b); + return b; + } + + @Override + public String readUTF() throws IOException { + int len = getObjectInputStream().readInt(); + if (len < 0) + return null; + + return getObjectInputStream().readUTF(); + } + + @Override + public Object readObject() throws IOException, ClassNotFoundException { + byte b = getObjectInputStream().readByte(); + if (b == 0) + return null; + + return getObjectInputStream().readObject(); + } + + @Override + @SuppressWarnings("unchecked") + public T readObject(Class cls) throws IOException, ClassNotFoundException { + return (T) readObject(); + } + + @Override + @SuppressWarnings("unchecked") + public T readObject(Class 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.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java new file mode 100644 index 000000000..2220b97ee --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java @@ -0,0 +1,98 @@ +/* + * 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 com.alibaba.dubbo.common.serialize.java; + +import java.io.*; +import java.lang.reflect.Proxy; + +public class ClassLoaderObjectInputStream extends ObjectInputStream { + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * The class loader to use. + */ + 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); + } + } + +} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java new file mode 100644 index 000000000..91581b508 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java @@ -0,0 +1,54 @@ +/* + * 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 com.alibaba.dubbo.common.serialize.java; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.Serialization; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * @author syd + * @version ClassLoaderJavaSerialization.java, v 0.1 2023年10月28日 19:18 syd + */ +public class JavaSerialization implements Serialization { + + @Override + public byte getContentTypeId() { + return 3; + } + + @Override + public String getContentType() { + return "x-application/java"; + } + + @Override + public ObjectOutput serialize(URL url, OutputStream output) throws IOException { + return new JavaObjectOutput(output); + } + + @Override + public ObjectInput deserialize(URL url, InputStream is) throws IOException { + return new ClassLoaderJavaObjectInput(new ClassLoaderObjectInputStream(null, is)); + } + +} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java new file mode 100644 index 000000000..9338931f0 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.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 com.alibaba.dubbo.config.model; + +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import com.alibaba.dubbo.rpc.Invoker; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +// TODO need to adjust project structure in order to fully utilize the methods introduced here. +public class ApplicationModel { + + protected static final Logger logger = LoggerFactory + .getLogger(ApplicationModel.class); + + /** + * full qualified class name -> provided service + */ + private static final ConcurrentMap providedServices = new ConcurrentHashMap(); + /** + * full qualified class name -> subscribe service + */ + private static final ConcurrentMap consumedServices = new ConcurrentHashMap(); + + public static final ConcurrentMap> providedServicesInvoker = new ConcurrentHashMap>(); + + public static List allConsumerModels() { + return new ArrayList(consumedServices.values()); + } + + public static ProviderModel getProviderModel(String serviceName) { + return providedServices.get(serviceName); + } + + public static ConsumerModel getConsumerModel(String serviceName) { + return consumedServices.get(serviceName); + } + + public static List allProviderModels() { + return new ArrayList(providedServices.values()); + } + + public static boolean initConsumerModel(String serviceName, ConsumerModel consumerModel) { + if (consumedServices + .putIfAbsent( + getConsumerModelKey(serviceName, consumerModel.getMetadata().getApplication() + .getName()), consumerModel) != null) { + logger.warn("Already register the same consumer:" + serviceName); + return false; + } + return true; + } + + public static String getConsumerModelKey(String serviceName, String applicationName) { + return applicationName + ":" + serviceName; + } + + public static void initProviderModel(String serviceName, ProviderModel providerModel) { + if (providedServices.put(serviceName, providerModel) != null) { + logger.warn("already register the provider service: " + serviceName); + return; + } + } + + public static void addProviderInvoker(String serviceName, Invoker invoker) { + Set invokers = providedServicesInvoker.get(serviceName); + if (invokers == null) { + providedServicesInvoker.putIfAbsent(serviceName, new ConcurrentHashSet()); + invokers = providedServicesInvoker.get(serviceName); + } + invokers.add(invoker); + } + + public Set getProviderInvoker(String serviceName) { + Set invokers = providedServicesInvoker.get(serviceName); + if (invokers == null) { + return Collections.emptySet(); + } + return invokers; + } +} diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java new file mode 100644 index 000000000..5d58227e2 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java @@ -0,0 +1,107 @@ +/* + * 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 com.alibaba.dubbo.config.spring.extension; + +import com.alibaba.dubbo.common.extension.ExtensionFactory; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.ApplicationContext; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * SpringExtensionFactory + */ +public class SpringExtensionFactory implements ExtensionFactory { + private static final Logger logger = LoggerFactory + .getLogger(SpringExtensionFactory.class); + + private static final Map> contextsWithClassLoader = new ConcurrentHashMap<>(); + + public static void addApplicationContext(ApplicationContext context) { + getContexts().add(context); + } + + public static void removeApplicationContext(ApplicationContext context) { + getContexts().remove(context); + } + + // currently for test purpose + public static void clearContexts() { + + getContexts().clear(); + } + + @Override + @SuppressWarnings("unchecked") + public T getExtension(Class type, String name) { + for (ApplicationContext context : getContexts()) { + if (context.containsBean(name)) { + Object bean = context.getBean(name); + if (type.isInstance(bean)) { + return (T) bean; + } + } + } + + logger.warn("No spring extension(bean) named:" + name + + ", try to find an extension(bean) of type " + type.getName()); + + for (ApplicationContext context : getContexts()) { + try { + return context.getBean(type); + } catch (NoUniqueBeanDefinitionException multiBeanExe) { + throw multiBeanExe; + } catch (NoSuchBeanDefinitionException noBeanExe) { + if (logger.isDebugEnabled()) { + logger.debug( + "Error when get spring extension(bean) for type:" + type.getName(), + noBeanExe); + } + } + } + + logger.warn("No spring extension(bean) named:" + name + ", type:" + type.getName() + + " found, stop get bean."); + + return null; + } + + private static ClassLoader findClassLoader() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader != null) + return classLoader; + return SpringExtensionFactory.class.getClassLoader(); + } + + private static Set getContexts() { + ClassLoader classLoader = findClassLoader(); + Set contexts = null; + if ((contexts = contextsWithClassLoader.get(classLoader)) == null) { + contextsWithClassLoader.put(classLoader, new ConcurrentHashSet<>()); + contexts = contextsWithClassLoader.get(classLoader); + } + ; + return contexts; + } + +} diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java new file mode 100644 index 000000000..f7ec2818e --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java @@ -0,0 +1,160 @@ +/* + * 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 com.alibaba.dubbo.rpc.protocol.dubbo; + +import com.alibaba.dubbo.common.ClassLoaderUtil; +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.serialize.Cleanable; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.java.ClassLoaderJavaObjectInput; +import com.alibaba.dubbo.common.serialize.java.ClassLoaderObjectInputStream; +import com.alibaba.dubbo.common.utils.Assert; +import com.alibaba.dubbo.common.utils.ReflectUtils; +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.remoting.Channel; +import com.alibaba.dubbo.remoting.Codec; +import com.alibaba.dubbo.remoting.Decodeable; +import com.alibaba.dubbo.remoting.exchange.Request; +import com.alibaba.dubbo.remoting.transport.CodecSupport; +import com.alibaba.dubbo.rpc.RpcInvocation; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import static com.alibaba.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(); + } + + @Override + public Object decode(Channel channel, InputStream input) throws IOException { + //注意 channel的url不具有唯一性 实际上使用以inputstream的path为准 + ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) + .deserialize(channel.getUrl(), input); + + String dubboVersion = in.readUTF(); + request.setVersion(dubboVersion); + setAttachment(Constants.DUBBO_VERSION_KEY, dubboVersion); + String path = in.readUTF(); + setAttachment(Constants.PATH_KEY, path); + if (in instanceof ClassLoaderJavaObjectInput) { + InputStream is = ((ClassLoaderJavaObjectInput) in).getInputStream(); + if (is instanceof ClassLoaderObjectInputStream) { + ClassLoader cl = ClassLoaderUtil.getClassLoaderByPath(path); + ((ClassLoaderObjectInputStream) is).setClassLoader(cl); + } + } + setAttachment(Constants.VERSION_KEY, in.readUTF()); + + setMethodName(in.readUTF()); + try { + Object[] args; + Class[] pts; + String desc = in.readUTF(); + if (desc.length() == 0) { + pts = DubboCodec.EMPTY_CLASS_ARRAY; + args = DubboCodec.EMPTY_OBJECT_ARRAY; + } else { + pts = ReflectUtils.desc2classArray(desc); + 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 = (Map) in.readObject(Map.class); + if (map != null && map.size() > 0) { + Map attachment = getAttachments(); + if (attachment == null) { + attachment = new HashMap(); + } + attachment.putAll(map); + setAttachments(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); + + } 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.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java new file mode 100644 index 000000000..459d81e81 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java @@ -0,0 +1,174 @@ +/* + * 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 com.alibaba.dubbo.rpc.protocol.dubbo; + +import com.alibaba.dubbo.common.ClassLoaderUtil; +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.serialize.Cleanable; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.java.ClassLoaderJavaObjectInput; +import com.alibaba.dubbo.common.serialize.java.ClassLoaderObjectInputStream; +import com.alibaba.dubbo.common.utils.Assert; +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.remoting.Channel; +import com.alibaba.dubbo.remoting.Codec; +import com.alibaba.dubbo.remoting.Decodeable; +import com.alibaba.dubbo.remoting.exchange.Response; +import com.alibaba.dubbo.remoting.transport.CodecSupport; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.RpcResult; +import com.alibaba.dubbo.rpc.support.RpcUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Type; +import java.util.Map; + +public class DecodeableRpcResult extends RpcResult 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 { + ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) + .deserialize(channel.getUrl(), input); + //表示应用的来源 + String application = channel.getUrl().getParameter(Constants.APPLICATION_KEY); + String serviceName = channel.getUrl().getServiceKey(); + ClassLoader cl = ClassLoaderUtil.getClassLoaderByServiceNameAndApplication(serviceName, + application); + Thread.currentThread().setContextClassLoader(cl); + if (in instanceof ClassLoaderJavaObjectInput) { + InputStream is = ((ClassLoaderJavaObjectInput) in).getInputStream(); + if (is instanceof ClassLoaderObjectInputStream) { + ((ClassLoaderObjectInputStream) is).setClassLoader(cl); + } + } + byte flag = in.readByte(); + switch (flag) { + case DubboCodec.RESPONSE_NULL_VALUE: + break; + case DubboCodec.RESPONSE_VALUE: + try { + Type[] returnType = RpcUtils.getReturnTypes(invocation); + setValue(returnType == null || returnType.length == 0 ? in.readObject() + : (returnType.length == 1 ? in.readObject((Class) returnType[0]) : in + .readObject((Class) returnType[0], returnType[1]))); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read response data failed.", e)); + } + break; + case DubboCodec.RESPONSE_WITH_EXCEPTION: + try { + Object obj = in.readObject(); + if (obj instanceof Throwable == false) + throw new IOException("Response data error, expect Throwable, but get " + + obj); + setException((Throwable) obj); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read response data failed.", e)); + } + break; + case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS: + try { + setAttachments((Map) in.readObject(Map.class)); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read response data failed.", e)); + } + break; + case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS: + try { + Type[] returnType = RpcUtils.getReturnTypes(invocation); + setValue(returnType == null || returnType.length == 0 ? in.readObject() + : (returnType.length == 1 ? in.readObject((Class) returnType[0]) : in + .readObject((Class) returnType[0], returnType[1]))); + setAttachments((Map) in.readObject(Map.class)); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read response data failed.", e)); + } + break; + case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS: + try { + Object obj = in.readObject(); + if (obj instanceof Throwable == false) + throw new IOException("Response data error, expect Throwable, but get " + + obj); + setException((Throwable) obj); + setAttachments((Map) in.readObject(Map.class)); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read response data failed.", e)); + } + break; + default: + throw new IOException("Unknown result flag, expect '0' '1' '2', get " + flag); + } + if (in instanceof Cleanable) { + ((Cleanable) in).cleanup(); + } + return this; + } + + @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 result failed: " + e.getMessage(), e); + } + response.setStatus(Response.CLIENT_ERROR); + response.setErrorMessage(StringUtils.toString(e)); + } finally { + hasDecoded = true; + } + } + } + +} From 6403e0d141a68815bcf48e7b413f039c785ddc55 Mon Sep 17 00:00:00 2001 From: qixiaobo Date: Fri, 10 Nov 2023 12:34:18 +0800 Subject: [PATCH 5/5] Revert "feat(ark-serverless): support dubbo 2.6" This reverts commit 1c1bb05f9dd9847a94091e3b7501bebb9c5e7c10. --- .../sofa-serverless-adapter-ext/pom.xml | 1 - .../sofa-serverless-adapter-dubbo2.6/pom.xml | 23 - .../alibaba/dubbo/common/ClassLoaderUtil.java | 89 -- .../common/extension/ExtensionLoader.java | 1028 ----------------- .../java/ClassLoaderJavaObjectInput.java | 83 -- .../java/ClassLoaderObjectInputStream.java | 98 -- .../serialize/java/JavaSerialization.java | 54 - .../dubbo/config/model/ApplicationModel.java | 102 -- .../extension/SpringExtensionFactory.java | 107 -- .../dubbo/DecodeableRpcInvocation.java | 160 --- .../protocol/dubbo/DecodeableRpcResult.java | 174 --- 11 files changed, 1919 deletions(-) delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java delete mode 100644 sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml b/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml index d9fd7776d..2307f769d 100644 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml +++ b/sofa-serverless-runtime/sofa-serverless-adapter-ext/pom.xml @@ -13,6 +13,5 @@ pom sofa-serverless-adapter-log4j2 - sofa-serverless-adapter-dubbo2.6 diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml deleted file mode 100644 index d8244fb2b..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - 4.0.0 - - com.alipay.sofa.serverless - sofa-serverless-adapter-ext - ${revision} - ../pom.xml - - sofa-serverless-adapter-dubbo2.6 - ${revision} - - - - com.alibaba - dubbo - 2.6.12 - - - - \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java deleted file mode 100644 index e1cc41b54..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/ClassLoaderUtil.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 com.alibaba.dubbo.common; - -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.config.model.ApplicationModel; -import com.alibaba.dubbo.config.model.ConsumerModel; -import com.alibaba.dubbo.config.model.ProviderModel; -import com.alibaba.dubbo.config.spring.ReferenceBean; -import com.alibaba.dubbo.config.spring.ServiceBean; -import org.springframework.context.ApplicationContext; - -import java.lang.reflect.Field; - -public class ClassLoaderUtil { - static Field serviceBeanApplicationContextField; - static Field referenceBeanApplicationContextField; - private static final Logger log = LoggerFactory.getLogger(ClassLoaderUtil.class); - - static { - try { - serviceBeanApplicationContextField = ServiceBean.class - .getDeclaredField("applicationContext"); - serviceBeanApplicationContextField.setAccessible(true); - referenceBeanApplicationContextField = ReferenceBean.class - .getDeclaredField("applicationContext"); - referenceBeanApplicationContextField.setAccessible(true); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - - public static ClassLoader getClassLoaderByPath(String path) { - ProviderModel providerModel = null; - for (ProviderModel iter : ApplicationModel.allProviderModels()) { - if (iter.getServiceName().contains(path)) { - providerModel = iter; - break; - } - } - if (providerModel == null) { - log.warn("can not find classloader by path:" + path); - return ClassLoader.getSystemClassLoader(); - } - ServiceBean serviceBean = (ServiceBean) providerModel.getMetadata(); - try { - ApplicationContext applicationContext = (ApplicationContext) serviceBeanApplicationContextField - .get(serviceBean); - ClassLoader classLoader = applicationContext.getClassLoader(); - Thread.currentThread().setContextClassLoader(classLoader); - return classLoader; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static ClassLoader getClassLoaderByServiceNameAndApplication(String serviceName, - String application) { - ConsumerModel consumerModel = ApplicationModel.getConsumerModel(ApplicationModel - .getConsumerModelKey(serviceName, application)); - if (consumerModel == null) - return ClassLoader.getSystemClassLoader(); - ReferenceBean referenceBean = (ReferenceBean) consumerModel.getMetadata(); - try { - ApplicationContext applicationContext = (ApplicationContext) referenceBeanApplicationContextField - .get(referenceBean); - ClassLoader classLoader = applicationContext.getClassLoader(); - Thread.currentThread().setContextClassLoader(classLoader); - return classLoader; - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java deleted file mode 100644 index 2165fa14c..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * 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 com.alibaba.dubbo.common.extension; - -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.common.extension.support.ActivateComparator; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.utils.ConcurrentHashSet; -import com.alibaba.dubbo.common.utils.ConfigUtils; -import com.alibaba.dubbo.common.utils.Holder; -import com.alibaba.dubbo.common.utils.StringUtils; -import com.alibaba.dubbo.rpc.Protocol; -import com.alibaba.dubbo.rpc.ProxyFactory; -import com.alibaba.dubbo.rpc.cluster.Cluster; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Pattern; - -/** - * Load dubbo extensions - *
    - *
  • auto inject dependency extension
  • - *
  • auto wrap extension in wrapper
  • - *
  • default extension is an adaptive instance
  • - *
- * - * @see Service Provider in Java 5 - * @see SPI - * @see Adaptive - * @see Activate - */ -public class ExtensionLoader { - - private static final Logger logger = LoggerFactory - .getLogger(ExtensionLoader.class); - - private static final String SERVICES_DIRECTORY = "META-INF/services/"; - - private static final String DUBBO_DIRECTORY = "META-INF/dubbo/"; - - private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY - + "internal/"; - - private static final Pattern NAME_SEPARATOR = Pattern - .compile("\\s*[,]+\\s*"); - - private static final ConcurrentMap, ExtensionLoader> EXTENSION_LOADERS = new ConcurrentHashMap<>(); - private static final ConcurrentMap, ExtensionLoader>> EXTENSION_LOADERS_SUPPORT_CLASSLOADER = new ConcurrentHashMap<>(); - - static { - EXTENSION_LOADERS_SUPPORT_CLASSLOADER.put(findClassLoader(), EXTENSION_LOADERS); - } - - private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap, Object>(); - - // ============================== - - private final Class type; - - private final ExtensionFactory objectFactory; - - private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap, String>(); - - private final Holder>> cachedClasses = new Holder>>(); - - private final Map cachedActivates = new ConcurrentHashMap(); - private final ConcurrentMap> cachedInstances = new ConcurrentHashMap>(); - private final Holder cachedAdaptiveInstance = new Holder(); - private volatile Class cachedAdaptiveClass = null; - private String cachedDefaultName; - private volatile Throwable createAdaptiveInstanceError; - - private Set> cachedWrapperClasses; - - private Map exceptions = new ConcurrentHashMap(); - - private ExtensionLoader(Class type) { - this.type = type; - objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader - .getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); - } - - private static boolean withExtensionAnnotation(Class type) { - return type.isAnnotationPresent(SPI.class); - } - - @SuppressWarnings("unchecked") - public static ExtensionLoader getExtensionLoader(Class type) { - if (type == null) - throw new IllegalArgumentException("Extension type == null"); - if (!type.isInterface()) { - throw new IllegalArgumentException("Extension type(" + type + ") is not interface!"); - } - if (!withExtensionAnnotation(type)) { - throw new IllegalArgumentException("Extension type(" + type - + ") is not extension, because WITHOUT @" - + SPI.class.getSimpleName() + " Annotation!"); - } - ClassLoader classLoader = findClassLoader(); - ConcurrentMap, ExtensionLoader> classExtensionLoaderConcurrentMap = EXTENSION_LOADERS_SUPPORT_CLASSLOADER - .get(classLoader); - if (classExtensionLoaderConcurrentMap == null) { - EXTENSION_LOADERS_SUPPORT_CLASSLOADER.putIfAbsent(classLoader, - new ConcurrentHashMap<>()); - classExtensionLoaderConcurrentMap = EXTENSION_LOADERS_SUPPORT_CLASSLOADER - .get(classLoader); - //TO avoid static init only once like ReferenceConfig - ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); - - ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension(); - - ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - } - // - ExtensionLoader loader = (ExtensionLoader) classExtensionLoaderConcurrentMap - .get(type); - if (loader == null) { - classExtensionLoaderConcurrentMap.putIfAbsent(type, new ExtensionLoader(type)); - loader = (ExtensionLoader) classExtensionLoaderConcurrentMap.get(type); - } - return loader; - } - - private static ClassLoader findClassLoader() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader != null) - return classLoader; - return ExtensionLoader.class.getClassLoader(); - } - - public String getExtensionName(T extensionInstance) { - return getExtensionName(extensionInstance.getClass()); - } - - public String getExtensionName(Class extensionClass) { - return cachedNames.get(extensionClass); - } - - /** - * This is equivalent to {@code getActivateExtension(url, key, null)} - * - * @param url url - * @param key url parameter key which used to get extension point names - * @return extension list which are activated. - * @see #getActivateExtension(URL, String, String) - */ - public List getActivateExtension(URL url, String key) { - return getActivateExtension(url, key, null); - } - - /** - * This is equivalent to {@code getActivateExtension(url, values, null)} - * - * @param url url - * @param values extension point names - * @return extension list which are activated - * @see #getActivateExtension(URL, String[], String) - */ - public List getActivateExtension(URL url, String[] values) { - return getActivateExtension(url, values, null); - } - - /** - * This is equivalent to {@code getActivateExtension(url, url.getParameter(key).split(","), null)} - * - * @param url url - * @param key url parameter key which used to get extension point names - * @param group group - * @return extension list which are activated. - * @see #getActivateExtension(URL, String[], String) - */ - public List getActivateExtension(URL url, String key, String group) { - String value = url.getParameter(key); - return getActivateExtension(url, value == null || value.length() == 0 ? null - : Constants.COMMA_SPLIT_PATTERN.split(value), group); - } - - /** - * Get activate extensions. - * - * @param url url - * @param values extension point names - * @param group group - * @return extension list which are activated - * @see Activate - */ - public List getActivateExtension(URL url, String[] values, String group) { - List exts = new ArrayList(); - List names = values == null ? new ArrayList(0) : Arrays.asList(values); - if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { - getExtensionClasses(); - for (Map.Entry entry : cachedActivates.entrySet()) { - String name = entry.getKey(); - Activate activate = entry.getValue(); - if (isMatchGroup(group, activate.group())) { - T ext = getExtension(name); - if (!names.contains(name) - && !names.contains(Constants.REMOVE_VALUE_PREFIX + name) - && isActive(activate, url)) { - exts.add(ext); - } - } - } - Collections.sort(exts, ActivateComparator.COMPARATOR); - } - List usrs = new ArrayList(); - for (int i = 0; i < names.size(); i++) { - String name = names.get(i); - if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX) - && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) { - if (Constants.DEFAULT_KEY.equals(name)) { - if (!usrs.isEmpty()) { - exts.addAll(0, usrs); - usrs.clear(); - } - } else { - T ext = getExtension(name); - usrs.add(ext); - } - } - } - if (!usrs.isEmpty()) { - exts.addAll(usrs); - } - return exts; - } - - private boolean isMatchGroup(String group, String[] groups) { - if (group == null || group.length() == 0) { - return true; - } - if (groups != null && groups.length > 0) { - for (String g : groups) { - if (group.equals(g)) { - return true; - } - } - } - return false; - } - - private boolean isActive(Activate activate, URL url) { - String[] keys = activate.value(); - if (keys.length == 0) { - return true; - } - for (String key : keys) { - for (Map.Entry entry : url.getParameters().entrySet()) { - String k = entry.getKey(); - String v = entry.getValue(); - if ((k.equals(key) || k.endsWith("." + key)) && ConfigUtils.isNotEmpty(v)) { - return true; - } - } - } - return false; - } - - /** - * Get extension's instance. Return null if extension is not found or is not initialized. Pls. note - * that this method will not trigger extension load. - *

- * In order to trigger extension load, call {@link #getExtension(String)} instead. - * - * @see #getExtension(String) - */ - @SuppressWarnings("unchecked") - public T getLoadedExtension(String name) { - if (name == null || name.length() == 0) - throw new IllegalArgumentException("Extension name == null"); - Holder holder = cachedInstances.get(name); - if (holder == null) { - cachedInstances.putIfAbsent(name, new Holder()); - holder = cachedInstances.get(name); - } - return (T) holder.get(); - } - - /** - * Return the list of extensions which are already loaded. - *

- * Usually {@link #getSupportedExtensions()} should be called in order to get all extensions. - * - * @see #getSupportedExtensions() - */ - public Set getLoadedExtensions() { - return Collections.unmodifiableSet(new TreeSet(cachedInstances.keySet())); - } - - /** - * Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException} - * will be thrown. - */ - @SuppressWarnings("unchecked") - public T getExtension(String name) { - if (name == null || name.length() == 0) - throw new IllegalArgumentException("Extension name == null"); - if ("true".equals(name)) { - return getDefaultExtension(); - } - Holder holder = cachedInstances.get(name); - if (holder == null) { - cachedInstances.putIfAbsent(name, new Holder()); - holder = cachedInstances.get(name); - } - Object instance = holder.get(); - if (instance == null) { - synchronized (holder) { - instance = holder.get(); - if (instance == null) { - instance = createExtension(name); - holder.set(instance); - } - } - } - return (T) instance; - } - - /** - * Return default extension, return null if it's not configured. - */ - public T getDefaultExtension() { - getExtensionClasses(); - if (null == cachedDefaultName || cachedDefaultName.length() == 0 - || "true".equals(cachedDefaultName)) { - return null; - } - return getExtension(cachedDefaultName); - } - - public boolean hasExtension(String name) { - if (name == null || name.length() == 0) - throw new IllegalArgumentException("Extension name == null"); - try { - this.getExtensionClass(name); - return true; - } catch (Throwable t) { - return false; - } - } - - public Set getSupportedExtensions() { - Map> clazzes = getExtensionClasses(); - return Collections.unmodifiableSet(new TreeSet(clazzes.keySet())); - } - - /** - * Return default extension name, return null if not configured. - */ - public String getDefaultExtensionName() { - getExtensionClasses(); - return cachedDefaultName; - } - - /** - * Register new extension via API - * - * @param name extension name - * @param clazz extension class - * @throws IllegalStateException when extension with the same name has already been registered. - */ - public void addExtension(String name, Class clazz) { - getExtensionClasses(); // load classes - - if (!type.isAssignableFrom(clazz)) { - throw new IllegalStateException("Input type " + clazz + "not implement Extension " - + type); - } - if (clazz.isInterface()) { - throw new IllegalStateException("Input type " + clazz + "can not be interface!"); - } - - if (!clazz.isAnnotationPresent(Adaptive.class)) { - if (StringUtils.isBlank(name)) { - throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); - } - if (cachedClasses.get().containsKey(name)) { - throw new IllegalStateException("Extension name " + name - + " already existed(Extension " + type + ")!"); - } - - cachedNames.put(clazz, name); - cachedClasses.get().put(name, clazz); - } else { - if (cachedAdaptiveClass != null) { - throw new IllegalStateException("Adaptive Extension already existed(Extension " - + type + ")!"); - } - - cachedAdaptiveClass = clazz; - } - } - - /** - * Replace the existing extension via API - * - * @param name extension name - * @param clazz extension class - * @throws IllegalStateException when extension to be placed doesn't exist - * @deprecated not recommended any longer, and use only when test - */ - @Deprecated - public void replaceExtension(String name, Class clazz) { - getExtensionClasses(); // load classes - - if (!type.isAssignableFrom(clazz)) { - throw new IllegalStateException("Input type " + clazz + "not implement Extension " - + type); - } - if (clazz.isInterface()) { - throw new IllegalStateException("Input type " + clazz + "can not be interface!"); - } - - if (!clazz.isAnnotationPresent(Adaptive.class)) { - if (StringUtils.isBlank(name)) { - throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); - } - if (!cachedClasses.get().containsKey(name)) { - throw new IllegalStateException("Extension name " + name - + " not existed(Extension " + type + ")!"); - } - - cachedNames.put(clazz, name); - cachedClasses.get().put(name, clazz); - cachedInstances.remove(name); - } else { - if (cachedAdaptiveClass == null) { - throw new IllegalStateException("Adaptive Extension not existed(Extension " + type - + ")!"); - } - - cachedAdaptiveClass = clazz; - cachedAdaptiveInstance.set(null); - } - } - - @SuppressWarnings("unchecked") - public T getAdaptiveExtension() { - Object instance = cachedAdaptiveInstance.get(); - if (instance == null) { - if (createAdaptiveInstanceError == null) { - synchronized (cachedAdaptiveInstance) { - instance = cachedAdaptiveInstance.get(); - if (instance == null) { - try { - instance = createAdaptiveExtension(); - cachedAdaptiveInstance.set(instance); - } catch (Throwable t) { - createAdaptiveInstanceError = t; - throw new IllegalStateException("fail to create adaptive instance: " - + t.toString(), t); - } - } - } - } else { - throw new IllegalStateException("fail to create adaptive instance: " - + createAdaptiveInstanceError.toString(), - createAdaptiveInstanceError); - } - } - - return (T) instance; - } - - private IllegalStateException findException(String name) { - for (Map.Entry entry : exceptions.entrySet()) { - if (entry.getKey().toLowerCase().contains(name.toLowerCase())) { - return entry.getValue(); - } - } - StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " - + name); - - int i = 1; - for (Map.Entry entry : exceptions.entrySet()) { - if (i == 1) { - buf.append(", possible causes: "); - } - - buf.append("\r\n("); - buf.append(i++); - buf.append(") "); - buf.append(entry.getKey()); - buf.append(":\r\n"); - buf.append(StringUtils.toString(entry.getValue())); - } - return new IllegalStateException(buf.toString()); - } - - @SuppressWarnings("unchecked") - private T createExtension(String name) { - Class clazz = getExtensionClasses().get(name); - if (clazz == null) { - throw findException(name); - } - try { - T instance = (T) EXTENSION_INSTANCES.get(clazz); - if (instance == null) { - EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); - instance = (T) EXTENSION_INSTANCES.get(clazz); - } - injectExtension(instance); - Set> wrapperClasses = cachedWrapperClasses; - if (wrapperClasses != null && !wrapperClasses.isEmpty()) { - for (Class wrapperClass : wrapperClasses) { - instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance( - instance)); - } - } - return instance; - } catch (Throwable t) { - throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type - + ") could not be instantiated: " + t.getMessage(), t); - } - } - - private T injectExtension(T instance) { - try { - if (objectFactory != null) { - for (Method method : instance.getClass().getMethods()) { - if (method.getName().startsWith("set") - && method.getParameterTypes().length == 1 - && Modifier.isPublic(method.getModifiers())) { - Class pt = method.getParameterTypes()[0]; - try { - String property = method.getName().length() > 3 ? method.getName() - .substring(3, 4).toLowerCase() - + method.getName() - .substring(4) - : ""; - Object object = objectFactory.getExtension(pt, property); - if (object != null) { - method.invoke(instance, object); - } - } catch (Exception e) { - logger.error( - "fail to inject via method " + method.getName() + " of interface " - + type.getName() + ": " + e.getMessage(), e); - } - } - } - } - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - return instance; - } - - private Class getExtensionClass(String name) { - if (type == null) - throw new IllegalArgumentException("Extension type == null"); - if (name == null) - throw new IllegalArgumentException("Extension name == null"); - Class clazz = getExtensionClasses().get(name); - if (clazz == null) - throw new IllegalStateException("No such extension \"" + name + "\" for " - + type.getName() + "!"); - return clazz; - } - - private Map> getExtensionClasses() { - Map> classes = cachedClasses.get(); - if (classes == null) { - synchronized (cachedClasses) { - classes = cachedClasses.get(); - if (classes == null) { - classes = loadExtensionClasses(); - cachedClasses.set(classes); - } - } - } - return classes; - } - - // synchronized in getExtensionClasses - private Map> loadExtensionClasses() { - final SPI defaultAnnotation = type.getAnnotation(SPI.class); - if (defaultAnnotation != null) { - String value = defaultAnnotation.value(); - if ((value = value.trim()).length() > 0) { - String[] names = NAME_SEPARATOR.split(value); - if (names.length > 1) { - throw new IllegalStateException( - "more than 1 default extension name on extension " + type.getName() + ": " - + Arrays.toString(names)); - } - if (names.length == 1) - cachedDefaultName = names[0]; - } - } - - Map> extensionClasses = new HashMap>(); - loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY); - loadDirectory(extensionClasses, DUBBO_DIRECTORY); - loadDirectory(extensionClasses, SERVICES_DIRECTORY); - return extensionClasses; - } - - private void loadDirectory(Map> extensionClasses, String dir) { - String fileName = dir + type.getName(); - try { - Enumeration urls; - ClassLoader classLoader = findClassLoader(); - if (classLoader != null) { - urls = classLoader.getResources(fileName); - } else { - urls = ClassLoader.getSystemResources(fileName); - } - if (urls != null) { - while (urls.hasMoreElements()) { - java.net.URL resourceURL = urls.nextElement(); - loadResource(extensionClasses, classLoader, resourceURL); - } - } - } catch (Throwable t) { - logger.error("Exception when load extension class(interface: " + type - + ", description file: " + fileName + ").", t); - } - } - - private void loadResource(Map> extensionClasses, ClassLoader classLoader, - java.net.URL resourceURL) { - try { - BufferedReader reader = new BufferedReader(new InputStreamReader( - resourceURL.openStream(), "utf-8")); - try { - String line; - while ((line = reader.readLine()) != null) { - final int ci = line.indexOf('#'); - if (ci >= 0) - line = line.substring(0, ci); - line = line.trim(); - if (line.length() > 0) { - try { - String name = null; - int i = line.indexOf('='); - if (i > 0) { - name = line.substring(0, i).trim(); - line = line.substring(i + 1).trim(); - } - if (line.length() > 0) { - loadClass(extensionClasses, resourceURL, - Class.forName(line, true, classLoader), name); - } - } catch (Throwable t) { - IllegalStateException e = new IllegalStateException( - "Failed to load extension class(interface: " + type - + ", class line: " + line + ") in " + resourceURL - + ", cause: " + t.getMessage(), t); - exceptions.put(line, e); - } - } - } - } finally { - reader.close(); - } - } catch (Throwable t) { - logger.error("Exception when load extension class(interface: " + type - + ", class file: " + resourceURL + ") in " + resourceURL, t); - } - } - - private void loadClass(Map> extensionClasses, java.net.URL resourceURL, - Class clazz, String name) throws NoSuchMethodException { - if (!type.isAssignableFrom(clazz)) { - throw new IllegalStateException("Error when load extension class(interface: " + type - + ", class line: " + clazz.getName() + "), class " - + clazz.getName() + "is not subtype of interface."); - } - if (clazz.isAnnotationPresent(Adaptive.class)) { - if (cachedAdaptiveClass == null) { - cachedAdaptiveClass = clazz; - } else if (!cachedAdaptiveClass.equals(clazz)) { - throw new IllegalStateException("More than 1 adaptive class found: " - + cachedAdaptiveClass.getClass().getName() + ", " - + clazz.getClass().getName()); - } - } else if (isWrapperClass(clazz)) { - Set> wrappers = cachedWrapperClasses; - if (wrappers == null) { - cachedWrapperClasses = new ConcurrentHashSet>(); - wrappers = cachedWrapperClasses; - } - wrappers.add(clazz); - } else { - clazz.getConstructor(); - if (name == null || name.length() == 0) { - name = findAnnotationName(clazz); - if (name.length() == 0) { - throw new IllegalStateException("No such extension name for the class " - + clazz.getName() + " in the config " - + resourceURL); - } - } - String[] names = NAME_SEPARATOR.split(name); - if (names != null && names.length > 0) { - Activate activate = clazz.getAnnotation(Activate.class); - if (activate != null) { - cachedActivates.put(names[0], activate); - } - for (String n : names) { - if (!cachedNames.containsKey(clazz)) { - cachedNames.put(clazz, n); - } - Class c = extensionClasses.get(n); - if (c == null) { - extensionClasses.put(n, clazz); - } else if (c != clazz) { - throw new IllegalStateException("Duplicate extension " + type.getName() - + " name " + n + " on " + c.getName() - + " and " + clazz.getName()); - } - } - } - } - } - - private boolean isWrapperClass(Class clazz) { - try { - clazz.getConstructor(type); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - - @SuppressWarnings("deprecation") - private String findAnnotationName(Class clazz) { - com.alibaba.dubbo.common.Extension extension = clazz - .getAnnotation(com.alibaba.dubbo.common.Extension.class); - if (extension == null) { - String name = clazz.getSimpleName(); - if (name.endsWith(type.getSimpleName())) { - name = name.substring(0, name.length() - type.getSimpleName().length()); - } - return name.toLowerCase(); - } - return extension.value(); - } - - @SuppressWarnings("unchecked") - private T createAdaptiveExtension() { - try { - return injectExtension((T) getAdaptiveExtensionClass().newInstance()); - } catch (Exception e) { - throw new IllegalStateException("Can not create adaptive extension " + type - + ", cause: " + e.getMessage(), e); - } - } - - private Class getAdaptiveExtensionClass() { - getExtensionClasses(); - if (cachedAdaptiveClass != null) { - return cachedAdaptiveClass; - } - return cachedAdaptiveClass = createAdaptiveExtensionClass(); - } - - private Class createAdaptiveExtensionClass() { - String code = createAdaptiveExtensionClassCode(); - ClassLoader classLoader = findClassLoader(); - com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader( - com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); - return compiler.compile(code, classLoader); - } - - private String createAdaptiveExtensionClassCode() { - StringBuilder codeBuilder = new StringBuilder(); - Method[] methods = type.getMethods(); - boolean hasAdaptiveAnnotation = false; - for (Method m : methods) { - if (m.isAnnotationPresent(Adaptive.class)) { - hasAdaptiveAnnotation = true; - break; - } - } - // no need to generate adaptive class since there's no adaptive method found. - if (!hasAdaptiveAnnotation) - throw new IllegalStateException("No adaptive method on extension " + type.getName() - + ", refuse to create the adaptive class!"); - - codeBuilder.append("package ").append(type.getPackage().getName()).append(";"); - codeBuilder.append("\nimport ").append(ExtensionLoader.class.getName()).append(";"); - codeBuilder.append("\npublic class ").append(type.getSimpleName()).append("$Adaptive") - .append(" implements ").append(type.getCanonicalName()).append(" {"); - - for (Method method : methods) { - Class rt = method.getReturnType(); - Class[] pts = method.getParameterTypes(); - Class[] ets = method.getExceptionTypes(); - - Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class); - StringBuilder code = new StringBuilder(512); - if (adaptiveAnnotation == null) { - code.append("throw new UnsupportedOperationException(\"method ") - .append(method.toString()).append(" of interface ").append(type.getName()) - .append(" is not adaptive method!\");"); - } else { - int urlTypeIndex = -1; - for (int i = 0; i < pts.length; ++i) { - if (pts[i].equals(URL.class)) { - urlTypeIndex = i; - break; - } - } - // found parameter in URL type - if (urlTypeIndex != -1) { - // Null Point check - String s = String - .format( - "\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");", - urlTypeIndex); - code.append(s); - - s = String.format("\n%s url = arg%d;", URL.class.getName(), urlTypeIndex); - code.append(s); - } - // did not find parameter in URL type - else { - String attribMethod = null; - - // find URL getter method - LBL_PTS: for (int i = 0; i < pts.length; ++i) { - Method[] ms = pts[i].getMethods(); - for (Method m : ms) { - String name = m.getName(); - if ((name.startsWith("get") || name.length() > 3) - && Modifier.isPublic(m.getModifiers()) - && !Modifier.isStatic(m.getModifiers()) - && m.getParameterTypes().length == 0 - && m.getReturnType() == URL.class) { - urlTypeIndex = i; - attribMethod = name; - break LBL_PTS; - } - } - } - if (attribMethod == null) { - throw new IllegalStateException( - "fail to create adaptive class for interface " - + type.getName() - + ": not found url parameter or url attribute in parameters of method " - + method.getName()); - } - - // Null point check - String s = String - .format( - "\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");", - urlTypeIndex, pts[urlTypeIndex].getName()); - code.append(s); - s = String - .format( - "\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");", - urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod); - code.append(s); - - s = String.format("%s url = arg%d.%s();", URL.class.getName(), urlTypeIndex, - attribMethod); - code.append(s); - } - - String[] value = adaptiveAnnotation.value(); - // value is not set, use the value generated from class name as the key - if (value.length == 0) { - char[] charArray = type.getSimpleName().toCharArray(); - StringBuilder sb = new StringBuilder(128); - for (int i = 0; i < charArray.length; i++) { - if (Character.isUpperCase(charArray[i])) { - if (i != 0) { - sb.append("."); - } - sb.append(Character.toLowerCase(charArray[i])); - } else { - sb.append(charArray[i]); - } - } - value = new String[] { sb.toString() }; - } - - boolean hasInvocation = false; - for (int i = 0; i < pts.length; ++i) { - if (pts[i].getName().equals("com.alibaba.dubbo.rpc.Invocation")) { - // Null Point check - String s = String - .format( - "\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", - i); - code.append(s); - s = String.format("\nString methodName = arg%d.getMethodName();", i); - code.append(s); - hasInvocation = true; - break; - } - } - - String defaultExtName = cachedDefaultName; - String getNameCode = null; - for (int i = value.length - 1; i >= 0; --i) { - if (i == value.length - 1) { - if (null != defaultExtName) { - if (!"protocol".equals(value[i])) - if (hasInvocation) - getNameCode = String.format( - "url.getMethodParameter(methodName, \"%s\", \"%s\")", - value[i], defaultExtName); - else - getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", - value[i], defaultExtName); - else - getNameCode = String.format( - "( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", - defaultExtName); - } else { - if (!"protocol".equals(value[i])) - if (hasInvocation) - getNameCode = String.format( - "url.getMethodParameter(methodName, \"%s\", \"%s\")", - value[i], defaultExtName); - else - getNameCode = String.format("url.getParameter(\"%s\")", - value[i]); - else - getNameCode = "url.getProtocol()"; - } - } else { - if (!"protocol".equals(value[i])) - if (hasInvocation) - getNameCode = String.format( - "url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], - defaultExtName); - else - getNameCode = String.format("url.getParameter(\"%s\", %s)", - value[i], getNameCode); - else - getNameCode = String - .format("url.getProtocol() == null ? (%s) : url.getProtocol()", - getNameCode); - } - } - code.append("\nString extName = ").append(getNameCode).append(";"); - // check extName == null? - String s = String - .format( - "\nif(extName == null) " - + "throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");", - type.getName(), Arrays.toString(value)); - code.append(s); - - s = String.format( - "\n%s extension = (% 0) { - codeBuilder.append(", "); - } - codeBuilder.append(pts[i].getCanonicalName()); - codeBuilder.append(" "); - codeBuilder.append("arg").append(i); - } - codeBuilder.append(")"); - if (ets.length > 0) { - codeBuilder.append(" throws "); - for (int i = 0; i < ets.length; i++) { - if (i > 0) { - codeBuilder.append(", "); - } - codeBuilder.append(ets[i].getCanonicalName()); - } - } - codeBuilder.append(" {"); - codeBuilder.append(code.toString()); - codeBuilder.append("\n}"); - } - codeBuilder.append("\n}"); - if (logger.isDebugEnabled()) { - logger.debug(codeBuilder.toString()); - } - return codeBuilder.toString(); - } - - @Override - public String toString() { - return this.getClass().getName() + "[" + type.getName() + "]"; - } - -} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java deleted file mode 100644 index 4cc4671f4..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderJavaObjectInput.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 com.alibaba.dubbo.common.serialize.java; - -import com.alibaba.dubbo.common.serialize.nativejava.NativeJavaObjectInput; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.lang.reflect.Type; - -public class ClassLoaderJavaObjectInput extends NativeJavaObjectInput { - public final static int MAX_BYTE_ARRAY_LENGTH = 8 * 1024 * 1024; - - public ClassLoaderJavaObjectInput(InputStream is) throws IOException { - super( - (ObjectInputStream) (is instanceof ObjectInputStream ? is : new ObjectInputStream(is))); - } - - @Override - public byte[] readBytes() throws IOException { - int len = getObjectInputStream().readInt(); - if (len < 0) - return null; - if (len == 0) - return new byte[0]; - if (len > MAX_BYTE_ARRAY_LENGTH) - throw new IOException("Byte array length too large. " + len); - - byte[] b = new byte[len]; - getObjectInputStream().readFully(b); - return b; - } - - @Override - public String readUTF() throws IOException { - int len = getObjectInputStream().readInt(); - if (len < 0) - return null; - - return getObjectInputStream().readUTF(); - } - - @Override - public Object readObject() throws IOException, ClassNotFoundException { - byte b = getObjectInputStream().readByte(); - if (b == 0) - return null; - - return getObjectInputStream().readObject(); - } - - @Override - @SuppressWarnings("unchecked") - public T readObject(Class cls) throws IOException, ClassNotFoundException { - return (T) readObject(); - } - - @Override - @SuppressWarnings("unchecked") - public T readObject(Class 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.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java deleted file mode 100644 index 2220b97ee..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/ClassLoaderObjectInputStream.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 com.alibaba.dubbo.common.serialize.java; - -import java.io.*; -import java.lang.reflect.Proxy; - -public class ClassLoaderObjectInputStream extends ObjectInputStream { - - public ClassLoader getClassLoader() { - return classLoader; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - /** - * The class loader to use. - */ - 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); - } - } - -} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java deleted file mode 100644 index 91581b508..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/common/serialize/java/JavaSerialization.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 com.alibaba.dubbo.common.serialize.java; - -import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.common.serialize.ObjectInput; -import com.alibaba.dubbo.common.serialize.ObjectOutput; -import com.alibaba.dubbo.common.serialize.Serialization; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * @author syd - * @version ClassLoaderJavaSerialization.java, v 0.1 2023年10月28日 19:18 syd - */ -public class JavaSerialization implements Serialization { - - @Override - public byte getContentTypeId() { - return 3; - } - - @Override - public String getContentType() { - return "x-application/java"; - } - - @Override - public ObjectOutput serialize(URL url, OutputStream output) throws IOException { - return new JavaObjectOutput(output); - } - - @Override - public ObjectInput deserialize(URL url, InputStream is) throws IOException { - return new ClassLoaderJavaObjectInput(new ClassLoaderObjectInputStream(null, is)); - } - -} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java deleted file mode 100644 index 9338931f0..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/model/ApplicationModel.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 com.alibaba.dubbo.config.model; - -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.utils.ConcurrentHashSet; -import com.alibaba.dubbo.rpc.Invoker; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -// TODO need to adjust project structure in order to fully utilize the methods introduced here. -public class ApplicationModel { - - protected static final Logger logger = LoggerFactory - .getLogger(ApplicationModel.class); - - /** - * full qualified class name -> provided service - */ - private static final ConcurrentMap providedServices = new ConcurrentHashMap(); - /** - * full qualified class name -> subscribe service - */ - private static final ConcurrentMap consumedServices = new ConcurrentHashMap(); - - public static final ConcurrentMap> providedServicesInvoker = new ConcurrentHashMap>(); - - public static List allConsumerModels() { - return new ArrayList(consumedServices.values()); - } - - public static ProviderModel getProviderModel(String serviceName) { - return providedServices.get(serviceName); - } - - public static ConsumerModel getConsumerModel(String serviceName) { - return consumedServices.get(serviceName); - } - - public static List allProviderModels() { - return new ArrayList(providedServices.values()); - } - - public static boolean initConsumerModel(String serviceName, ConsumerModel consumerModel) { - if (consumedServices - .putIfAbsent( - getConsumerModelKey(serviceName, consumerModel.getMetadata().getApplication() - .getName()), consumerModel) != null) { - logger.warn("Already register the same consumer:" + serviceName); - return false; - } - return true; - } - - public static String getConsumerModelKey(String serviceName, String applicationName) { - return applicationName + ":" + serviceName; - } - - public static void initProviderModel(String serviceName, ProviderModel providerModel) { - if (providedServices.put(serviceName, providerModel) != null) { - logger.warn("already register the provider service: " + serviceName); - return; - } - } - - public static void addProviderInvoker(String serviceName, Invoker invoker) { - Set invokers = providedServicesInvoker.get(serviceName); - if (invokers == null) { - providedServicesInvoker.putIfAbsent(serviceName, new ConcurrentHashSet()); - invokers = providedServicesInvoker.get(serviceName); - } - invokers.add(invoker); - } - - public Set getProviderInvoker(String serviceName) { - Set invokers = providedServicesInvoker.get(serviceName); - if (invokers == null) { - return Collections.emptySet(); - } - return invokers; - } -} diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java deleted file mode 100644 index 5d58227e2..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 com.alibaba.dubbo.config.spring.extension; - -import com.alibaba.dubbo.common.extension.ExtensionFactory; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.utils.ConcurrentHashSet; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.NoUniqueBeanDefinitionException; -import org.springframework.context.ApplicationContext; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * SpringExtensionFactory - */ -public class SpringExtensionFactory implements ExtensionFactory { - private static final Logger logger = LoggerFactory - .getLogger(SpringExtensionFactory.class); - - private static final Map> contextsWithClassLoader = new ConcurrentHashMap<>(); - - public static void addApplicationContext(ApplicationContext context) { - getContexts().add(context); - } - - public static void removeApplicationContext(ApplicationContext context) { - getContexts().remove(context); - } - - // currently for test purpose - public static void clearContexts() { - - getContexts().clear(); - } - - @Override - @SuppressWarnings("unchecked") - public T getExtension(Class type, String name) { - for (ApplicationContext context : getContexts()) { - if (context.containsBean(name)) { - Object bean = context.getBean(name); - if (type.isInstance(bean)) { - return (T) bean; - } - } - } - - logger.warn("No spring extension(bean) named:" + name - + ", try to find an extension(bean) of type " + type.getName()); - - for (ApplicationContext context : getContexts()) { - try { - return context.getBean(type); - } catch (NoUniqueBeanDefinitionException multiBeanExe) { - throw multiBeanExe; - } catch (NoSuchBeanDefinitionException noBeanExe) { - if (logger.isDebugEnabled()) { - logger.debug( - "Error when get spring extension(bean) for type:" + type.getName(), - noBeanExe); - } - } - } - - logger.warn("No spring extension(bean) named:" + name + ", type:" + type.getName() - + " found, stop get bean."); - - return null; - } - - private static ClassLoader findClassLoader() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader != null) - return classLoader; - return SpringExtensionFactory.class.getClassLoader(); - } - - private static Set getContexts() { - ClassLoader classLoader = findClassLoader(); - Set contexts = null; - if ((contexts = contextsWithClassLoader.get(classLoader)) == null) { - contextsWithClassLoader.put(classLoader, new ConcurrentHashSet<>()); - contexts = contextsWithClassLoader.get(classLoader); - } - ; - return contexts; - } - -} diff --git a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java deleted file mode 100644 index f7ec2818e..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 com.alibaba.dubbo.rpc.protocol.dubbo; - -import com.alibaba.dubbo.common.ClassLoaderUtil; -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.serialize.Cleanable; -import com.alibaba.dubbo.common.serialize.ObjectInput; -import com.alibaba.dubbo.common.serialize.java.ClassLoaderJavaObjectInput; -import com.alibaba.dubbo.common.serialize.java.ClassLoaderObjectInputStream; -import com.alibaba.dubbo.common.utils.Assert; -import com.alibaba.dubbo.common.utils.ReflectUtils; -import com.alibaba.dubbo.common.utils.StringUtils; -import com.alibaba.dubbo.remoting.Channel; -import com.alibaba.dubbo.remoting.Codec; -import com.alibaba.dubbo.remoting.Decodeable; -import com.alibaba.dubbo.remoting.exchange.Request; -import com.alibaba.dubbo.remoting.transport.CodecSupport; -import com.alibaba.dubbo.rpc.RpcInvocation; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.HashMap; -import java.util.Map; - -import static com.alibaba.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(); - } - - @Override - public Object decode(Channel channel, InputStream input) throws IOException { - //注意 channel的url不具有唯一性 实际上使用以inputstream的path为准 - ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) - .deserialize(channel.getUrl(), input); - - String dubboVersion = in.readUTF(); - request.setVersion(dubboVersion); - setAttachment(Constants.DUBBO_VERSION_KEY, dubboVersion); - String path = in.readUTF(); - setAttachment(Constants.PATH_KEY, path); - if (in instanceof ClassLoaderJavaObjectInput) { - InputStream is = ((ClassLoaderJavaObjectInput) in).getInputStream(); - if (is instanceof ClassLoaderObjectInputStream) { - ClassLoader cl = ClassLoaderUtil.getClassLoaderByPath(path); - ((ClassLoaderObjectInputStream) is).setClassLoader(cl); - } - } - setAttachment(Constants.VERSION_KEY, in.readUTF()); - - setMethodName(in.readUTF()); - try { - Object[] args; - Class[] pts; - String desc = in.readUTF(); - if (desc.length() == 0) { - pts = DubboCodec.EMPTY_CLASS_ARRAY; - args = DubboCodec.EMPTY_OBJECT_ARRAY; - } else { - pts = ReflectUtils.desc2classArray(desc); - 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 = (Map) in.readObject(Map.class); - if (map != null && map.size() > 0) { - Map attachment = getAttachments(); - if (attachment == null) { - attachment = new HashMap(); - } - attachment.putAll(map); - setAttachments(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); - - } 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.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java deleted file mode 100644 index 459d81e81..000000000 --- a/sofa-serverless-runtime/sofa-serverless-adapter-ext/sofa-serverless-adapter-dubbo2.6/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 com.alibaba.dubbo.rpc.protocol.dubbo; - -import com.alibaba.dubbo.common.ClassLoaderUtil; -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.serialize.Cleanable; -import com.alibaba.dubbo.common.serialize.ObjectInput; -import com.alibaba.dubbo.common.serialize.java.ClassLoaderJavaObjectInput; -import com.alibaba.dubbo.common.serialize.java.ClassLoaderObjectInputStream; -import com.alibaba.dubbo.common.utils.Assert; -import com.alibaba.dubbo.common.utils.StringUtils; -import com.alibaba.dubbo.remoting.Channel; -import com.alibaba.dubbo.remoting.Codec; -import com.alibaba.dubbo.remoting.Decodeable; -import com.alibaba.dubbo.remoting.exchange.Response; -import com.alibaba.dubbo.remoting.transport.CodecSupport; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.RpcResult; -import com.alibaba.dubbo.rpc.support.RpcUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Type; -import java.util.Map; - -public class DecodeableRpcResult extends RpcResult 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 { - ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) - .deserialize(channel.getUrl(), input); - //表示应用的来源 - String application = channel.getUrl().getParameter(Constants.APPLICATION_KEY); - String serviceName = channel.getUrl().getServiceKey(); - ClassLoader cl = ClassLoaderUtil.getClassLoaderByServiceNameAndApplication(serviceName, - application); - Thread.currentThread().setContextClassLoader(cl); - if (in instanceof ClassLoaderJavaObjectInput) { - InputStream is = ((ClassLoaderJavaObjectInput) in).getInputStream(); - if (is instanceof ClassLoaderObjectInputStream) { - ((ClassLoaderObjectInputStream) is).setClassLoader(cl); - } - } - byte flag = in.readByte(); - switch (flag) { - case DubboCodec.RESPONSE_NULL_VALUE: - break; - case DubboCodec.RESPONSE_VALUE: - try { - Type[] returnType = RpcUtils.getReturnTypes(invocation); - setValue(returnType == null || returnType.length == 0 ? in.readObject() - : (returnType.length == 1 ? in.readObject((Class) returnType[0]) : in - .readObject((Class) returnType[0], returnType[1]))); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read response data failed.", e)); - } - break; - case DubboCodec.RESPONSE_WITH_EXCEPTION: - try { - Object obj = in.readObject(); - if (obj instanceof Throwable == false) - throw new IOException("Response data error, expect Throwable, but get " - + obj); - setException((Throwable) obj); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read response data failed.", e)); - } - break; - case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS: - try { - setAttachments((Map) in.readObject(Map.class)); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read response data failed.", e)); - } - break; - case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS: - try { - Type[] returnType = RpcUtils.getReturnTypes(invocation); - setValue(returnType == null || returnType.length == 0 ? in.readObject() - : (returnType.length == 1 ? in.readObject((Class) returnType[0]) : in - .readObject((Class) returnType[0], returnType[1]))); - setAttachments((Map) in.readObject(Map.class)); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read response data failed.", e)); - } - break; - case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS: - try { - Object obj = in.readObject(); - if (obj instanceof Throwable == false) - throw new IOException("Response data error, expect Throwable, but get " - + obj); - setException((Throwable) obj); - setAttachments((Map) in.readObject(Map.class)); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read response data failed.", e)); - } - break; - default: - throw new IOException("Unknown result flag, expect '0' '1' '2', get " + flag); - } - if (in instanceof Cleanable) { - ((Cleanable) in).cleanup(); - } - return this; - } - - @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 result failed: " + e.getMessage(), e); - } - response.setStatus(Response.CLIENT_ERROR); - response.setErrorMessage(StringUtils.toString(e)); - } finally { - hasDecoded = true; - } - } - } - -}