/*
* Copyright 2013 The authors
* 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 com.intellij.struts2.facet;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.facet.ui.FacetBasedFrameworkSupportProvider;
import com.intellij.framework.library.DownloadableLibraryService;
import com.intellij.framework.library.FrameworkSupportWithLibrary;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurableBase;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportProviderBase;
import com.intellij.ide.util.frameworkSupport.FrameworkVersion;
import com.intellij.jam.model.util.JamCommonUtil;
import com.intellij.javaee.model.xml.web.Filter;
import com.intellij.javaee.model.xml.web.FilterMapping;
import com.intellij.javaee.model.xml.web.WebApp;
import com.intellij.javaee.web.facet.WebFacet;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.struts2.StrutsConstants;
import com.intellij.struts2.StrutsFileTemplateProvider;
import com.intellij.struts2.facet.ui.StrutsConfigsSearcher;
import com.intellij.struts2.facet.ui.StrutsFileSet;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.descriptors.ConfigFile;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* "Add Framework" support.
*
* @author Yann Cébron
*/
public class StrutsFrameworkSupportProvider extends FacetBasedFrameworkSupportProvider<StrutsFacet> {
private static final Logger LOG = Logger.getInstance("#com.intellij.struts2.facet.StrutsFrameworkSupportProvider");
public StrutsFrameworkSupportProvider() {
super(StrutsFacetType.getInstance());
}
public String getTitle() {
return UIUtil.replaceMnemonicAmpersand("Struts &2");
}
@NotNull
@Override
public FrameworkSupportConfigurableBase createConfigurable(@NotNull final FrameworkSupportModel model) {
return new Struts2FrameworkSupportConfigurable(this, model, getVersions(), getVersionLabelText());
}
protected void setupConfiguration(final StrutsFacet strutsFacet,
final ModifiableRootModel modifiableRootModel, final FrameworkVersion version) {
}
@Override
protected void onFacetCreated(final StrutsFacet strutsFacet,
final ModifiableRootModel modifiableRootModel,
final FrameworkVersion version) {
final Module module = strutsFacet.getModule();
StartupManager.getInstance(module.getProject()).runWhenProjectIsInitialized(new Runnable() {
public void run() {
final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
if (sourceRoots.length <= 0) {
return;
}
final PsiDirectory directory = PsiManager.getInstance(module.getProject()).findDirectory(sourceRoots[0]);
if (directory == null ||
directory.findFile(StrutsConstants.STRUTS_XML_DEFAULT_FILENAME) != null) {
return;
}
final StrutsFileTemplateProvider templateProvider = new StrutsFileTemplateProvider(module);
final FileTemplate strutsXmlTemplate = templateProvider.determineFileTemplate();
try {
final StrutsFacetConfiguration strutsFacetConfiguration = strutsFacet.getConfiguration();
// create empty struts.xml & fileset with all found struts-*.xml files (struts2.jar, plugins)
final PsiElement psiElement = FileTemplateUtil.createFromTemplate(strutsXmlTemplate,
StrutsConstants.STRUTS_XML_DEFAULT_FILENAME,
null,
directory);
final Set<StrutsFileSet> empty = Collections.emptySet();
final StrutsFileSet fileSet = new StrutsFileSet(StrutsFileSet.getUniqueId(empty),
StrutsFileSet.getUniqueName("Default File Set", empty),
strutsFacetConfiguration);
fileSet.addFile(((XmlFile) psiElement).getVirtualFile());
final StrutsConfigsSearcher searcher = new StrutsConfigsSearcher(module);
searcher.search();
final MultiMap<VirtualFile, PsiFile> jarConfigFiles = searcher.getJars();
for (final VirtualFile virtualFile : jarConfigFiles.keySet()) {
final Collection<PsiFile> psiFiles = jarConfigFiles.get(virtualFile);
for (final PsiFile psiFile : psiFiles) {
fileSet.addFile(psiFile.getVirtualFile());
}
}
strutsFacetConfiguration.getFileSets().add(fileSet);
// create filter & mapping in web.xml (if present)
new WriteCommandAction.Simple(modifiableRootModel.getProject()) {
protected void run() throws Throwable {
final WebFacet webFacet = strutsFacet.getWebFacet();
final ConfigFile configFile = webFacet.getWebXmlDescriptor();
if (configFile == null) return;
final XmlFile webXmlFile = configFile.getXmlFile();
final WebApp webApp = JamCommonUtil.getRootElement(webXmlFile, WebApp.class, null);
if (webApp == null) return;
if (!FileModificationService.getInstance().prepareFileForWrite(webXmlFile)) return;
final Filter strutsFilter = webApp.addFilter();
strutsFilter.getFilterName().setStringValue("struts2");
@NonNls final String filterClass = templateProvider.is21orNewer() ?
StrutsConstants.STRUTS_2_1_FILTER_CLASS :
StrutsConstants.STRUTS_2_0_FILTER_CLASS;
strutsFilter.getFilterClass().setStringValue(filterClass);
final FilterMapping filterMapping = webApp.addFilterMapping();
filterMapping.getFilterName().setValue(strutsFilter);
filterMapping.addUrlPattern().setStringValue("/*");
}
}.execute();
final NotificationListener showFacetSettingsListener = new NotificationListener() {
public void hyperlinkUpdate(@NotNull final Notification notification,
@NotNull final HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
notification.expire();
ModulesConfigurator.showFacetSettingsDialog(strutsFacet, null);
}
}
};
Notifications.Bus.notify(
new Notification("Struts 2", "Struts 2 Setup",
"Struts 2 Facet has been created, please check <a href=\"more\">created fileset</a>",
NotificationType.INFORMATION,
showFacetSettingsListener),
module.getProject());
} catch (Exception e) {
LOG.error("error creating struts.xml from template", e);
}
}
});
}
private static class Struts2FrameworkSupportConfigurable extends FrameworkSupportConfigurableBase
implements FrameworkSupportWithLibrary {
private Struts2FrameworkSupportConfigurable(FrameworkSupportProviderBase frameworkSupportProvider,
FrameworkSupportModel model,
@NotNull List<FrameworkVersion> versions,
@Nullable String versionLabelText) {
super(frameworkSupportProvider, model, versions, versionLabelText);
}
@NotNull
@Override
public CustomLibraryDescription createLibraryDescription() {
return DownloadableLibraryService.getInstance().createDescriptionForType(Struts2LibraryType.class);
}
@Override
public boolean isLibraryOnly() {
return false;
}
}
}