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

org.apache.dubbo.rpc.model.ScopeModel Maven / Gradle / Ivy

There is a newer version: 3.3.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.dubbo.rpc.model;

import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionDirector;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.StringUtils;

import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_UNABLE_DESTROY_MODEL;

public abstract class ScopeModel implements ExtensionAccessor {
    protected static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(ScopeModel.class);

    /**
     * The internal id is used to represent the hierarchy of the model tree, such as:
     * 
    *
  1. 1
  2. * FrameworkModel (index=1) *
  3. 1.2
  4. * FrameworkModel (index=1) -> ApplicationModel (index=2) *
  5. 1.2.0
  6. * FrameworkModel (index=1) -> ApplicationModel (index=2) -> ModuleModel (index=0, internal module) *
  7. 1.2.1
  8. * FrameworkModel (index=1) -> ApplicationModel (index=2) -> ModuleModel (index=1, first user module) *
*/ private String internalId; /** * Public Model Name, can be set from user */ private String modelName; private String desc; private Set classLoaders; private final ScopeModel parent; private final ExtensionScope scope; private ExtensionDirector extensionDirector; private ScopeBeanFactory beanFactory; private List destroyListeners; private List classLoaderListeners; private Map attributes; private final AtomicBoolean destroyed = new AtomicBoolean(false); private final boolean internalScope; public ScopeModel(ScopeModel parent, ExtensionScope scope, boolean isInternal) { this.parent = parent; this.scope = scope; this.internalScope = isInternal; } /** * NOTE: *
    *
  1. The initialize method only be called in subclass.
  2. *
  3. * In subclass, the extensionDirector and beanFactory are available in initialize but not available in constructor. *
  4. *
*/ protected void initialize() { this.extensionDirector = new ExtensionDirector(parent != null ? parent.getExtensionDirector() : null, scope, this); this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this)); this.beanFactory = new ScopeBeanFactory(parent != null ? parent.getBeanFactory() : null, extensionDirector); this.destroyListeners = new LinkedList<>(); this.classLoaderListeners = new LinkedList<>(); this.attributes = new ConcurrentHashMap<>(); this.classLoaders = new ConcurrentHashSet<>(); // Add Framework's ClassLoader by default ClassLoader dubboClassLoader = ScopeModel.class.getClassLoader(); if (dubboClassLoader != null) { this.addClassLoader(dubboClassLoader); } } public void destroy() { if (destroyed.compareAndSet(false, true)) { try { onDestroy(); HashSet copyOfClassLoaders = new HashSet<>(classLoaders); for (ClassLoader classLoader : copyOfClassLoaders) { removeClassLoader(classLoader); } if (beanFactory != null) { beanFactory.destroy(); } if (extensionDirector != null) { extensionDirector.destroy(); } } catch (Throwable t) { LOGGER.error(CONFIG_UNABLE_DESTROY_MODEL, "", "", "Error happened when destroying ScopeModel.", t); } } } public boolean isDestroyed() { return destroyed.get(); } protected void notifyDestroy() { for (ScopeModelDestroyListener destroyListener : destroyListeners) { destroyListener.onDestroy(this); } } protected void notifyProtocolDestroy() { for (ScopeModelDestroyListener destroyListener : destroyListeners) { if (destroyListener.isProtocol()) { destroyListener.onDestroy(this); } } } protected void notifyClassLoaderAdd(ClassLoader classLoader) { for (ScopeClassLoaderListener classLoaderListener : classLoaderListeners) { classLoaderListener.onAddClassLoader(this, classLoader); } } protected void notifyClassLoaderDestroy(ClassLoader classLoader) { for (ScopeClassLoaderListener classLoaderListener : classLoaderListeners) { classLoaderListener.onRemoveClassLoader(this, classLoader); } } protected abstract void onDestroy(); public final void addDestroyListener(ScopeModelDestroyListener listener) { destroyListeners.add(listener); } public final void addClassLoaderListener(ScopeClassLoaderListener listener) { classLoaderListeners.add(listener); } public Map getAttributes() { return attributes; } public T getAttribute(String key, Class type) { return (T) attributes.get(key); } public Object getAttribute(String key) { return attributes.get(key); } public void setAttribute(String key, Object value) { attributes.put(key, value); } @Override public ExtensionDirector getExtensionDirector() { return extensionDirector; } public ScopeBeanFactory getBeanFactory() { return beanFactory; } public ScopeModel getParent() { return parent; } public ExtensionScope getScope() { return scope; } public void addClassLoader(ClassLoader classLoader) { this.classLoaders.add(classLoader); if (parent != null) { parent.addClassLoader(classLoader); } extensionDirector.removeAllCachedLoader(); notifyClassLoaderAdd(classLoader); } public void removeClassLoader(ClassLoader classLoader) { if (checkIfClassLoaderCanRemoved(classLoader)) { this.classLoaders.remove(classLoader); if (parent != null) { parent.removeClassLoader(classLoader); } extensionDirector.removeAllCachedLoader(); notifyClassLoaderDestroy(classLoader); } } protected boolean checkIfClassLoaderCanRemoved(ClassLoader classLoader) { return classLoader != null && !classLoader.equals(ScopeModel.class.getClassLoader()); } public Set getClassLoaders() { return Collections.unmodifiableSet(classLoaders); } public abstract Environment getModelEnvironment(); public String getInternalId() { return this.internalId; } void setInternalId(String internalId) { this.internalId = internalId; } protected String buildInternalId(String parentInternalId, long childIndex) { // FrameworkModel 1 // ApplicationModel 1.1 // ModuleModel 1.1.1 if (StringUtils.hasText(parentInternalId)) { return parentInternalId + "." + childIndex; } else { return "" + childIndex; } } public String getModelName() { return modelName; } public void setModelName(String modelName) { this.modelName = modelName; this.desc = buildDesc(); } public boolean isInternal() { return internalScope; } /** * @return to describe string of this scope model */ public String getDesc() { if (this.desc == null) { this.desc = buildDesc(); } return this.desc; } private String buildDesc() { // Dubbo Framework[1] // Dubbo Application[1.1](appName) // Dubbo Module[1.1.1](appName/moduleName) String type = this.getClass().getSimpleName().replace("Model", ""); String desc = "Dubbo " + type + "[" + this.getInternalId() + "]"; // append model name path String modelNamePath = this.getModelNamePath(); if (StringUtils.hasText(modelNamePath)) { desc += "(" + modelNamePath + ")"; } return desc; } private String getModelNamePath() { if (this instanceof ApplicationModel) { return safeGetAppName((ApplicationModel) this); } else if (this instanceof ModuleModel) { String modelName = this.getModelName(); if (StringUtils.hasText(modelName)) { // appName/moduleName return safeGetAppName(((ModuleModel) this).getApplicationModel()) + "/" + modelName; } } return null; } private static String safeGetAppName(ApplicationModel applicationModel) { String modelName = applicationModel.getModelName(); if (StringUtils.isBlank(modelName)) { modelName = "unknown"; // unknown application } return modelName; } @Override public String toString() { return getDesc(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy