package com.navercorp.pinpoint.testapp.controller; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; /** * @author koo.taejin */ import com.navercorp.pinpoint.testapp.util.Description; @Controller(value = "apisController") public class ApisController { private final RequestMappingHandlerMapping handlerMapping; private final Map<String, SortedSet<RequestMappedUri>> apiMappings = new TreeMap<String, SortedSet<RequestMappedUri>>(String.CASE_INSENSITIVE_ORDER); @Autowired public ApisController(RequestMappingHandlerMapping handlerMapping) { this.handlerMapping = handlerMapping; } @PostConstruct private void initApiMappings() { Map<RequestMappingInfo, HandlerMethod> requestMappedHandlers = this.handlerMapping.getHandlerMethods(); for (Map.Entry<RequestMappingInfo, HandlerMethod> requestMappedHandlerEntry : requestMappedHandlers.entrySet()) { RequestMappingInfo requestMappingInfo = requestMappedHandlerEntry.getKey(); HandlerMethod handlerMethod = requestMappedHandlerEntry.getValue(); Class<?> handlerMethodBeanClazz = handlerMethod.getBeanType(); if (handlerMethodBeanClazz == this.getClass()) { continue; } String controllerName = handlerMethodBeanClazz.getSimpleName(); Set<String> mappedRequests = requestMappingInfo.getPatternsCondition().getPatterns(); SortedSet<RequestMappedUri> alreadyMappedRequests = this.apiMappings.get(controllerName); if (alreadyMappedRequests == null) { alreadyMappedRequests = new TreeSet<RequestMappedUri>(RequestMappedUri.MAPPED_URI_ORDER); this.apiMappings.put(controllerName, alreadyMappedRequests); } alreadyMappedRequests.addAll(createRequestMappedApis(handlerMethod, mappedRequests)); } } private Set<RequestMappedUri> createRequestMappedApis(HandlerMethod handlerMethod, Set<String> mappedUris) { if (CollectionUtils.isEmpty(mappedUris)) { return Collections.emptySet(); } Set<RequestMappedUri> requestMappedUris = new HashSet<RequestMappedUri>(mappedUris.size()); Description description = handlerMethod.getMethodAnnotation(Description.class); for (String mappedUri : mappedUris) { requestMappedUris.add(new RequestMappedUri(mappedUri, description)); } return requestMappedUris; } @RequestMapping(value = { "/index.html", "/apis" }, method = RequestMethod.GET) public String apis(Model model) { model.addAttribute("apiMappings", this.apiMappings); return "apis"; } public static class RequestMappedUri { private final String mappedUri; private final String description; private RequestMappedUri(String mappedUri, Description description) { if (mappedUri == null) { throw new IllegalArgumentException("mappedUri must not be null"); } this.mappedUri = mappedUri; this.description = description == null ? "" : description.value(); } public String getMappedUri() { return this.mappedUri; } public String getDescription() { return this.description; } private static final Comparator<RequestMappedUri> MAPPED_URI_ORDER = new Comparator<RequestMappedUri>() { @Override public int compare(RequestMappedUri arg0, RequestMappedUri arg1) { if (arg0 == null && arg1 == null) return 0; if (arg1 == null) return -1; if (arg0 == null) return 1; return String.CASE_INSENSITIVE_ORDER.compare(arg0.mappedUri, arg1.mappedUri); } }; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((mappedUri == null) ? 0 : mappedUri.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RequestMappedUri other = (RequestMappedUri) obj; if (description == null) { if (other.description != null) return false; } else if (!description.equals(other.description)) return false; if (mappedUri == null) { if (other.mappedUri != null) return false; } else if (!mappedUri.equals(other.mappedUri)) return false; return true; } @Override public String toString() { return "RequestMappedUri [mappedUri=" + mappedUri + ", description=" + description + "]"; } } }