001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve.java;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.openapi.components.ServiceManager;
021    import com.intellij.openapi.progress.ProgressIndicatorProvider;
022    import com.intellij.openapi.project.Project;
023    import com.intellij.psi.PsiClass;
024    import com.intellij.psi.PsiElementFinder;
025    import com.intellij.psi.PsiPackage;
026    import com.intellij.psi.impl.JavaPsiFacadeImpl;
027    import com.intellij.psi.impl.file.impl.JavaFileManager;
028    import com.intellij.psi.search.GlobalSearchScope;
029    import org.jetbrains.annotations.NotNull;
030    import org.jetbrains.annotations.Nullable;
031    
032    import java.util.List;
033    
034    /**
035     * TODO Temporary class until {@link JavaPsiFacadeImpl} hacked.
036     *
037     * @see JavaPsiFacadeImpl
038     */
039    public class JavaPsiFacadeKotlinHacks {
040        public interface KotlinFinderMarker {}
041    
042        private final JavaFileManager javaFileManager;
043        private final List<PsiElementFinder> extensionPsiElementFinders;
044    
045        public JavaPsiFacadeKotlinHacks(@NotNull Project project) {
046            this.javaFileManager = findJavaFileManager(project);
047            this.extensionPsiElementFinders = Lists.newArrayList();
048            for (PsiElementFinder finder : project.getExtensions(PsiElementFinder.EP_NAME)) {
049                if (!(finder instanceof KotlinFinderMarker)) {
050                    this.extensionPsiElementFinders.add(finder);
051                }
052            }
053        }
054    
055        @NotNull
056        private static JavaFileManager findJavaFileManager(@NotNull Project project) {
057            JavaFileManager javaFileManager = ServiceManager.getService(project, JavaFileManager.class);
058            if (javaFileManager != null) {
059                return javaFileManager;
060            }
061            throw new IllegalStateException("JavaFileManager component is not found in project");
062        }
063    
064        @Nullable
065        public PsiPackage findPackage(@NotNull String qualifiedName) {
066            PsiPackage psiPackage = javaFileManager.findPackage(qualifiedName);
067            if (psiPackage != null) {
068                return psiPackage;
069            }
070    
071            for (PsiElementFinder finder : extensionPsiElementFinders) {
072                psiPackage = finder.findPackage(qualifiedName);
073                if (psiPackage != null) {
074                    return psiPackage;
075                }
076            }
077            return null;
078        }
079    
080        public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
081            ProgressIndicatorProvider.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
082    
083            PsiClass aClass = javaFileManager.findClass(qualifiedName, scope);
084            if (aClass != null) {
085                return aClass;
086            }
087    
088            for (PsiElementFinder finder : extensionPsiElementFinders) {
089                aClass = finder.findClass(qualifiedName, scope);
090                if (aClass != null) {
091                    return aClass;
092                }
093            }
094    
095            return null;
096        }
097    }