Home | History | Annotate | Download | only in typesolvers
      1 /*
      2  * Copyright 2016 Federico Tomassetti
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.github.javaparser.symbolsolver.resolution.typesolvers;
     18 
     19 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
     20 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
     21 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
     22 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
     23 
     24 import java.util.Optional;
     25 
     26 /**
     27  * @author Federico Tomassetti
     28  */
     29 public class ReflectionTypeSolver implements TypeSolver {
     30 
     31     private TypeSolver parent;
     32 
     33     public ReflectionTypeSolver(boolean jreOnly) {
     34         this.jreOnly = jreOnly;
     35     }
     36 
     37     public ReflectionTypeSolver() {
     38         this(true);
     39     }
     40 
     41     private boolean jreOnly;
     42 
     43     @Override
     44     public TypeSolver getParent() {
     45         return parent;
     46     }
     47 
     48     @Override
     49     public void setParent(TypeSolver parent) {
     50         this.parent = parent;
     51     }
     52 
     53     @Override
     54     public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name) {
     55         if (!jreOnly || (name.startsWith("java.") || name.startsWith("javax."))) {
     56             try {
     57                 ClassLoader classLoader = ReflectionTypeSolver.class.getClassLoader();
     58 
     59                 // Some implementations could return null when the class was loaded through the bootstrap classloader
     60                 // see https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getClassLoader--
     61                 if (classLoader == null) {
     62                     throw new RuntimeException("The ReflectionTypeSolver has been probably loaded through the bootstrap class loader. This usage is not supported by the JavaSymbolSolver");
     63                 }
     64 
     65                 Class<?> clazz = classLoader.loadClass(name);
     66                 return SymbolReference.solved(ReflectionFactory.typeDeclarationFor(clazz, getRoot()));
     67             } catch (ClassNotFoundException e) {
     68                 // it could be an inner class
     69                 int lastDot = name.lastIndexOf('.');
     70                 if (lastDot == -1) {
     71                     return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
     72                 } else {
     73                     String parentName = name.substring(0, lastDot);
     74                     String childName = name.substring(lastDot + 1);
     75                     SymbolReference<ResolvedReferenceTypeDeclaration> parent = tryToSolveType(parentName);
     76                     if (parent.isSolved()) {
     77                         Optional<ResolvedReferenceTypeDeclaration> innerClass = parent.getCorrespondingDeclaration().internalTypes()
     78                                 .stream().filter(it -> it.getName().equals(childName)).findFirst();
     79                         if (innerClass.isPresent()) {
     80                             return SymbolReference.solved(innerClass.get());
     81                         } else {
     82                             return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
     83                         }
     84                     } else {
     85                         return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
     86                     }
     87                 }
     88             }
     89         } else {
     90             return SymbolReference.unsolved(ResolvedReferenceTypeDeclaration.class);
     91         }
     92     }
     93 
     94 }
     95