diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form
new file mode 100644
index 000000000000..d9347ab8d981
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form
@@ -0,0 +1,101 @@
+
+
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java
new file mode 100644
index 000000000000..22a9b83905f9
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java
@@ -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("");
+ setIcon(null);
+ }
+ return component;
+ }
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactType.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactType.java
index 01bcd7153c86..47d0033a6e09 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactType.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactType.java
@@ -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));
+ }
}
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java
new file mode 100644
index 000000000000..976533aaa8de
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java
@@ -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 libraries = new THashSet();
+ orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().productionOnly().runtimeOnly().recursively().forEach(new Processor() {
+ @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 classpath = new ArrayList();
+ 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 libraries, ArtifactRootElement> root, CompositePackagingElement> archive,
+ List 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 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...";
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PlainArtifactType.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PlainArtifactType.java
index 4cd6ab503037..b720824c04f3 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PlainArtifactType.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PlainArtifactType.java
@@ -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() {
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java
index 34be7a6e00bf..ab4c1e9efe34 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryElementType.java
@@ -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 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 list = new ArrayList();
+ final List> list = new ArrayList>();
+ 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;
}
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java
index 112f8c4cf95c..a0b4ddabe537 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ExtractedDirectoryPackagingElement.java
@@ -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();
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ManifestFileUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ManifestFileUtil.java
index 21433a5e74e3..392d58aa7e8d 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ManifestFileUtil.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ManifestFileUtil.java
@@ -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 classpath, final boolean replaceValues) {
+ public static void updateManifest(@NotNull VirtualFile file, final @Nullable String mainClass, final @Nullable List 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 exc = Ref.create(null);
final VirtualFile file = new WriteAction() {
protected void run(final Result 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);
+ }
+ }
}
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java
index be6c0b32993f..7ec062a7101a 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java
@@ -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 DIRECTORY_ELEMENT_TYPE = new DirectoryElementType();
public static final PackagingElementType ARCHIVE_ELEMENT_TYPE = new ArchiveElementType();
public static final PackagingElementType 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) {
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/ui/properties/ElementWithManifestPropertiesPanel.java b/java/compiler/impl/src/com/intellij/packaging/impl/ui/properties/ElementWithManifestPropertiesPanel.java
index 0d8cc91fbd75..9aad9c69c6da 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/ui/properties/ElementWithManifestPropertiesPanel.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/ui/properties/ElementWithManifestPropertiesPanel.java
@@ -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 extends PackagingElement 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> added = new ArrayList>();
for (PackagingElement> child : children) {
added.add(addOrFindChild(child));
}
- myUnmodifiableChildren = null;
return added;
}
@@ -69,7 +81,6 @@ public abstract class CompositePackagingElement extends PackagingElement 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 extends PackagingElement 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 extends PackagingElement i
public void removeAllChildren() {
myChildren.clear();
- myUnmodifiableChildren = null;
}
}
diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java
index 2cbad503ce6a..eaf0c6f2554e 100644
--- a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java
+++ b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java
@@ -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);