protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
    if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
      // The application context id is still set to its original default value
      // -> assign a more useful id based on available information
      if (this.contextId != null) {
        wac.setId(this.contextId);
      } else {
        // Generate default id...
        wac.setId(
            ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX
                + ObjectUtils.getDisplayString(getServletContext().getContextPath())
                + "/"
                + getServletName());
      }
    }

    wac.setServletContext(getServletContext());
    wac.setServletConfig(getServletConfig());
    wac.setNamespace(getNamespace());
    wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

    // The wac environment's #initPropertySources will be called in any case when the context
    // is refreshed; do it eagerly here to ensure servlet property sources are in place for
    // use in any post-processing or initialization that occurs below prior to #refresh
    ConfigurableEnvironment env = wac.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
      ((ConfigurableWebEnvironment) env)
          .initPropertySources(getServletContext(), getServletConfig());
    }

    postProcessWebApplicationContext(wac);
    applyInitializers(wac);
    wac.refresh();
  }
Exemple #2
0
 @Override
 public String toString() {
   StringBuilder sb = new StringBuilder(getClass().getName());
   if (this.object != null) {
     sb.append(": wrapping object [")
         .append(ObjectUtils.identityToString(this.object))
         .append("]");
   } else {
     sb.append(": no wrapped object set");
   }
   return sb.toString();
 }
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   if (ReflectionUtils.isEqualsMethod(method)) {
     return (isProxyForSameRubyObject(args[0]) ? Boolean.TRUE : Boolean.FALSE);
   } else if (ReflectionUtils.isHashCodeMethod(method)) {
     return new Integer(this.rubyObject.hashCode());
   } else if (ReflectionUtils.isToStringMethod(method)) {
     String toStringResult = this.rubyObject.toString();
     if (!StringUtils.hasText(toStringResult)) {
       toStringResult = ObjectUtils.identityToString(this.rubyObject);
     }
     return "JRuby object [" + toStringResult + "]";
   }
   try {
     IRubyObject[] rubyArgs = convertToRuby(args);
     IRubyObject rubyResult =
         this.rubyObject.callMethod(this.ruby.getCurrentContext(), method.getName(), rubyArgs);
     return convertFromRuby(rubyResult, method.getReturnType());
   } catch (RaiseException ex) {
     throw new JRubyExecutionException(ex);
   }
 }
 protected String getShortPayloadLogMessage(Object payload) {
   if (payload instanceof String) {
     String payloadText = (String) payload;
     return (payloadText.length() < 80)
         ? " payload=" + payloadText
         : " payload=" + payloadText.substring(0, 80) + "...(truncated)";
   } else if (payload instanceof byte[]) {
     byte[] bytes = (byte[]) payload;
     if (isReadableContentType()) {
       Charset charset = getContentType().getCharSet();
       charset = (charset != null ? charset : DEFAULT_CHARSET);
       return (bytes.length < 80)
           ? " payload=" + new String(bytes, charset)
           : " payload=" + new String(Arrays.copyOf(bytes, 80), charset) + "...(truncated)";
     } else {
       return " payload=byte[" + bytes.length + "]";
     }
   } else {
     String payloadText = payload.toString();
     return (payloadText.length() < 80)
         ? " payload=" + payloadText
         : " payload=" + ObjectUtils.identityToString(payload);
   }
 }
/**
 * Abstract implementation of the {@link org.springframework.context.ApplicationContext} interface.
 * Doesn't mandate the type of storage used for configuration; simply implements common context
 * functionality. Uses the Template Method design pattern, requiring concrete subclasses to
 * implement abstract methods.
 *
 * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed to detect special beans
 * defined in its internal bean factory: Therefore, this class automatically registers {@link
 * org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
 * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors} and {@link
 * org.springframework.context.ApplicationListener ApplicationListeners} which are defined as beans
 * in the context.
 *
 * <p>A {@link org.springframework.context.MessageSource} may also be supplied as a bean in the
 * context, with the name "messageSource"; otherwise, message resolution is delegated to the parent
 * context. Furthermore, a multicaster for application events can be supplied as
 * "applicationEventMulticaster" bean of type {@link
 * org.springframework.context.event.ApplicationEventMulticaster} in the context; otherwise, a
 * default multicaster of type {@link
 * org.springframework.context.event.SimpleApplicationEventMulticaster} will be used.
 *
 * <p>Implements resource loading through extending {@link
 * org.springframework.core.io.DefaultResourceLoader}. Consequently treats non-URL resource paths as
 * class path resources (supporting full class path resource names that include the package path,
 * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath} method is overwritten in
 * a subclass.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @author Stephane Nicoll
 * @since January 21, 2001
 * @see #refreshBeanFactory
 * @see #getBeanFactory
 * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
 * @see org.springframework.beans.factory.config.BeanPostProcessor
 * @see org.springframework.context.event.ApplicationEventMulticaster
 * @see org.springframework.context.ApplicationListener
 * @see org.springframework.context.MessageSource
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext, DisposableBean {

  /**
   * Name of the MessageSource bean in the factory. If none is supplied, message resolution is
   * delegated to the parent.
   *
   * @see MessageSource
   */
  public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";

  /**
   * Name of the LifecycleProcessor bean in the factory. If none is supplied, a
   * DefaultLifecycleProcessor is used.
   *
   * @see org.springframework.context.LifecycleProcessor
   * @see org.springframework.context.support.DefaultLifecycleProcessor
   */
  public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";

  /**
   * Name of the ApplicationEventMulticaster bean in the factory. If none is supplied, a default
   * SimpleApplicationEventMulticaster is used.
   *
   * @see org.springframework.context.event.ApplicationEventMulticaster
   * @see org.springframework.context.event.SimpleApplicationEventMulticaster
   */
  public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME =
      "applicationEventMulticaster";

  static {
    // Eagerly load the ContextClosedEvent class to avoid weird classloader issues
    // on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
    ContextClosedEvent.class.getName();
  }

  /** Logger used by this class. Available to subclasses. */
  protected final Log logger = LogFactory.getLog(getClass());

  /** Unique id for this context, if any */
  private String id = ObjectUtils.identityToString(this);

  /** Display name */
  private String displayName = ObjectUtils.identityToString(this);

  /** Parent context */
  private ApplicationContext parent;

  /** Environment used by this context */
  private ConfigurableEnvironment environment;

  /** BeanFactoryPostProcessors to apply on refresh */
  private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors =
      new ArrayList<BeanFactoryPostProcessor>();

  /** System time in milliseconds when this context started */
  private long startupDate;

  /** Flag that indicates whether this context is currently active */
  private final AtomicBoolean active = new AtomicBoolean();

  /** Flag that indicates whether this context has been closed already */
  private final AtomicBoolean closed = new AtomicBoolean();

  /** Synchronization monitor for the "refresh" and "destroy" */
  private final Object startupShutdownMonitor = new Object();

  /** Reference to the JVM shutdown hook, if registered */
  private Thread shutdownHook;

  /** ResourcePatternResolver used by this context */
  private ResourcePatternResolver resourcePatternResolver;

  /** LifecycleProcessor for managing the lifecycle of beans within this context */
  private LifecycleProcessor lifecycleProcessor;

  /** MessageSource we delegate our implementation of this interface to */
  private MessageSource messageSource;

  /** Helper class used in event publishing */
  private ApplicationEventMulticaster applicationEventMulticaster;

  /** Statically specified listeners */
  private final Set<ApplicationListener<?>> applicationListeners =
      new LinkedHashSet<ApplicationListener<?>>();

  /** ApplicationEvents published early */
  private Set<ApplicationEvent> earlyApplicationEvents;

  /** Create a new AbstractApplicationContext with no parent. */
  public AbstractApplicationContext() {
    this.resourcePatternResolver = getResourcePatternResolver();
  }

  /**
   * Create a new AbstractApplicationContext with the given parent context.
   *
   * @param parent the parent context
   */
  public AbstractApplicationContext(ApplicationContext parent) {
    this();
    setParent(parent);
  }

  // ---------------------------------------------------------------------
  // Implementation of ApplicationContext interface
  // ---------------------------------------------------------------------

  /**
   * Set the unique id of this application context.
   *
   * <p>Default is the object id of the context instance, or the name of the context bean if the
   * context is itself defined as a bean.
   *
   * @param id the unique id of the context
   */
  @Override
  public void setId(String id) {
    this.id = id;
  }

  @Override
  public String getId() {
    return this.id;
  }

  @Override
  public String getApplicationName() {
    return "";
  }

  /**
   * Set a friendly name for this context. Typically done during initialization of concrete context
   * implementations.
   *
   * <p>Default is the object id of the context instance.
   */
  public void setDisplayName(String displayName) {
    Assert.hasLength(displayName, "Display name must not be empty");
    this.displayName = displayName;
  }

  /**
   * Return a friendly name for this context.
   *
   * @return a display name for this context (never {@code null})
   */
  @Override
  public String getDisplayName() {
    return this.displayName;
  }

  /**
   * Return the parent context, or {@code null} if there is no parent (that is, this context is the
   * root of the context hierarchy).
   */
  @Override
  public ApplicationContext getParent() {
    return this.parent;
  }

  /**
   * {@inheritDoc}
   *
   * <p>If {@code null}, a new environment will be initialized via {@link #createEnvironment()}.
   */
  @Override
  public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
      this.environment = createEnvironment();
    }
    return this.environment;
  }

  /**
   * {@inheritDoc}
   *
   * <p>Default value is determined by {@link #createEnvironment()}. Replacing the default with this
   * method is one option but configuration through {@link #getEnvironment()} should also be
   * considered. In either case, such modifications should be performed <em>before</em> {@link
   * #refresh()}.
   *
   * @see org.springframework.context.support.AbstractApplicationContext#createEnvironment
   */
  @Override
  public void setEnvironment(ConfigurableEnvironment environment) {
    this.environment = environment;
  }

  /**
   * Return this context's internal bean factory as AutowireCapableBeanFactory, if already
   * available.
   *
   * @see #getBeanFactory()
   */
  @Override
  public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
    return getBeanFactory();
  }

  /** Return the timestamp (ms) when this context was first loaded. */
  @Override
  public long getStartupDate() {
    return this.startupDate;
  }

  /**
   * Publish the given event to all listeners.
   *
   * <p>Note: Listeners get initialized after the MessageSource, to be able to access it within
   * listener implementations. Thus, MessageSource implementations cannot publish events.
   *
   * @param event the event to publish (may be application-specific or a standard framework event)
   */
  @Override
  public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
  }

  @Override
  public void publishEvent(Object event) {
    publishEvent(event, null);
  }

  protected void publishEvent(Object event, ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
      logger.trace("Publishing event in " + getDisplayName() + ": " + event);
    }

    // Decorate event as an ApplicationEvent if necessary
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
      applicationEvent = (ApplicationEvent) event;
    } else {
      applicationEvent = new PayloadApplicationEvent<Object>(this, event);
      if (eventType == null) {
        eventType =
            ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
      }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
      this.earlyApplicationEvents.add(applicationEvent);
    } else {
      getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // Publish event via parent context as well...
    if (this.parent != null) {
      if (this.parent instanceof AbstractApplicationContext) {
        ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
      } else {
        this.parent.publishEvent(event);
      }
    }
  }

  /**
   * Return the internal ApplicationEventMulticaster used by the context.
   *
   * @return the internal ApplicationEventMulticaster (never {@code null})
   * @throws IllegalStateException if the context has not been initialized yet
   */
  ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
    if (this.applicationEventMulticaster == null) {
      throw new IllegalStateException(
          "ApplicationEventMulticaster not initialized - "
              + "call 'refresh' before multicasting events via the context: "
              + this);
    }
    return this.applicationEventMulticaster;
  }

  /**
   * Return the internal LifecycleProcessor used by the context.
   *
   * @return the internal LifecycleProcessor (never {@code null})
   * @throws IllegalStateException if the context has not been initialized yet
   */
  LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
    if (this.lifecycleProcessor == null) {
      throw new IllegalStateException(
          "LifecycleProcessor not initialized - "
              + "call 'refresh' before invoking lifecycle methods via the context: "
              + this);
    }
    return this.lifecycleProcessor;
  }

  /**
   * Return the ResourcePatternResolver to use for resolving location patterns into Resource
   * instances. Default is a {@link
   * org.springframework.core.io.support.PathMatchingResourcePatternResolver}, supporting Ant-style
   * location patterns.
   *
   * <p>Can be overridden in subclasses, for extended resolution strategies, for example in a web
   * environment.
   *
   * <p><b>Do not call this when needing to resolve a location pattern.</b> Call the context's
   * {@code getResources} method instead, which will delegate to the ResourcePatternResolver.
   *
   * @return the ResourcePatternResolver for this context
   * @see #getResources
   * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
   */
  protected ResourcePatternResolver getResourcePatternResolver() {
    return new PathMatchingResourcePatternResolver(this);
  }

  // ---------------------------------------------------------------------
  // Implementation of ConfigurableApplicationContext interface
  // ---------------------------------------------------------------------

  /**
   * {@inheritDoc}
   *
   * <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is {@linkplain
   * ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with this (child) application
   * context environment if the parent is non-{@code null} and its environment is an instance of
   * {@link ConfigurableEnvironment}.
   *
   * @see ConfigurableEnvironment#merge(ConfigurableEnvironment)
   */
  @Override
  public void setParent(ApplicationContext parent) {
    this.parent = parent;
    if (parent != null) {
      Environment parentEnvironment = parent.getEnvironment();
      if (parentEnvironment instanceof ConfigurableEnvironment) {
        getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
      }
    }
  }

  @Override
  public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {
    this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);
  }

  /**
   * Return the list of BeanFactoryPostProcessors that will get applied to the internal BeanFactory.
   */
  public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
  }

  @Override
  public void addApplicationListener(ApplicationListener<?> listener) {
    if (this.applicationEventMulticaster != null) {
      this.applicationEventMulticaster.addApplicationListener(listener);
    } else {
      this.applicationListeners.add(listener);
    }
  }

  /** Return the list of statically specified ApplicationListeners. */
  public Collection<ApplicationListener<?>> getApplicationListeners() {
    return this.applicationListeners;
  }

  /**
   * Create and return a new {@link StandardEnvironment}.
   *
   * <p>Subclasses may override this method in order to supply a custom {@link
   * ConfigurableEnvironment} implementation.
   */
  protected ConfigurableEnvironment createEnvironment() {
    return new StandardEnvironment();
  }

  @Override
  public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
        // Allows post-processing of the bean factory in context subclasses.
        postProcessBeanFactory(beanFactory);

        // Invoke factory processors registered as beans in the context.
        invokeBeanFactoryPostProcessors(beanFactory);

        // Register bean processors that intercept bean creation.
        registerBeanPostProcessors(beanFactory);

        // Initialize message source for this context.
        initMessageSource();

        // Initialize event multicaster for this context.
        initApplicationEventMulticaster();

        // Initialize other special beans in specific context subclasses.
        onRefresh();

        // Check for listener beans and register them.
        registerListeners();

        // Instantiate all remaining (non-lazy-init) singletons.
        finishBeanFactoryInitialization(beanFactory);

        // Last step: publish corresponding event.
        finishRefresh();
      } catch (BeansException ex) {
        logger.warn(
            "Exception encountered during context initialization - cancelling refresh attempt", ex);

        // Destroy already created singletons to avoid dangling resources.
        destroyBeans();

        // Reset 'active' flag.
        cancelRefresh(ex);

        // Propagate exception to caller.
        throw ex;
      }
    }
  }

  /**
   * Prepare this context for refreshing, setting its startup date and active flag as well as
   * performing any initialization of property sources.
   */
  protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.active.set(true);

    if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
    }

    // Initialize any placeholder property sources in the context environment
    initPropertySources();

    // Validate that all properties marked as required are resolvable
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
  }

  /**
   * Replace any stub property sources with actual instances.
   *
   * @see org.springframework.core.env.PropertySource.StubPropertySource
   * @see
   *     org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
   */
  protected void initPropertySources() {
    // For subclasses: do nothing by default.
  }

  /**
   * Tell the subclass to refresh the internal bean factory.
   *
   * @return the fresh BeanFactory instance
   * @see #refreshBeanFactory()
   * @see #getBeanFactory()
   */
  protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
  }

  /**
   * Configure the factory's standard context characteristics, such as the context's ClassLoader and
   * post-processors.
   *
   * @param beanFactory the BeanFactory to configure
   */
  protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(
        new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(
          new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // Register default environment beans.
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(
          SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(
          SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
  }

  /**
   * Modify the application context's internal bean factory after its standard initialization. All
   * bean definitions will have been loaded, but no beans will have been instantiated yet. This
   * allows for registering special BeanPostProcessors etc in certain ApplicationContext
   * implementations.
   *
   * @param beanFactory the bean factory used by the application context
   */
  protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}

  /**
   * Instantiate and invoke all registered BeanFactoryPostProcessor beans, respecting explicit order
   * if given.
   *
   * <p>Must be called before singleton instantiation.
   */
  protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(
        beanFactory, getBeanFactoryPostProcessors());
  }

  /**
   * Instantiate and invoke all registered BeanPostProcessor beans, respecting explicit order if
   * given.
   *
   * <p>Must be called before any instantiation of application beans.
   */
  protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
  }

  /** Initialize the MessageSource. Use parent's if none defined in this context. */
  protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Make MessageSource aware of parent MessageSource.
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
        HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
        if (hms.getParentMessageSource() == null) {
          // Only set parent context as parent MessageSource if no parent MessageSource
          // registered already.
          hms.setParentMessageSource(getInternalParentMessageSource());
        }
      }
      if (logger.isDebugEnabled()) {
        logger.debug("Using MessageSource [" + this.messageSource + "]");
      }
    } else {
      // Use empty MessageSource to be able to accept getMessage calls.
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Unable to locate MessageSource with name '"
                + MESSAGE_SOURCE_BEAN_NAME
                + "': using default ["
                + this.messageSource
                + "]");
      }
    }
  }

  /**
   * Initialize the ApplicationEventMulticaster. Uses SimpleApplicationEventMulticaster if none
   * defined in the context.
   *
   * @see org.springframework.context.event.SimpleApplicationEventMulticaster
   */
  protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster =
          beanFactory.getBean(
              APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
    } else {
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(
          APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Unable to locate ApplicationEventMulticaster with name '"
                + APPLICATION_EVENT_MULTICASTER_BEAN_NAME
                + "': using default ["
                + this.applicationEventMulticaster
                + "]");
      }
    }
  }

  /**
   * Initialize the LifecycleProcessor. Uses DefaultLifecycleProcessor if none defined in the
   * context.
   *
   * @see org.springframework.context.support.DefaultLifecycleProcessor
   */
  protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
      this.lifecycleProcessor =
          beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
      if (logger.isDebugEnabled()) {
        logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
      }
    } else {
      DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
      defaultProcessor.setBeanFactory(beanFactory);
      this.lifecycleProcessor = defaultProcessor;
      beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Unable to locate LifecycleProcessor with name '"
                + LIFECYCLE_PROCESSOR_BEAN_NAME
                + "': using default ["
                + this.lifecycleProcessor
                + "]");
      }
    }
  }

  /**
   * Template method which can be overridden to add context-specific refresh work. Called on
   * initialization of special beans, before instantiation of singletons.
   *
   * <p>This implementation is empty.
   *
   * @throws BeansException in case of errors
   * @see #refresh()
   */
  protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
  }

  /**
   * Add beans that implement ApplicationListener as listeners. Doesn't affect other listeners,
   * which can be added without being beans.
   */
  protected void registerListeners() {
    // Register statically specified listeners first.
    for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
    }
  }

  /**
   * Finish the initialization of this context's bean factory, initializing all remaining singleton
   * beans.
   */
  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
        && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
          beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    String[] weaverAwareNames =
        beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
    }

    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
  }

  /**
   * Finish the refresh of this context, invoking the LifecycleProcessor's onRefresh() method and
   * publishing the {@link org.springframework.context.event.ContextRefreshedEvent}.
   */
  protected void finishRefresh() {
    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
  }

  /**
   * Cancel this context's refresh attempt, resetting the {@code active} flag after an exception got
   * thrown.
   *
   * @param ex the exception that led to the cancellation
   */
  protected void cancelRefresh(BeansException ex) {
    this.active.set(false);
  }

  /**
   * Register a shutdown hook with the JVM runtime, closing this context on JVM shutdown unless it
   * has already been closed at that time.
   *
   * <p>Delegates to {@code doClose()} for the actual closing procedure.
   *
   * @see Runtime#addShutdownHook
   * @see #close()
   * @see #doClose()
   */
  @Override
  public void registerShutdownHook() {
    if (this.shutdownHook == null) {
      // No shutdown hook registered yet.
      this.shutdownHook =
          new Thread() {
            @Override
            public void run() {
              doClose();
            }
          };
      Runtime.getRuntime().addShutdownHook(this.shutdownHook);
    }
  }

  /**
   * DisposableBean callback for destruction of this instance. Only called when the
   * ApplicationContext itself is running as a bean in another BeanFactory or ApplicationContext,
   * which is rather unusual.
   *
   * <p>The {@code close} method is the native way to shut down an ApplicationContext.
   *
   * @see #close()
   * @see org.springframework.beans.factory.access.SingletonBeanFactoryLocator
   */
  @Override
  public void destroy() {
    close();
  }

  /**
   * Close this application context, destroying all beans in its bean factory.
   *
   * <p>Delegates to {@code doClose()} for the actual closing procedure. Also removes a JVM shutdown
   * hook, if registered, as it's not needed anymore.
   *
   * @see #doClose()
   * @see #registerShutdownHook()
   */
  @Override
  public void close() {
    synchronized (this.startupShutdownMonitor) {
      doClose();
      // If we registered a JVM shutdown hook, we don't need it anymore now:
      // We've already explicitly closed the context.
      if (this.shutdownHook != null) {
        try {
          Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
        } catch (IllegalStateException ex) {
          // ignore - VM is already shutting down
        }
      }
    }
  }

  /**
   * Actually performs context closing: publishes a ContextClosedEvent and destroys the singletons
   * in the bean factory of this application context.
   *
   * <p>Called by both {@code close()} and a JVM shutdown hook, if any.
   *
   * @see org.springframework.context.event.ContextClosedEvent
   * @see #destroyBeans()
   * @see #close()
   * @see #registerShutdownHook()
   */
  protected void doClose() {
    if (this.active.get() && this.closed.compareAndSet(false, true)) {
      if (logger.isInfoEnabled()) {
        logger.info("Closing " + this);
      }

      LiveBeansView.unregisterApplicationContext(this);

      try {
        // Publish shutdown event.
        publishEvent(new ContextClosedEvent(this));
      } catch (Throwable ex) {
        logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
      }

      // Stop all Lifecycle beans, to avoid delays during individual destruction.
      try {
        getLifecycleProcessor().onClose();
      } catch (Throwable ex) {
        logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
      }

      // Destroy all cached singletons in the context's BeanFactory.
      destroyBeans();

      // Close the state of this context itself.
      closeBeanFactory();

      // Let subclasses do some final clean-up if they wish...
      onClose();

      this.active.set(false);
    }
  }

  /**
   * Template method for destroying all beans that this context manages. The default implementation
   * destroy all cached singletons in this context, invoking {@code DisposableBean.destroy()} and/or
   * the specified "destroy-method".
   *
   * <p>Can be overridden to add context-specific bean destruction steps right before or right after
   * standard singleton destruction, while the context's BeanFactory is still active.
   *
   * @see #getBeanFactory()
   * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
   */
  protected void destroyBeans() {
    getBeanFactory().destroySingletons();
  }

  /**
   * Template method which can be overridden to add context-specific shutdown work. The default
   * implementation is empty.
   *
   * <p>Called at the end of {@link #doClose}'s shutdown procedure, after this context's BeanFactory
   * has been closed. If custom shutdown logic needs to execute while the BeanFactory is still
   * active, override the {@link #destroyBeans()} method instead.
   */
  protected void onClose() {
    // For subclasses: do nothing by default.
  }

  @Override
  public boolean isActive() {
    return this.active.get();
  }

  /**
   * Assert that this context's BeanFactory is currently active, throwing an {@link
   * IllegalStateException} if it isn't.
   *
   * <p>Invoked by all {@link BeanFactory} delegation methods that depend on an active context, i.e.
   * in particular all bean accessor methods.
   *
   * <p>The default implementation checks the {@link #isActive() 'active'} status of this context
   * overall. May be overridden for more specific checks, or for a no-op if {@link
   * #getBeanFactory()} itself throws an exception in such a case.
   */
  protected void assertBeanFactoryActive() {
    if (!this.active.get()) {
      if (this.closed.get()) {
        throw new IllegalStateException(getDisplayName() + " has been closed already");
      } else {
        throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
      }
    }
  }

  // ---------------------------------------------------------------------
  // Implementation of BeanFactory interface
  // ---------------------------------------------------------------------

  @Override
  public Object getBean(String name) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(name);
  }

  @Override
  public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(name, requiredType);
  }

  @Override
  public <T> T getBean(Class<T> requiredType) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(requiredType);
  }

  @Override
  public Object getBean(String name, Object... args) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(name, args);
  }

  @Override
  public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(requiredType, args);
  }

  @Override
  public boolean containsBean(String name) {
    return getBeanFactory().containsBean(name);
  }

  @Override
  public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
    assertBeanFactoryActive();
    return getBeanFactory().isSingleton(name);
  }

  @Override
  public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
    assertBeanFactoryActive();
    return getBeanFactory().isPrototype(name);
  }

  @Override
  public boolean isTypeMatch(String name, ResolvableType typeToMatch)
      throws NoSuchBeanDefinitionException {
    assertBeanFactoryActive();
    return getBeanFactory().isTypeMatch(name, typeToMatch);
  }

  @Override
  public boolean isTypeMatch(String name, Class<?> typeToMatch)
      throws NoSuchBeanDefinitionException {
    assertBeanFactoryActive();
    return getBeanFactory().isTypeMatch(name, typeToMatch);
  }

  @Override
  public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
    assertBeanFactoryActive();
    return getBeanFactory().getType(name);
  }

  @Override
  public String[] getAliases(String name) {
    return getBeanFactory().getAliases(name);
  }

  // ---------------------------------------------------------------------
  // Implementation of ListableBeanFactory interface
  // ---------------------------------------------------------------------

  @Override
  public boolean containsBeanDefinition(String beanName) {
    return getBeanFactory().containsBeanDefinition(beanName);
  }

  @Override
  public int getBeanDefinitionCount() {
    return getBeanFactory().getBeanDefinitionCount();
  }

  @Override
  public String[] getBeanDefinitionNames() {
    return getBeanFactory().getBeanDefinitionNames();
  }

  @Override
  public String[] getBeanNamesForType(ResolvableType type) {
    assertBeanFactoryActive();
    return getBeanFactory().getBeanNamesForType(type);
  }

  @Override
  public String[] getBeanNamesForType(Class<?> type) {
    assertBeanFactoryActive();
    return getBeanFactory().getBeanNamesForType(type);
  }

  @Override
  public String[] getBeanNamesForType(
      Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    assertBeanFactoryActive();
    return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
  }

  @Override
  public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBeansOfType(type);
  }

  @Override
  public <T> Map<String, T> getBeansOfType(
      Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {

    assertBeanFactoryActive();
    return getBeanFactory().getBeansOfType(type, includeNonSingletons, allowEagerInit);
  }

  @Override
  public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
    assertBeanFactoryActive();
    return getBeanFactory().getBeanNamesForAnnotation(annotationType);
  }

  @Override
  public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
      throws BeansException {

    assertBeanFactoryActive();
    return getBeanFactory().getBeansWithAnnotation(annotationType);
  }

  @Override
  public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
      throws NoSuchBeanDefinitionException {

    assertBeanFactoryActive();
    return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
  }

  // ---------------------------------------------------------------------
  // Implementation of HierarchicalBeanFactory interface
  // ---------------------------------------------------------------------

  @Override
  public BeanFactory getParentBeanFactory() {
    return getParent();
  }

  @Override
  public boolean containsLocalBean(String name) {
    return getBeanFactory().containsLocalBean(name);
  }

  /**
   * Return the internal bean factory of the parent context if it implements
   * ConfigurableApplicationContext; else, return the parent context itself.
   *
   * @see org.springframework.context.ConfigurableApplicationContext#getBeanFactory
   */
  protected BeanFactory getInternalParentBeanFactory() {
    return (getParent() instanceof ConfigurableApplicationContext)
        ? ((ConfigurableApplicationContext) getParent()).getBeanFactory()
        : getParent();
  }

  // ---------------------------------------------------------------------
  // Implementation of MessageSource interface
  // ---------------------------------------------------------------------

  @Override
  public String getMessage(String code, Object args[], String defaultMessage, Locale locale) {
    return getMessageSource().getMessage(code, args, defaultMessage, locale);
  }

  @Override
  public String getMessage(String code, Object args[], Locale locale)
      throws NoSuchMessageException {
    return getMessageSource().getMessage(code, args, locale);
  }

  @Override
  public String getMessage(MessageSourceResolvable resolvable, Locale locale)
      throws NoSuchMessageException {
    return getMessageSource().getMessage(resolvable, locale);
  }

  /**
   * Return the internal MessageSource used by the context.
   *
   * @return the internal MessageSource (never {@code null})
   * @throws IllegalStateException if the context has not been initialized yet
   */
  private MessageSource getMessageSource() throws IllegalStateException {
    if (this.messageSource == null) {
      throw new IllegalStateException(
          "MessageSource not initialized - "
              + "call 'refresh' before accessing messages via the context: "
              + this);
    }
    return this.messageSource;
  }

  /**
   * Return the internal message source of the parent context if it is an AbstractApplicationContext
   * too; else, return the parent context itself.
   */
  protected MessageSource getInternalParentMessageSource() {
    return (getParent() instanceof AbstractApplicationContext)
        ? ((AbstractApplicationContext) getParent()).messageSource
        : getParent();
  }

  // ---------------------------------------------------------------------
  // Implementation of ResourcePatternResolver interface
  // ---------------------------------------------------------------------

  @Override
  public Resource[] getResources(String locationPattern) throws IOException {
    return this.resourcePatternResolver.getResources(locationPattern);
  }

  // ---------------------------------------------------------------------
  // Implementation of Lifecycle interface
  // ---------------------------------------------------------------------

  @Override
  public void start() {
    getLifecycleProcessor().start();
    publishEvent(new ContextStartedEvent(this));
  }

  @Override
  public void stop() {
    getLifecycleProcessor().stop();
    publishEvent(new ContextStoppedEvent(this));
  }

  @Override
  public boolean isRunning() {
    return getLifecycleProcessor().isRunning();
  }

  // ---------------------------------------------------------------------
  // Abstract methods that must be implemented by subclasses
  // ---------------------------------------------------------------------

  /**
   * Subclasses must implement this method to perform the actual configuration load. The method is
   * invoked by {@link #refresh()} before any other initialization work.
   *
   * <p>A subclass will either create a new bean factory and hold a reference to it, or return a
   * single BeanFactory instance that it holds. In the latter case, it will usually throw an
   * IllegalStateException if refreshing the context more than once.
   *
   * @throws BeansException if initialization of the bean factory failed
   * @throws IllegalStateException if already initialized and multiple refresh attempts are not
   *     supported
   */
  protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

  /**
   * Subclasses must implement this method to release their internal bean factory. This method gets
   * invoked by {@link #close()} after all other shutdown work.
   *
   * <p>Should never throw an exception but rather log shutdown failures.
   */
  protected abstract void closeBeanFactory();

  /**
   * Subclasses must return their internal bean factory here. They should implement the lookup
   * efficiently, so that it can be called repeatedly without a performance penalty.
   *
   * <p>Note: Subclasses should check whether the context is still active before returning the
   * internal bean factory. The internal factory should generally be considered unavailable once the
   * context has been closed.
   *
   * @return this application context's internal bean factory (never {@code null})
   * @throws IllegalStateException if the context does not hold an internal bean factory yet
   *     (usually if {@link #refresh()} has never been called) or if the context has been closed
   *     already
   * @see #refreshBeanFactory()
   * @see #closeBeanFactory()
   */
  @Override
  public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

  /** Return information about this context. */
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(getDisplayName());
    sb.append(": startup date [").append(new Date(getStartupDate()));
    sb.append("]; ");
    ApplicationContext parent = getParent();
    if (parent == null) {
      sb.append("root of context hierarchy");
    } else {
      sb.append("parent: ").append(parent.getDisplayName());
    }
    return sb.toString();
  }
}
// this class is modified from org.springframework.web.socket.server.endpoint.SpringConfigurator
// this configurator make new endpoint when endpoint does not exist in spring bean.
// however, bring endpoint from spring container when endpoint bean is exist in spring container
public class MdConfigurator extends Configurator {
  private static Logger logger = LoggerFactory.getLogger(MdConfigurator.class);

  private static final Map<String, Map<Class<?>, String>> cache =
      new ConcurrentHashMap<String, Map<Class<?>, String>>();

  private static final String NO_VALUE = ObjectUtils.identityToString(new Object());

  @SuppressWarnings("unchecked")
  @Override
  public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
    // this is servlet container application context
    WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();

    if (wac == null) {
      String message =
          "Failed to find the root WebApplicationContext. Was ContextLoaderListener not used?";
      logger.error(message);
      throw new IllegalStateException(message);
    }

    // obtain spring application context
    WebApplicationContext springWac =
        WebApplicationContextUtils.getWebApplicationContext(
            wac.getServletContext(), FrameworkServlet.SERVLET_CONTEXT_PREFIX + "appServlet");

    String beanName = ClassUtils.getShortNameAsProperty(endpointClass);
    if (springWac.containsBean(beanName)) {
      T endpoint = springWac.getBean(beanName, endpointClass);
      if (logger.isTraceEnabled()) {
        logger.trace("Using @ServerEndpoint singleton " + endpoint);
      }
      return endpoint;
    }

    Component annot = AnnotationUtils.findAnnotation(endpointClass, Component.class);
    if ((annot != null) && springWac.containsBean(annot.value())) {
      T endpoint = springWac.getBean(annot.value(), endpointClass);
      if (logger.isTraceEnabled()) {
        logger.trace("Using @ServerEndpoint singleton " + endpoint);
      }
      return endpoint;
    }

    beanName = getBeanNameByType(springWac, endpointClass);
    if (beanName != null) {
      return (T) springWac.getBean(beanName);
    }

    if (logger.isTraceEnabled()) {
      logger.trace("Creating new @ServerEndpoint instance of type " + endpointClass);
    }
    return springWac.getAutowireCapableBeanFactory().createBean(endpointClass);
  }

  private String getBeanNameByType(WebApplicationContext wac, Class<?> endpointClass) {

    String wacId = wac.getId();

    Map<Class<?>, String> beanNamesByType = cache.get(wacId);
    if (beanNamesByType == null) {
      beanNamesByType = new ConcurrentHashMap<Class<?>, String>();
      cache.put(wacId, beanNamesByType);
    }

    if (!beanNamesByType.containsKey(endpointClass)) {
      String[] names = wac.getBeanNamesForType(endpointClass);
      if (names.length == 1) {
        beanNamesByType.put(endpointClass, names[0]);
      } else {
        beanNamesByType.put(endpointClass, NO_VALUE);
        if (names.length > 1) {
          String message =
              "Found multiple @ServerEndpoint's of type " + endpointClass + ", names=" + names;
          logger.error(message);
          throw new IllegalStateException(message);
        }
      }
    }

    String beanName = beanNamesByType.get(endpointClass);
    return NO_VALUE.equals(beanName) ? null : beanName;
  }
}
 public String toString() {
   return "SingletonTargetSource for target object ["
       + ObjectUtils.identityToString(this.target)
       + "]";
 }