IDEA-25719: Add option to quickly create an application from a module in artifacts

This commit is contained in:
nik
2010-08-06 09:42:46 +04:00
parent 7369bbb863
commit 09d2e7b454
12 changed files with 547 additions and 48 deletions
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.packaging.impl.artifacts.JarArtifactFromModulesDialog">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="c89c9" class="javax.swing.JLabel" binding="myMainClassLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Main &amp;Class:"/>
</properties>
</component>
<vspacer id="8cb38">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="535a8" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myMainClassField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="2fb86" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="4853e"/>
<text value="&amp;Module:"/>
</properties>
</component>
<component id="4853e" class="javax.swing.JComboBox" binding="myModuleComboBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="400" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="8e551" class="javax.swing.JLabel" binding="myManifestDirLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Directory for META-INF/MANIFEST.MF:"/>
</properties>
</component>
<component id="1ea2d" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myManifestDirField">
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="53c3f" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="Jar files from libraries:"/>
<children>
<component id="f9a17" class="javax.swing.JRadioButton" binding="myExtractJarsRadioButton">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text value="&amp;extract to the target jar"/>
</properties>
</component>
<hspacer id="90c4f">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="b3972" class="javax.swing.JRadioButton" default-binding="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="copy &amp;to the output directory and link via manifest"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
<buttonGroups>
<group name="jarFiles">
<member id="f9a17"/>
<member id="b3972"/>
</group>
</buttonGroups>
</form>
@@ -0,0 +1,141 @@
/*
* Copyright 2000-2010 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 com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.elements.ManifestFileUtil;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
/**
* @author nik
*/
public class JarArtifactFromModulesDialog extends DialogWrapper {
private JPanel myMainPanel;
private TextFieldWithBrowseButton myMainClassField;
private JComboBox myModuleComboBox;
private JLabel myMainClassLabel;
private TextFieldWithBrowseButton myManifestDirField;
private JLabel myManifestDirLabel;
private JRadioButton myExtractJarsRadioButton;
private PackagingElementResolvingContext myContext;
public JarArtifactFromModulesDialog(PackagingElementResolvingContext context) {
super(context.getProject());
myContext = context;
setTitle("Create Jar from Modules");
myMainClassLabel.setLabelFor(myMainClassField.getTextField());
myManifestDirLabel.setLabelFor(myManifestDirField.getTextField());
final Project project = myContext.getProject();
ManifestFileUtil.setupMainClassField(project, myMainClassField);
myMainClassField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
updateManifestDirField();
}
});
updateManifestDirField();
myManifestDirField.addBrowseFolderListener(null, null, project, ManifestFileUtil.createDescriptorForManifestDirectory());
final Module[] modules = context.getModulesProvider().getModules();
if (modules.length > 1) {
myModuleComboBox.addItem(null);
}
for (Module module : modules) {
myModuleComboBox.addItem(module);
}
myModuleComboBox.setRenderer(new ModuleListRenderer());
init();
}
private void updateManifestDirField() {
final boolean enable = !myMainClassField.getText().isEmpty() || !myExtractJarsRadioButton.isSelected();
setManifestDirFieldEnabled(enable);
if (enable && myManifestDirField.getText().isEmpty()) {
final VirtualFile file = ManifestFileUtil.suggestManifestFileDirectory(myContext.getProject(), getSelectedModule());
if (file != null) {
myManifestDirField.setText(FileUtil.toSystemDependentName(file.getPath()));
}
}
}
@Nullable
private Module getSelectedModule() {
return (Module)myModuleComboBox.getSelectedItem();
}
@NotNull
public Module[] getSelectedModules() {
final Module module = getSelectedModule();
if (module != null) {
return new Module[]{module};
}
return myContext.getModulesProvider().getModules();
}
@NotNull
public String getDirectoryForManifest() {
return FileUtil.toSystemIndependentName(myManifestDirField.getText());
}
public boolean isExtractLibrariesToJar() {
return myExtractJarsRadioButton.isSelected();
}
public String getMainClassName() {
return myMainClassField.getText();
}
private void setManifestDirFieldEnabled(boolean enabled) {
myManifestDirLabel.setEnabled(enabled);
myManifestDirField.setEnabled(enabled);
}
@Override
protected JComponent createCenterPanel() {
return myMainPanel;
}
private static class ModuleListRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Module) {
final Module module = (Module)value;
setIcon(module.getModuleType().getNodeIcon(false));
setText(module.getName());
}
else {
setText("<All Modules>");
setIcon(null);
}
return component;
}
}
}
@@ -16,13 +16,17 @@
package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.packaging.artifacts.ArtifactTemplate;
import com.intellij.packaging.artifacts.ArtifactType;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElementOutputKind;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.elements.ArchivePackagingElement;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
/**
* @author nik
@@ -32,6 +36,10 @@ public class JarArtifactType extends ArtifactType {
super("jar", "Jar");
}
public static JarArtifactType getInstance() {
return EP_NAME.findExtension(JarArtifactType.class);
}
@NotNull
@Override
public Icon getIcon() {
@@ -48,4 +56,10 @@ public class JarArtifactType extends ArtifactType {
public CompositePackagingElement<?> createRootElement(@NotNull String artifactName) {
return new ArchivePackagingElement(FileUtil.sanitizeFileName(artifactName) + ".jar");
}
@NotNull
@Override
public List<? extends ArtifactTemplate> getNewArtifactTemplates(@NotNull PackagingElementResolvingContext context) {
return Collections.singletonList(new JarFromModulesTemplate(context));
}
}
@@ -0,0 +1,179 @@
/*
* Copyright 2000-2010 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 com.intellij.packaging.impl.artifacts;
import com.intellij.CommonBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.ArtifactTemplate;
import com.intellij.packaging.elements.*;
import com.intellij.packaging.impl.elements.LibraryPackagingElement;
import com.intellij.packaging.impl.elements.ManifestFileUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.*;
/**
* @author nik
*/
public class JarFromModulesTemplate extends ArtifactTemplate {
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.artifacts.JarFromModulesTemplate");
private PackagingElementResolvingContext myContext;
public JarFromModulesTemplate(PackagingElementResolvingContext context) {
myContext = context;
}
@Override
public NewArtifactConfiguration createArtifact() {
JarArtifactFromModulesDialog dialog = new JarArtifactFromModulesDialog(myContext);
dialog.show();
if (!dialog.isOK()) {
return null;
}
return doCreateArtifact(dialog.getSelectedModules(), dialog.getMainClassName(), dialog.getDirectoryForManifest(),
dialog.isExtractLibrariesToJar());
}
@Nullable
public NewArtifactConfiguration doCreateArtifact(final Module[] modules, final String mainClassName,
final String directoryForManifest, final boolean extractLibrariesToJar) {
VirtualFile manifestFile = null;
final Project project = myContext.getProject();
if (mainClassName != null && !mainClassName.isEmpty() || !extractLibrariesToJar) {
final VirtualFile directory;
try {
directory = VfsUtil.createDirectoryIfMissing(directoryForManifest);
}
catch (IOException e) {
LOG.info(e);
Messages.showErrorDialog(project, "Cannot create directory '" + directoryForManifest + "': " + e.getMessage(),
CommonBundle.getErrorTitle());
return null;
}
if (directory == null) return null;
manifestFile = ManifestFileUtil.createManifestFile(directory, project);
if (manifestFile == null) {
return null;
}
ManifestFileUtil.updateManifest(manifestFile, mainClassName, null, true);
}
String name = modules.length == 1 ? modules[0].getName() : project.getName();
final PackagingElementFactory factory = PackagingElementFactory.getInstance();
final CompositePackagingElement<?> archive = factory.createArchive(FileUtil.sanitizeFileName(name) + ".jar");
final OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(project).orderEntries(Arrays.asList(modules));
final Set<Library> libraries = new THashSet<Library>();
orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().productionOnly().runtimeOnly().recursively().forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry orderEntry) {
if (orderEntry instanceof ModuleSourceOrderEntry) {
archive.addOrFindChild(factory.createModuleOutput(orderEntry.getOwnerModule()));
}
else if (orderEntry instanceof LibraryOrderEntry) {
ContainerUtil.addIfNotNull(((LibraryOrderEntry)orderEntry).getLibrary(), libraries);
}
return true;
}
});
final JarArtifactType jarArtifactType = JarArtifactType.getInstance();
if (manifestFile != null && !manifestFile.equals(ManifestFileUtil.findManifestFile(archive, myContext, jarArtifactType))) {
archive.addFirstChild(factory.createFileCopyWithParentDirectories(manifestFile.getPath(), ManifestFileUtil.MANIFEST_DIR_NAME));
}
final String artifactName = name + ":jar";
if (extractLibrariesToJar) {
addExtractedLibrariesToJar(archive, factory, libraries);
return new NewArtifactConfiguration(archive, artifactName, jarArtifactType);
}
else {
final ArtifactRootElement<?> root = factory.createArtifactRootElement();
List<String> classpath = new ArrayList<String>();
root.addOrFindChild(archive);
addLibraries(libraries, root, archive, classpath);
ManifestFileUtil.updateManifest(manifestFile, mainClassName, classpath, true);
return new NewArtifactConfiguration(root, artifactName, PlainArtifactType.getInstance());
}
}
private void addLibraries(Set<Library> libraries, ArtifactRootElement<?> root, CompositePackagingElement<?> archive,
List<String> classpath) {
PackagingElementFactory factory = PackagingElementFactory.getInstance();
for (Library library : libraries) {
if (LibraryPackagingElement.getKindForLibrary(library).containsDirectoriesWithClasses()) {
for (VirtualFile classesRoot : library.getFiles(OrderRootType.CLASSES)) {
if (classesRoot.isInLocalFileSystem()) {
archive.addOrFindChild(factory.createDirectoryCopyWithParentDirectories(classesRoot.getPath(), "/"));
}
else {
final PackagingElement<?> child = factory.createFileCopyWithParentDirectories(PathUtil.getLocalFile(classesRoot).getPath(), "/");
root.addOrFindChild(child);
classpath.addAll(ManifestFileUtil.getClasspathForElements(Collections.singletonList(child), myContext, PlainArtifactType.getInstance()));
}
}
}
else {
final List<? extends PackagingElement<?>> children = factory.createLibraryElements(library);
classpath.addAll(ManifestFileUtil.getClasspathForElements(children, myContext, PlainArtifactType.getInstance()));
root.addOrFindChildren(children);
}
}
}
private static void addExtractedLibrariesToJar(CompositePackagingElement<?> archive, PackagingElementFactory factory, Set<Library> libraries) {
for (Library library : libraries) {
if (LibraryPackagingElement.getKindForLibrary(library).containsJarFiles()) {
for (VirtualFile classesRoot : library.getFiles(OrderRootType.CLASSES)) {
if (classesRoot.isInLocalFileSystem()) {
archive.addOrFindChild(factory.createDirectoryCopyWithParentDirectories(classesRoot.getPath(), "/"));
}
else {
archive.addOrFindChild(factory.createExtractedDirectory(classesRoot));
}
}
}
else {
archive.addOrFindChildren(factory.createLibraryElements(library));
}
}
}
@Override
public String getPresentableName() {
return "Jar from Modules...";
}
}
@@ -21,7 +21,6 @@ import com.intellij.packaging.artifacts.ArtifactType;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElementOutputKind;
import com.intellij.packaging.impl.elements.ArtifactRootElementImpl;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -35,7 +34,7 @@ public class PlainArtifactType extends ArtifactType {
@NonNls public static final String ID = "plain";
public static PlainArtifactType getInstance() {
return ContainerUtil.findInstance(getAllTypes(), PlainArtifactType.class);
return EP_NAME.findExtension(PlainArtifactType.class);
}
public PlainArtifactType() {
@@ -20,10 +20,11 @@ import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementFactory;
import com.intellij.packaging.elements.PackagingElementType;
import com.intellij.packaging.ui.ArtifactEditorContext;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +54,7 @@ public class ExtractedDirectoryElementType extends PackagingElementType<Extracte
}
@NotNull
public List<? extends ExtractedDirectoryPackagingElement> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
public List<? extends PackagingElement<?>> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
@NotNull CompositePackagingElement<?> parent) {
final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, true, false, true, true) {
@Override
@@ -64,11 +65,10 @@ public class ExtractedDirectoryElementType extends PackagingElementType<Extracte
};
final FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, context.getProject());
final VirtualFile[] files = chooser.choose(null, context.getProject());
final List<ExtractedDirectoryPackagingElement> list = new ArrayList<ExtractedDirectoryPackagingElement>();
final List<PackagingElement<?>> list = new ArrayList<PackagingElement<?>>();
final PackagingElementFactory factory = PackagingElementFactory.getInstance();
for (VirtualFile file : files) {
final String fullPath = file.getPath();
final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
list.add(new ExtractedDirectoryPackagingElement(fullPath.substring(0, jarEnd), fullPath.substring(jarEnd + 1)));
list.add(factory.createExtractedDirectory(file));
}
return list;
}
@@ -63,6 +63,11 @@ public class ExtractedDirectoryPackagingElement extends FileOrDirectoryCopyPacka
return new ExtractedDirectoryPresentation(this);
}
@Override
public String toString() {
return "extracted:" + myFilePath + "!" + myPathInJar;
}
@Override
public VirtualFile findFile() {
final VirtualFile jarFile = super.findFile();
@@ -16,6 +16,9 @@
package com.intellij.packaging.impl.elements;
import com.intellij.CommonBundle;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.compiler.make.ManifestBuilder;
@@ -24,9 +27,12 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -42,10 +48,16 @@ import com.intellij.packaging.impl.artifacts.PackagingElementPath;
import com.intellij.packaging.impl.artifacts.PackagingElementProcessor;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.ManifestFileConfiguration;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -111,7 +123,18 @@ public class ManifestFileUtil {
}
@Nullable
private static VirtualFile suggestBaseDir(Project project, final @Nullable VirtualFile file) {
public static VirtualFile suggestManifestFileDirectory(@NotNull Project project, @Nullable Module module) {
OrderEnumerator enumerator = module != null ? OrderEnumerator.orderEntries(module) : OrderEnumerator.orderEntries(project);
final VirtualFile[] files = enumerator.withoutDepModules().withoutLibraries().withoutSdk().productionOnly().sources().getRoots();
if (files.length > 0) {
return files[0];
}
return suggestBaseDir(project, null);
}
@Nullable
private static VirtualFile suggestBaseDir(@NotNull Project project, final @Nullable VirtualFile file) {
final VirtualFile[] contentRoots = ProjectRootManager.getInstance(project).getContentRoots();
if (file == null && contentRoots.length > 0) {
return contentRoots[0];
@@ -145,7 +168,7 @@ public class ManifestFileUtil {
}
}
public static void updateManifest(VirtualFile file, final String mainClass, final List<String> classpath, final boolean replaceValues) {
public static void updateManifest(@NotNull VirtualFile file, final @Nullable String mainClass, final @Nullable List<String> classpath, final boolean replaceValues) {
final Manifest manifest = readManifest(file);
final Attributes mainAttributes = manifest.getMainAttributes();
@@ -235,18 +258,23 @@ public class ManifestFileUtil {
@Nullable
public static VirtualFile showDialogAndCreateManifest(final ArtifactEditorContext context, final CompositePackagingElement<?> element) {
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setTitle("Select Directory for META-INF/MANIFEST.MF file");
FileChooserDescriptor descriptor = createDescriptorForManifestDirectory();
final VirtualFile directory = suggestManifestFileDirectory(element, context, context.getArtifactType());
final VirtualFile[] files = FileChooser.chooseFiles(context.getProject(), descriptor, directory);
if (files.length != 1) {
return null;
}
return createManifestFile(files[0], context.getProject());
}
@Nullable
public static VirtualFile createManifestFile(final @NotNull VirtualFile directory, final @NotNull Project project) {
ApplicationManager.getApplication().assertIsDispatchThread();
final Ref<IOException> exc = Ref.create(null);
final VirtualFile file = new WriteAction<VirtualFile>() {
protected void run(final Result<VirtualFile> result) {
VirtualFile dir = files[0];
VirtualFile dir = directory;
try {
if (!dir.getName().equals(MANIFEST_DIR_NAME)) {
dir = VfsUtil.createDirectoryIfMissing(dir, MANIFEST_DIR_NAME);
@@ -272,12 +300,18 @@ public class ManifestFileUtil {
final IOException exception = exc.get();
if (exception != null) {
LOG.info(exception);
Messages.showErrorDialog(context.getProject(), exception.getMessage(), CommonBundle.getErrorTitle());
Messages.showErrorDialog(project, exception.getMessage(), CommonBundle.getErrorTitle());
return null;
}
return file;
}
public static FileChooserDescriptor createDescriptorForManifestDirectory() {
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setTitle("Select Directory for META-INF/MANIFEST.MF file");
return descriptor;
}
public static void addManifestFileToLayout(final @NotNull String path, final @NotNull ArtifactEditorContext context,
final @NotNull CompositePackagingElement<?> element) {
context.editLayout(context.getArtifact(), new Runnable() {
@@ -289,4 +323,32 @@ public class ManifestFileUtil {
}
});
}
@Nullable
public static PsiClass selectMainClass(Project project, final @Nullable String initialClassName) {
final TreeClassChooserFactory chooserFactory = TreeClassChooserFactory.getInstance(project);
final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project);
final PsiClass aClass = initialClassName != null ? JavaPsiFacade.getInstance(project).findClass(initialClassName, searchScope) : null;
final TreeClassChooser chooser =
chooserFactory.createWithInnerClassesScopeChooser("Select Main Class", searchScope, new MainClassFilter(), aClass);
chooser.showDialog();
return chooser.getSelectedClass();
}
public static void setupMainClassField(final Project project, final TextFieldWithBrowseButton field) {
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final PsiClass selected = selectMainClass(project, field.getText());
if (selected != null) {
field.setText(selected.getQualifiedName());
}
}
});
}
private static class MainClassFilter implements TreeClassChooser.ClassFilter {
public boolean isAccepted(PsiClass aClass) {
return PsiMethodUtil.MAIN_CLASS.value(aClass) && PsiMethodUtil.hasMainMethod(aClass);
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.packaging.impl.elements;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
@@ -27,6 +28,7 @@ import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactPointer;
@@ -47,6 +49,7 @@ import java.util.List;
* @author nik
*/
public class PackagingElementFactoryImpl extends PackagingElementFactory {
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.elements.PackagingElementFactoryImpl");
public static final PackagingElementType<DirectoryPackagingElement> DIRECTORY_ELEMENT_TYPE = new DirectoryElementType();
public static final PackagingElementType<ArchivePackagingElement> ARCHIVE_ELEMENT_TYPE = new ArchiveElementType();
public static final PackagingElementType<FileCopyPackagingElement> FILE_COPY_ELEMENT_TYPE = new FileCopyElementType();
@@ -261,6 +264,15 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
return createParentDirectories(relativeOutputPath, new ExtractedDirectoryPackagingElement(jarPath, pathInJar));
}
@NotNull
@Override
public PackagingElement<?> createExtractedDirectory(@NotNull VirtualFile jarEntry) {
LOG.assertTrue(jarEntry.getFileSystem() instanceof JarFileSystem, "Expected file from jar but file from " + jarEntry.getFileSystem() + " found");
final String fullPath = jarEntry.getPath();
final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
return new ExtractedDirectoryPackagingElement(fullPath.substring(0, jarEnd), fullPath.substring(jarEnd + 1));
}
@NotNull
@Override
public PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath) {
@@ -15,11 +15,8 @@
*/
package com.intellij.packaging.impl.ui.properties;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
@@ -31,10 +28,6 @@ import com.intellij.packaging.impl.elements.ManifestFileUtil;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.ManifestFileConfiguration;
import com.intellij.packaging.ui.PackagingElementPropertiesPanel;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,21 +60,7 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
myElement = element;
myContext = context;
myMainClassField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final Project project = context.getProject();
final TreeClassChooserFactory chooserFactory = TreeClassChooserFactory.getInstance(project);
final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project);
final PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(myMainClassField.getText(), searchScope);
final TreeClassChooser chooser =
chooserFactory.createWithInnerClassesScopeChooser("Select Main Class", searchScope, new MainClassFilter(), aClass);
chooser.showDialog();
final PsiClass selected = chooser.getSelectedClass();
if (selected != null) {
myMainClassField.setText(selected.getQualifiedName());
}
}
});
ManifestFileUtil.setupMainClassField(context.getProject(), myMainClassField);
myClasspathField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -192,9 +171,4 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
return className.length() != 0 ? className : null;
}
protected static class MainClassFilter implements TreeClassChooser.ClassFilter {
public boolean isAccepted(PsiClass aClass) {
return PsiMethodUtil.MAIN_CLASS.value(aClass) && PsiMethodUtil.hasMainMethod(aClass);
}
}
}
@@ -48,16 +48,28 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
}
}
myChildren.add(child);
myUnmodifiableChildren = null;
return child;
}
public void addFirstChild(@NotNull PackagingElement<?> child) {
myChildren.add(0, child);
for (int i = 1; i < myChildren.size(); i++) {
PackagingElement<?> element = myChildren.get(i);
if (element.isEqualTo(child)) {
if (element instanceof CompositePackagingElement<?>) {
((CompositePackagingElement<?>)child).addOrFindChildren(((CompositePackagingElement<?>)element).getChildren());
}
myChildren.remove(i);
break;
}
}
}
public List<? extends PackagingElement<?>> addOrFindChildren(Collection<? extends PackagingElement<?>> children) {
List<PackagingElement<?>> added = new ArrayList<PackagingElement<?>>();
for (PackagingElement<?> child : children) {
added.add(addOrFindChild(child));
}
myUnmodifiableChildren = null;
return added;
}
@@ -69,7 +81,6 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
final PackagingElement<?> element2 = myChildren.get(target);
myChildren.set(index, element2);
myChildren.set(target, element1);
myUnmodifiableChildren = null;
return element1;
}
return null;
@@ -77,12 +88,10 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
public void removeChild(@NotNull PackagingElement<?> child) {
myChildren.remove(child);
myUnmodifiableChildren = null;
}
public void removeChildren(@NotNull Collection<? extends PackagingElement<?>> children) {
myChildren.removeAll(children);
myUnmodifiableChildren = null;
}
@NotNull
@@ -117,6 +126,5 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
public void removeAllChildren() {
myChildren.clear();
myUnmodifiableChildren = null;
}
}
@@ -17,8 +17,9 @@ package com.intellij.packaging.elements;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactPointer;
import org.jetbrains.annotations.NonNls;
@@ -71,6 +72,9 @@ public abstract class PackagingElementFactory {
public abstract PackagingElement<?> createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar,
@NotNull String relativeOutputPath);
@NotNull
public abstract PackagingElement<?> createExtractedDirectory(@NotNull VirtualFile jarEntry);
@NotNull
public abstract PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath,
@Nullable String outputFileName);