blob: 07877dea11db5e6ff17b667fe05df66da21d997d [file] [log] [blame]
/*
* 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.aries.jax.rs.whiteboard.internal.introspection;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.MethodDispatcher;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.utils.AnnotationUtils;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
import org.osgi.service.jaxrs.runtime.dto.ResourceMethodInfoDTO;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ClassIntrospector {
public static Collection<ResourceMethodInfoDTO> getResourceMethodInfos(
Class<?> clazz, Bus bus) {
ClassResourceInfo classResourceInfo =
ResourceUtils.createClassResourceInfo(
clazz, clazz, true, true, bus);
Stream<ResourceMethodInfoDTO> convert = convert(
new HashSet<>(), "/", null, null, null, null,
true, classResourceInfo);
return convert.collect(Collectors.toList());
}
private static Stream<ResourceMethodInfoDTO> convert(
Set<ClassResourceInfo> visited,
String parentPath, String defaultHttpMethod,
List<MediaType> defaultConsumeTypes,
List<MediaType> defaultProduceTypes,
Set<String> defaultNameBindings, boolean recurse,
ClassResourceInfo classResourceInfo) {
visited.add(classResourceInfo);
String path = parentPath + getPathSafe(classResourceInfo);
List<MediaType> consumeMime = getConsumesInfo(
classResourceInfo.getResourceClass());
if (consumeMime == null) {
consumeMime = defaultConsumeTypes;
}
List<MediaType> produceMime = getProducesInfo(
classResourceInfo.getResourceClass());
if (produceMime == null) {
produceMime = defaultProduceTypes;
}
Set<String> nameBindings = classResourceInfo.getNameBindings();
if (nameBindings.isEmpty()) {
nameBindings = defaultNameBindings;
}
MethodDispatcher methodDispatcher =
classResourceInfo.getMethodDispatcher();
Set<OperationResourceInfo> operationResourceInfos =
methodDispatcher.getOperationResourceInfos();
List<MediaType> consumeParam = consumeMime == null ? null : new ArrayList<>(consumeMime);
List<MediaType> produceParam = produceMime == null ? null : new ArrayList<>(produceMime);
HashSet<String> nameBindingsParam = nameBindings == null ? null : new HashSet<>(nameBindings);
Stream<ResourceMethodInfoDTO> stream =
operationResourceInfos.stream().
flatMap(
ori -> convert(
visited, path, defaultHttpMethod, consumeParam,
produceParam, nameBindingsParam, recurse, ori)
).collect(
Collectors.toList()
).stream();
visited.remove(classResourceInfo);
return stream;
}
private static Stream<ResourceMethodInfoDTO> convert(
Set<ClassResourceInfo> visited,
String parentPath, String defaultHttpMethod,
List<MediaType> defaultConsumeTypes,
List<MediaType> defaultProduceTypes,
Set<String> defaultNameBindings, boolean recurse,
OperationResourceInfo operationResourceInfo) {
List<MediaType> consumeTypes = getConsumesInfo(
operationResourceInfo.getAnnotatedMethod());
if (consumeTypes == null) {
consumeTypes = defaultConsumeTypes;
}
List<MediaType> produceTypes = getProducesInfo(
operationResourceInfo.getAnnotatedMethod());
if (produceTypes == null) {
produceTypes = defaultProduceTypes;
}
String httpMethod = operationResourceInfo.getHttpMethod();
if (httpMethod == null) {
httpMethod = defaultHttpMethod;
}
Set<String> nameBindings = operationResourceInfo.getNameBindings();
if (nameBindings.isEmpty()) {
nameBindings = defaultNameBindings;
}
String path = parentPath +
operationResourceInfo.getURITemplate().getValue();
if (operationResourceInfo.isSubResourceLocator()) {
ClassResourceInfo classResourceInfo =
operationResourceInfo.getClassResourceInfo();
Class<?> returnType =
operationResourceInfo.getAnnotatedMethod().getReturnType();
ClassResourceInfo subResource = classResourceInfo.getSubResource(
returnType, returnType);
if (subResource != null) {
if (recurse) {
return convert(visited,
path, httpMethod, consumeTypes, produceTypes,
nameBindings, !visited.contains(subResource),
subResource);
}
else {
return Stream.empty();
}
}
}
ResourceMethodInfoDTO resourceMethodInfoDTO =
new ResourceMethodInfoDTO();
resourceMethodInfoDTO.consumingMimeType = consumeTypes == null ? null :
consumeTypes.stream().
map(
MediaType::toString
).toArray(
String[]::new
);
resourceMethodInfoDTO.producingMimeType = produceTypes == null ? null :
produceTypes.stream().
map(
MediaType::toString
).toArray(
String[]::new
);
resourceMethodInfoDTO.nameBindings = nameBindings == null ? null :
nameBindings.toArray(new String[0]);
resourceMethodInfoDTO.path = normalize(path);
resourceMethodInfoDTO.method = httpMethod;
return Stream.of(resourceMethodInfoDTO);
}
private static List<MediaType> getConsumesInfo(Method method) {
Consumes consumes = AnnotationUtils.getMethodAnnotation(
method, Consumes.class);
return consumes == null ? null : JAXRSUtils.getMediaTypes(consumes.value());
}
private static List<MediaType> getConsumesInfo(Class<?> clazz) {
Consumes consumes = AnnotationUtils.getClassAnnotation(
clazz, Consumes.class);
return consumes == null ? null : JAXRSUtils.getMediaTypes(consumes.value());
}
private static String getPathSafe(ClassResourceInfo classResourceInfo) {
Path path = classResourceInfo.getPath();
if (path == null) {
return "/";
}
return path.value();
}
private static List<MediaType> getProducesInfo(Method method) {
Produces produces = AnnotationUtils.getMethodAnnotation(
method, Produces.class);
return produces == null ? null : JAXRSUtils.getMediaTypes(produces.value());
}
private static List<MediaType> getProducesInfo(Class<?> clazz) {
Produces produces = AnnotationUtils.getClassAnnotation(
clazz, Produces.class);
return produces == null ? null : JAXRSUtils.getMediaTypes(produces.value());
}
private static String normalize(String path) {
return "/" + Arrays.stream(path.split("/")).
filter(s -> !s.isEmpty()).
collect(Collectors.joining("/"));
}
}