org.jetbrains.plugins.groovy.mvc.MvcFramework.java Source code

Java tutorial

Introduction

Here is the source code for org.jetbrains.plugins.groovy.mvc.MvcFramework.java

Source

/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * 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/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.jetbrains.plugins.groovy.mvc;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.Icon;

import org.consulo.compiler.CompilerPathsManager;
import org.consulo.java.platform.module.extension.JavaModuleExtensionImpl;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import org.mustbe.consulo.roots.ContentFolderScopes;
import org.mustbe.consulo.roots.ContentFolderTypeProvider;
import com.intellij.compiler.options.CompileStepBeforeRun;
import com.intellij.compiler.options.CompileStepBeforeRunNoErrorCheck;
import com.intellij.execution.CantRunException;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunManagerEx;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.CommandLineBuilder;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeView;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryKind;
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.ArchiveFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.util.ArchiveVfsUtil;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.PathUtil;
import com.intellij.util.PathsList;
import com.intellij.util.containers.ContainerUtil;

/**
 * @author peter
 */
@Deprecated //TODO [VISTALL] rewrit it using ModuleExtensions
public abstract class MvcFramework {
    protected static final ExtensionPointName<MvcFramework> EP_NAME = ExtensionPointName
            .create("org.intellij.groovy.mvc.framework");

    private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.mvc.MvcFramework");
    public static final Key<Boolean> CREATE_APP_STRUCTURE = Key.create("CREATE_MVC_APP_STRUCTURE");
    public static final Key<Boolean> UPGRADE = Key.create("UPGRADE");
    @NonNls
    public static final String GROOVY_STARTER_CONF = "/conf/groovy-starter.conf";
    @NonNls
    public static final String XMX_JVM_PARAMETER = "-Xmx";

    public abstract boolean hasSupport(@NotNull Module module);

    public boolean isAuxModule(@NotNull Module module) {
        return isCommonPluginsModule(module) || isGlobalPluginModule(module);
    }

    public boolean hasFrameworkJar(@NotNull Module module) {
        GlobalSearchScope scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false);
        return JavaPsiFacade.getInstance(module.getProject()).findClass(getSomeFrameworkClass(), scope) != null;
    }

    public boolean isCommonPluginsModule(@NotNull Module module) {
        return module.getName().endsWith(getCommonPluginSuffix());
    }

    public List<Module> reorderModulesForMvcView(List<Module> modules) {
        return modules;
    }

    public abstract String getApplicationDirectoryName();

    public void syncSdkAndLibrariesInPluginsModule(@NotNull Module module) {
        final Module pluginsModule = findCommonPluginsModule(module);
        if (pluginsModule != null) {
            MvcModuleStructureUtil.syncAuxModuleSdk(module, pluginsModule, this);
        }
    }

    public boolean isInteractiveConsoleSupported(@NotNull Module module) {
        return false;
    }

    public void runInteractiveConsole(@NotNull Module module) {
        throw new UnsupportedOperationException();
    }

    public abstract void upgradeFramework(@NotNull Module module);

    public void createApplicationIfNeeded(@NotNull final Module module) {
        if (findAppRoot(module) == null && module.getUserData(CREATE_APP_STRUCTURE) == Boolean.TRUE) {
            while (ModuleUtilCore.getSdk(module, JavaModuleExtensionImpl.class) == null) {
                if (Messages.showYesNoDialog(module.getProject(), "Cannot generate " + getDisplayName()
                        + " project structure because JDK is not specified for module \"" + module.getName()
                        + "\".\n" + getDisplayName()
                        + " project will not be created if you don't specify JDK.\nDo you want to specify JDK?",
                        "Error", Messages.getErrorIcon()) == 1) {
                    return;
                }
                ProjectSettingsService.getInstance(module.getProject())
                        .showModuleConfigurationDialog(module.getName(), ClasspathEditor.NAME);
            }
            module.putUserData(CREATE_APP_STRUCTURE, null);
            final GeneralCommandLine commandLine = getCreationCommandLine(module);
            if (commandLine == null)
                return;

            MvcConsole.executeProcess(module, commandLine, new Runnable() {
                public void run() {
                    VirtualFile root = findAppRoot(module);
                    if (root == null)
                        return;

                    PsiDirectory psiDir = PsiManager.getInstance(module.getProject()).findDirectory(root);
                    IdeView ide = LangDataKeys.IDE_VIEW.getData(DataManager.getInstance().getDataContext());
                    if (ide != null)
                        ide.selectElement(psiDir);

                    //also here comes fileCreated(application.properties) which manages roots and run configuration
                }
            }, true);
        }

    }

    @Nullable
    protected GeneralCommandLine getCreationCommandLine(Module module) {
        String message = "Create default " + getDisplayName() + " directory structure in module '"
                + module.getName() + "'?";
        final int result = Messages.showDialog(module.getProject(), message,
                "Create " + getDisplayName() + " application",
                new String[] { "Run 'create-&app'", "Run 'create-&plugin'", "&Cancel" }, 0, getIcon());
        if (result < 0 || result > 1) {
            return null;
        }

        return createCommandAndShowErrors(null, module, true,
                new MvcCommand(result == 0 ? "create-app" : "create-plugin"));
    }

    public abstract void updateProjectStructure(@NotNull final Module module);

    public abstract void ensureRunConfigurationExists(@NotNull Module module);

    @Nullable
    public VirtualFile findAppRoot(@Nullable Module module) {
        if (module == null)
            return null;

        String appDirName = getApplicationDirectoryName();

        for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) {
            if (root.findChild(appDirName) != null)
                return root;
        }

        return null;
    }

    @Nullable
    public VirtualFile findAppRoot(@Nullable PsiElement element) {
        VirtualFile appDirectory = findAppDirectory(element);
        return appDirectory == null ? null : appDirectory.getParent();
    }

    @Nullable
    public VirtualFile findAppDirectory(@Nullable Module module) {
        if (module == null)
            return null;

        String appDirName = getApplicationDirectoryName();

        for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) {
            VirtualFile res = root.findChild(appDirName);
            if (res != null)
                return res;
        }

        return null;
    }

    @Nullable
    public VirtualFile findAppDirectory(@Nullable PsiElement element) {
        if (element == null)
            return null;

        PsiFile containingFile = element.getContainingFile().getOriginalFile();
        VirtualFile file = containingFile.getVirtualFile();
        if (file == null)
            return null;

        ProjectFileIndex index = ProjectRootManager.getInstance(containingFile.getProject()).getFileIndex();

        VirtualFile root = index.getContentRootForFile(file);
        if (root == null)
            return null;

        return root.findChild(getApplicationDirectoryName());
    }

    @Nullable
    public abstract VirtualFile getSdkRoot(@Nullable Module module);

    public abstract String getUserLibraryName();

    protected List<File> getImplicitClasspathRoots(@NotNull Module module) {
        final List<File> toExclude = new ArrayList<File>();

        VirtualFile sdkRoot = getSdkRoot(module);
        if (sdkRoot != null)
            toExclude.add(VfsUtil.virtualToIoFile(sdkRoot));

        ContainerUtil.addIfNotNull(getCommonPluginsDir(module), toExclude);
        final VirtualFile appRoot = findAppRoot(module);
        if (appRoot != null) {
            VirtualFile pluginDir = appRoot.findChild(MvcModuleStructureUtil.PLUGINS_DIRECTORY);
            if (pluginDir != null)
                toExclude.add(VfsUtil.virtualToIoFile(pluginDir));

            VirtualFile libDir = appRoot.findChild("lib");
            if (libDir != null)
                toExclude.add(VfsUtil.virtualToIoFile(libDir));
        }

        final Library library = MvcModuleStructureUtil.findUserLibrary(module, getUserLibraryName());
        if (library != null) {
            for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
                toExclude.add(VfsUtil.virtualToIoFile(PathUtil.getLocalFile(file)));
            }
        }
        return toExclude;
    }

    private PathsList removeFrameworkStuff(Module module, List<VirtualFile> rootFiles) {
        final List<File> toExclude = getImplicitClasspathRoots(module);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Before removing framework stuff: " + rootFiles);
            LOG.debug("Implicit roots:" + toExclude);
        }

        PathsList scriptClassPath = new PathsList();
        eachRoot: for (VirtualFile file : rootFiles) {
            for (final File excluded : toExclude) {
                if (VfsUtil.isAncestor(excluded, VfsUtil.virtualToIoFile(file), false)) {
                    continue eachRoot;
                }
            }
            scriptClassPath.add(file);
        }
        return scriptClassPath;
    }

    public PathsList getApplicationClassPath(Module module) {
        final List<VirtualFile> classPath = OrderEnumerator.orderEntries(module).recursively().withoutSdk()
                .getPathsList().getVirtualFiles();

        retainOnlyJarsAndDirectories(classPath);

        removeModuleOutput(module, classPath);

        final Module pluginsModule = findCommonPluginsModule(module);
        if (pluginsModule != null) {
            removeModuleOutput(pluginsModule, classPath);
        }

        return removeFrameworkStuff(module, classPath);
    }

    public abstract boolean updatesWholeProject();

    private static void retainOnlyJarsAndDirectories(List<VirtualFile> woSdk) {
        for (Iterator<VirtualFile> iterator = woSdk.iterator(); iterator.hasNext();) {
            VirtualFile file = iterator.next();
            final VirtualFile local = ArchiveVfsUtil.getVirtualFileForJar(file);
            final boolean dir = file.isDirectory();
            final String name = file.getName();
            if (LOG.isDebugEnabled()) {
                LOG.debug(
                        "Considering: " + file.getPath() + "; local=" + local + "; dir=" + dir + "; name=" + name);
            }
            if (dir || local != null) {
                continue;
            }
            if (name.endsWith(".jar")) {
                continue;
            }
            LOG.debug("Removing");
            iterator.remove();
        }
    }

    private static void removeModuleOutput(Module module, List<VirtualFile> from) {
        CompilerPathsManager compilerPathsManager = CompilerPathsManager.getInstance(module.getProject());
        for (ContentFolderTypeProvider contentFolderType : ContentFolderTypeProvider
                .filter(ContentFolderScopes.productionAndTest())) {
            from.remove(compilerPathsManager.getCompilerOutput(module, contentFolderType));
        }
    }

    public abstract JavaParameters createJavaParameters(@NotNull Module module, boolean forCreation,
            boolean forTests, boolean classpathFromDependencies, @Nullable String jvmParams,
            @NotNull MvcCommand command) throws ExecutionException;

    protected static void ensureRunConfigurationExists(Module module, ConfigurationType configurationType,
            String name) {
        final RunManagerEx runManager = RunManagerEx.getInstanceEx(module.getProject());
        for (final RunConfiguration runConfiguration : runManager.getConfigurations(configurationType)) {
            if (runConfiguration instanceof MvcRunConfiguration
                    && ((MvcRunConfiguration) runConfiguration).getModule() == module) {
                return;
            }
        }

        final ConfigurationFactory factory = configurationType.getConfigurationFactories()[0];
        final RunnerAndConfigurationSettings runSettings = runManager.createRunConfiguration(name, factory);
        final MvcRunConfiguration configuration = (MvcRunConfiguration) runSettings.getConfiguration();
        configuration.setModule(module);
        runManager.addConfiguration(runSettings, false);
        runManager.setActiveConfiguration(runSettings);

        RunManagerEx.disableTasks(module.getProject(), configuration, CompileStepBeforeRun.ID,
                CompileStepBeforeRunNoErrorCheck.ID);
    }

    public abstract String getFrameworkName();

    public String getDisplayName() {
        return getFrameworkName();
    }

    public abstract Icon getIcon(); // 16*16

    public abstract Icon getToolWindowIcon(); // 13*13

    public abstract String getSdkHomePropertyName();

    @Nullable
    public GeneralCommandLine createCommandAndShowErrors(@NotNull Module module, @NotNull String command,
            String... args) {
        return createCommandAndShowErrors(null, module, new MvcCommand(command, args));
    }

    @Nullable
    public GeneralCommandLine createCommandAndShowErrors(@NotNull Module module, @NotNull MvcCommand command) {
        return createCommandAndShowErrors(null, module, command);
    }

    @Nullable
    public GeneralCommandLine createCommandAndShowErrors(@Nullable String vmOptions, @NotNull Module module,
            @NotNull MvcCommand command) {
        return createCommandAndShowErrors(vmOptions, module, false, command);
    }

    @Nullable
    public GeneralCommandLine createCommandAndShowErrors(@Nullable String vmOptions, @NotNull Module module,
            final boolean forCreation, @NotNull MvcCommand command) {
        try {
            return createCommand(module, vmOptions, forCreation, command);
        } catch (ExecutionException e) {
            Messages.showErrorDialog(e.getMessage(), "Failed to run grails command: " + command);
            return null;
        }
    }

    @NotNull
    public GeneralCommandLine createCommand(@NotNull Module module, @Nullable String jvmParams, boolean forCreation,
            @NotNull MvcCommand command) throws ExecutionException {
        final JavaParameters params = createJavaParameters(module, forCreation, false, true, jvmParams, command);
        addJavaHome(params, module);

        final GeneralCommandLine commandLine = createCommandLine(params);

        final VirtualFile griffonHome = getSdkRoot(module);
        if (griffonHome != null) {
            commandLine.getEnvironment().put(getSdkHomePropertyName(),
                    FileUtil.toSystemDependentName(griffonHome.getPath()));
        }

        final VirtualFile root = findAppRoot(module);
        final File ioRoot = root != null ? VfsUtilCore.virtualToIoFile(root) : new File(module.getModuleDirPath());
        commandLine.setWorkDirectory(forCreation ? ioRoot.getParentFile() : ioRoot);

        return commandLine;
    }

    public static void addJavaHome(@NotNull JavaParameters params, @NotNull Module module) {
        final Sdk sdk = ModuleUtilCore.getSdk(module, JavaModuleExtensionImpl.class);
        if (sdk != null && sdk.getSdkType() instanceof JavaSdkType) {
            String path = StringUtil.trimEnd(sdk.getHomePath(), File.separator);
            if (StringUtil.isNotEmpty(path)) {
                Map<String, String> env = params.getEnv();
                if (env == null) {
                    env = new HashMap<String, String>();
                    params.setEnv(env);
                }

                env.put("JAVA_HOME", FileUtil.toSystemDependentName(path));
            }
        }
    }

    public static GeneralCommandLine createCommandLine(@NotNull JavaParameters params) throws CantRunException {
        return CommandLineBuilder.createFromJavaParameters(params);
    }

    private void extractPlugins(Project project, @Nullable VirtualFile pluginRoot, Map<String, VirtualFile> res) {
        if (pluginRoot != null) {
            VirtualFile[] children = pluginRoot.getChildren();
            if (children != null) {
                for (VirtualFile child : children) {
                    String pluginName = getInstalledPluginNameByPath(project, child);
                    if (pluginName != null) {
                        res.put(pluginName, child);
                    }
                }
            }
        }
    }

    public Collection<VirtualFile> getAllPluginRoots(@NotNull Module module, boolean refresh) {
        return getCommonPluginRoots(module, refresh);
    }

    public void collectCommonPluginRoots(Map<String, VirtualFile> result, @NotNull Module module, boolean refresh) {
        if (isCommonPluginsModule(module)) {
            for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) {
                String pluginName = getInstalledPluginNameByPath(module.getProject(), root);
                if (pluginName != null) {
                    result.put(pluginName, root);
                }
            }
        } else {
            VirtualFile root = findAppRoot(module);
            if (root == null)
                return;

            extractPlugins(module.getProject(), root.findChild(MvcModuleStructureUtil.PLUGINS_DIRECTORY), result);
            extractPlugins(module.getProject(),
                    MvcModuleStructureUtil.findFile(getCommonPluginsDir(module), refresh), result);
            extractPlugins(module.getProject(),
                    MvcModuleStructureUtil.findFile(getGlobalPluginsDir(module), refresh), result);
        }
    }

    public Collection<VirtualFile> getCommonPluginRoots(@NotNull Module module, boolean refresh) {
        Map<String, VirtualFile> result = new HashMap<String, VirtualFile>();
        collectCommonPluginRoots(result, module, refresh);
        return result.values();
    }

    @Nullable
    public Module findCommonPluginsModule(@NotNull Module module) {
        return ModuleManager.getInstance(module.getProject()).findModuleByName(getCommonPluginsModuleName(module));
    }

    public boolean isGlobalPluginModule(@NotNull Module module) {
        return module.getName().startsWith(getGlobalPluginsModuleName());
    }

    @Nullable
    public File getSdkWorkDir(@NotNull Module module) {
        return getDefaultSdkWorkDir(module);
    }

    @Nullable
    public abstract File getDefaultSdkWorkDir(@NotNull Module module);

    @Nullable
    public File getGlobalPluginsDir(@NotNull Module module) {
        final File sdkWorkDir = getSdkWorkDir(module);
        return sdkWorkDir == null ? null : new File(sdkWorkDir, "global-plugins");
    }

    @Nullable
    public File getCommonPluginsDir(@NotNull Module module) {
        final File grailsWorkDir = getSdkWorkDir(module);
        if (grailsWorkDir == null)
            return null;

        final String applicationName = getApplicationName(module);
        if (applicationName == null)
            return null;

        return new File(grailsWorkDir, "projects/" + applicationName + "/plugins");
    }

    public String getApplicationName(Module module) {
        final VirtualFile root = findAppRoot(module);
        if (root == null)
            return null;
        return root.getName();
    }

    protected abstract String getCommonPluginSuffix();

    public abstract String getGlobalPluginsModuleName();

    public String getCommonPluginsModuleName(Module module) {
        return module.getName() + getCommonPluginSuffix();
    }

    public abstract boolean isSDKLibrary(Library library);

    public abstract MvcProjectStructure createProjectStructure(@NotNull Module module, boolean auxModule);

    public abstract LibraryKind getLibraryKind();

    public abstract String getSomeFrameworkClass();

    public static void addAvailableSystemScripts(final Collection<String> result, @NotNull Module module) {
        VirtualFile scriptRoot = null;

        GlobalSearchScope searchScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false);

        for (PsiClass aClass : JavaPsiFacade.getInstance(module.getProject()).findClasses("CreateApp_",
                searchScope)) {
            PsiClass superClass = aClass.getSuperClass();
            if (superClass != null
                    && GroovyCommonClassNames.GROOVY_LANG_SCRIPT.equals(superClass.getQualifiedName())) {
                PsiFile psiFile = aClass.getContainingFile();
                if (psiFile != null) {
                    VirtualFile file = psiFile.getVirtualFile();
                    if (file != null && file.getFileSystem() instanceof ArchiveFileSystem) {
                        VirtualFile parent = file.getParent();
                        if (parent != null && parent.findChild("Console.class") != null) {
                            scriptRoot = parent;
                            break;
                        }
                    }
                }
            }
        }

        if (scriptRoot == null)
            return;

        Pattern scriptPattern = Pattern.compile("([A-Za-z0-9]+)_?\\.class");

        for (VirtualFile file : scriptRoot.getChildren()) {
            Matcher matcher = scriptPattern.matcher(file.getName());
            if (matcher.matches()) {
                result.add(GroovyNamesUtil.camelToSnake(matcher.group(1)));
            }
        }

    }

    public abstract boolean isToReformatOnCreation(VirtualFile file);

    public static void addAvailableScripts(final Collection<String> result, @Nullable final VirtualFile root) {
        if (root == null || !root.isDirectory()) {
            return;
        }

        final VirtualFile scripts = root.findChild("scripts");

        if (scripts == null || !scripts.isDirectory()) {
            return;
        }

        for (VirtualFile child : scripts.getChildren()) {
            if (isScriptFile(child)) {
                result.add(GroovyNamesUtil.camelToSnake(child.getNameWithoutExtension()));
            }
        }
    }

    @Nullable
    public static MvcFramework findCommonPluginModuleFramework(Module module) {
        for (MvcFramework framework : EP_NAME.getExtensions()) {
            if (framework.isCommonPluginsModule(module)) {
                return framework;
            }
        }
        return null;
    }

    public static boolean isScriptFileName(String fileName) {
        return fileName.endsWith(GroovyFileType.DEFAULT_EXTENSION) && fileName.charAt(0) != '_';
    }

    private static boolean isScriptFile(VirtualFile virtualFile) {
        return !virtualFile.isDirectory() && isScriptFileName(virtualFile.getName());
    }

    @Nullable
    public String getInstalledPluginNameByPath(Project project, @NotNull VirtualFile pluginPath) {
        VirtualFile pluginXml = pluginPath.findChild("plugin.xml");
        if (pluginXml == null)
            return null;

        PsiFile pluginXmlPsi = PsiManager.getInstance(project).findFile(pluginXml);
        if (!(pluginXmlPsi instanceof XmlFile))
            return null;

        XmlTag rootTag = ((XmlFile) pluginXmlPsi).getRootTag();
        if (rootTag == null || !"plugin".equals(rootTag.getName()))
            return null;

        XmlAttribute attrName = rootTag.getAttribute("name");
        if (attrName == null)
            return null;

        String res = attrName.getValue();
        if (res == null)
            return null;

        res = res.trim();
        if (res.length() == 0)
            return null;

        return res;
    }

    @Nullable
    public static MvcFramework getInstance(@Nullable final Module module) {
        if (module == null) {
            return null;
        }

        final Project project = module.getProject();

        return CachedValuesManager.getManager(project).getCachedValue(module,
                new CachedValueProvider<MvcFramework>() {
                    @Override
                    public Result<MvcFramework> compute() {
                        final ModificationTracker tracker = MvcModuleStructureSynchronizer.getInstance(project)
                                .getFileAndRootsModificationTracker();
                        for (final MvcFramework framework : EP_NAME.getExtensions()) {
                            if (framework.hasSupport(module)) {
                                return Result.create(framework, tracker);
                            }
                        }
                        return Result.create(null, tracker);

                    }
                });
    }

    @Nullable
    public static MvcFramework getInstanceBySdk(@NotNull Module module) {
        for (final MvcFramework framework : EP_NAME.getExtensions()) {
            if (framework.getSdkRoot(module) != null) {
                return framework;
            }
        }
        return null;
    }

}