package com.wb.domainserver.realm; import com.wb.domainserver.exception.WnbtRestException; import com.wb.domainserver.realm.entity.Site; import com.wb.domainserver.realm.exception.RealmNotFoundException; import com.wb.domainserver.realm.repository.SiteRepository; import com.wb.domainserver.realm.util.UrlExtractor; import com.wb.domainserver.util.string.StringUtil; import jakarta.servlet.ServletRequest; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import java.util.Objects; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Component public class RealmResolver { private static final Logger logger = LoggerFactory.getLogger(RealmResolver.class); private final SiteRepository siteRepository; private final ApplicationContext applicationContext; private final ExecutorService executorService = Executors.newCachedThreadPool(); @Autowired public RealmResolver(SiteRepository siteRepository, ApplicationContext applicationContext) { this.siteRepository = siteRepository; this.applicationContext = applicationContext; } public CompletableFuture resolveRealm(String host) { return CompletableFuture.supplyAsync(() -> { String hostUrl; try { hostUrl = Objects.requireNonNull(host).replaceAll("/", ""); logger.info("Resolving tenant for host URL: {}", hostUrl); return resolveRealmInternal(hostUrl); // 동기 호출 } catch (NullPointerException e) { logger.error("Failed to retrieve host URL from request", e); throw new RealmNotFoundException("Failed to retrieve host URL from request", e); } }, executorService); } @Cacheable(cacheNames = "realmCache", key = "#hostUrl") public Object resolveRealmInternal(String hostUrl) { return resolveRealmInternalDirect(hostUrl).join(); } public CompletableFuture resolveRealmInternalDirect(String hostUrl) { //url 정제 (로컬, 개발 url 경우 필요) logger.debug("RealmResolver#hostUrl: {}", hostUrl); String finalHostUrl = UrlExtractor.getOriginalHost(hostUrl); logger.debug("RealmResolver#finalHostUrl: {}", finalHostUrl); return CompletableFuture.supplyAsync(() -> { try { Optional siteOptional = siteRepository.findByUrl(finalHostUrl); if (siteOptional.isPresent()) { Site site = siteOptional.get(); if(site != null){ if (site.getRealm() == null) { logger.error("Tenant not found for site with URL: {}", finalHostUrl); throw new RealmNotFoundException("Tenant not found for site with URL: " + finalHostUrl); } String tenantName = site.getRealm().getName(); logger.info("Resolved tenant name: {}, sysDvCd: {}", tenantName, site.getSysDvCd()); //return tenantName.concat(":").concat(site.getSiteCode()); return tenantName.concat(":") .concat(site.getSiteCode()) .concat(":") .concat(site.getSysDvCd()); }else{ throw new RealmNotFoundException("Tenant not found for site with URL: " + finalHostUrl); } } else { logger.error("No site found for URL: {}", finalHostUrl); throw new RealmNotFoundException("No site found for URL: " + finalHostUrl); } } catch (WnbtRestException wre) { throw new WnbtRestException(wre.getMessage()); } catch (Exception e) { logger.error("Failed to resolve tenant for host URL: {}", finalHostUrl, e); throw new RealmNotFoundException("Failed to resolve tenant for host URL: " + finalHostUrl, e); } }, executorService); } }