Creating a temporary JAR artifact configuration for building artifact

Answered

Hi,

 

I am trying to create a JAR artifact when a particular action is performed. I am using ArtifactManager class to create artifact. I was able to achieve the intended behavior with the following code:

if (moduleMeetsCriteria(module)) {
JarArtifactType jarArtifactType = JarArtifactType.getInstance();
CompositePackagingElement<?> rootElement = jarArtifactType.createRootElement(jarName);
PackagingElement<?> moduleOutput = elementFactory.createModuleOutput(module);
rootElement.addOrFindChild(moduleOutput);

ArtifactManager artifactManager = ArtifactManager.getInstance(project);
ModifiableArtifactModel modifiableModel = artifactManager.createModifiableModel();
ModifiableArtifact artifact = modifiableModel.addArtifact(artifactName, jarArtifactType, rootElement);
artifactName = artifact.getName();
artifact.setOutputPath(outputPath);
WriteAction.run(modifiableModel::commit);

project.getService(ArtifactDeleter.class).setArtifactToDelete(artifactName);
ProjectTaskManager projectTaskManager = ProjectTaskManager.getInstance(project);
projectTaskManager.build(artifact);
break;
}

The code in the ArtifactDeleter class is as follows:

public class ArtifactDeleter implements ProjectTaskManagerListener {
private final Project project;
private String artifactToDelete;

public ArtifactDeleter(Project project) {
this.project = project;
ProjectTaskManager projectTaskManager = ProjectTaskManager.getInstance(project);
((ProjectTaskManagerImpl) projectTaskManager).addListener(this);
}

public void setArtifactToDelete(String artifactToDelete) {
this.artifactToDelete = artifactToDelete;
}

@Override
public void beforeRun(@NotNull ProjectTaskContext context) {}

@Override
public void afterRun(ProjectTaskManager.@NotNull Result result) {
ApplicationManager.getApplication().invokeLater(() ->
WriteAction.run(this::deleteArtifact));
}

private void deleteArtifact() {
if (artifactToDelete != null) {
ArtifactManager artifactManager = ArtifactManager.getInstance(project);
ModifiableArtifactModel modifiableModel = artifactManager.createModifiableModel();
Artifact artifact = modifiableModel.findArtifact(artifactToDelete);
if (artifact != null) {
modifiableModel.removeArtifact(artifact);
modifiableModel.commit();
}
}
}
}

While the above code works, it has some disadvantages:

  1. Artifact created in such a way can appear in the Project Structure dialog. If that dialog is opened before the artifact was deleted, the temporary artifact is visible to the user. I create the artifact configuration and execute it immediately and hence I do not want it to be saved in the Project Structure.
  2. Since it is saved to Project Structure, I am obligated to delete the artifact after the task is completed. To achieve this, I am using the following experimental API:
    ((ProjectTaskManagerImpl) projectTaskManager).addListener(this);
    I am not sure if this is the right way to do it.

Are there any alternative APIs that can solve the above mentioned issues???

1
1 comment

If you don't need to build that JAR often, maybe it would be simpler to use com.intellij.util.io.Compressor.Jar utility, this way you won't need to deal with artifacts at all. Building JAR file as an artifact makes sense if it is built often, and you want to reuse the already built JAR if module output wasn't changed. In order to do this, you can register an implementation of org.jetbrains.jps.incremental.artifacts.JpsSyntheticArtifactProvider class as a extension to the build process (see the doc). This way the artifact configuration will be used inside the build process only, and it won't affect the project model in the IDE.

0

Please sign in to leave a comment.