mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-25719: Add option to quickly create an application from a module in artifacts
This commit is contained in:
+101
@@ -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 &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="&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="&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="&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 &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>
|
||||
+141
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+179
@@ -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() {
|
||||
|
||||
+6
-6
@@ -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;
|
||||
}
|
||||
|
||||
+5
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -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) {
|
||||
|
||||
+1
-27
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-6
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user