001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.http.classic.remote; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.commons.utils.Shorts.*; 021import static org.apache.juneau.commons.utils.StringUtils.*; 022 023import java.lang.reflect.*; 024import java.util.*; 025 026import org.apache.juneau.commons.lang.*; 027import org.apache.juneau.commons.reflect.*; 028import org.apache.juneau.commons.utils.*; 029import org.apache.juneau.http.remote.*; 030 031/** 032 * Contains the meta-data about a remote proxy REST interface. 033 * 034 * <p> 035 * Captures the information in {@link Remote @Remote} annotations for caching and reuse. 036 * 037 * <h5 class='section'>See Also:</h5><ul> 038 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a> 039 * </ul> 040 */ 041public class RrpcInterfaceMeta { 042 043 private static final AnnotationProvider AP = AnnotationProvider.INSTANCE; 044 045 private final Map<Method,RrpcInterfaceMethodMeta> methods; 046 private final Map<String,RrpcInterfaceMethodMeta> methodsByPath; 047 private final String path; 048 private final Class<?> c; 049 050 /** 051 * Constructor. 052 * 053 * @param c 054 * The interface class annotated with a {@link Remote @Remote} annotation. 055 * <br>Note that the annotations are optional. 056 * <br>Must not be <jk>null</jk>. 057 * @param uri 058 * The absolute URL of the remote REST interface that implements this proxy interface. 059 * <br>This is only used on the client side. 060 * <br>Can be <jk>null</jk>, in which case each method's URL is prefixed with the literal text <js>"null"</js>. 061 */ 062 public RrpcInterfaceMeta(Class<?> c, String uri) { 063 this.c = c; 064 Holder<String> path2 = Holder.of(""); 065 var ci = ClassInfo.of(c); 066 067 rstream(AP.find(Remote.class, ci)).map(x -> x.inner().path()).filter(Shorts::ine).forEach(x -> path2.set(trimSlashes(x))); 068 069 Map<Method,RrpcInterfaceMethodMeta> methods2 = map(); 070 ci.getPublicMethods().forEach(x -> methods2.put(x.inner(), new RrpcInterfaceMethodMeta(uri, x.inner()))); 071 072 Map<String,RrpcInterfaceMethodMeta> methodsByPath2 = map(); 073 methods2.values().forEach(x -> methodsByPath2.put(x.getPath(), x)); 074 075 this.methods = u(methods2); 076 this.methodsByPath = u(methodsByPath2); 077 this.path = path2.get(); 078 } 079 080 /** 081 * Returns the Java class of this interface. 082 * 083 * @return 084 * The Java class of this interface. 085 * <br>Never <jk>null</jk>. 086 */ 087 public Class<?> getJavaClass() { return c; } 088 089 /** 090 * Returns the metadata about the specified method on this interface proxy. 091 * 092 * @param m The method to look up. 093 * @return Metadata about the method or <jk>null</jk> if no metadata was found. 094 */ 095 public RrpcInterfaceMethodMeta getMethodMeta(Method m) { 096 return methods.get(m); 097 } 098 099 /** 100 * Returns the metadata about the specified method on this interface proxy by the path defined on the method. 101 * 102 * @param p The HTTP path to look for. 103 * @return Metadata about the method or <jk>null</jk> if no metadata was found. 104 */ 105 public RrpcInterfaceMethodMeta getMethodMetaByPath(String p) { 106 return methodsByPath.get(p); 107 } 108 109 /** 110 * Returns a map of all methods on this interface proxy keyed by HTTP path. 111 * 112 * @return 113 * A map of all methods on this remote interface keyed by HTTP path. 114 * <br>The keys never have leading slashes. 115 * <br>The map is never <jk>null</jk>. 116 */ 117 public Map<String,RrpcInterfaceMethodMeta> getMethodsByPath() { return methodsByPath; } 118 119 /** 120 * Returns the HTTP path of this interface. 121 * 122 * @return 123 * The HTTP path of this interface. 124 * <br>Never <jk>null</jk>. 125 * <br>Never has leading or trailing slashes. 126 */ 127 public String getPath() { return path; } 128 129 @Override 130 public boolean equals(Object o) { 131 return o instanceof RrpcInterfaceMeta other && eq(this, other, (x, y) -> x.c == y.c); 132 } 133 134 @Override 135 public int hashCode() { 136 return System.identityHashCode(c); 137 } 138}