/* * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com * * Licensed 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/LICENSE2.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 com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode; import com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodPool; import com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodSimulator; import com.sebastian_daschner.jaxrs_analyzer.model.Types; import com.sebastian_daschner.jaxrs_analyzer.model.elements.Element; import com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse; import com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonValue; import com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction; import com.sebastian_daschner.jaxrs_analyzer.model.methods.ProjectMethod; import com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult; import java.util.List; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; /** * Analyzes JAX-RS resource methods. This class is thread-safe. * * @author Sebastian Daschner */ class ResourceMethodContentAnalyzer extends MethodContentAnalyzer { private final Lock lock = new ReentrantLock(); /** * Analyzes the method (including own project methods). * * @param methodResult The method result */ void analyze(final MethodResult methodResult) { lock.lock(); try { buildPackagePrefix(methodResult.getParentResource().getOriginalClass()); final List<Instruction> visitedInstructions = interpretRelevantInstructions(methodResult.getInstructions()); // find project defined methods in invoke occurrences final Set<ProjectMethod> projectMethods = findProjectMethods(visitedInstructions); // add project methods to global method pool projectMethods.forEach(MethodPool.getInstance()::addProjectMethod); Element returnedElement = new MethodSimulator().simulate(visitedInstructions); final String returnType = methodResult.getOriginalMethodSignature().getReturnType(); // void resource methods are interpreted later; stop analyzing on error if (Types.PRIMITIVE_VOID.equals(returnType)) { return; } if (returnedElement == null) { // happens for abstract methods or if there is no return return; } final Set<Object> possibleObjects = returnedElement.getPossibleValues().stream().filter(o -> !(o instanceof HttpResponse)) .collect(Collectors.toSet()); // for non-Response methods add a default if there are non-Response objects or none objects at all if (!Types.RESPONSE.equals(returnType)) { final HttpResponse defaultResponse = new HttpResponse(); if (Types.OBJECT.equals(returnType)) defaultResponse.getEntityTypes().addAll(returnedElement.getTypes()); else defaultResponse.getEntityTypes().add(returnType); possibleObjects.stream().filter(o -> o instanceof JsonValue).map(o -> (JsonValue) o).forEach(defaultResponse.getInlineEntities()::add); methodResult.getResponses().add(defaultResponse); } // add Response results as well returnedElement.getPossibleValues().stream().filter(o -> o instanceof HttpResponse).map(o -> (HttpResponse) o).forEach(methodResult.getResponses()::add); } finally { lock.unlock(); } } }