blob: 7e8f6016d591cf1df2d93f435c1fc7e42e4872a4 [file] [log] [blame]
/*
* Copyright 2000-2011 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.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;
import com.intellij.openapi.module.ModulePointerManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil;
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;
import com.intellij.packaging.artifacts.ArtifactPointerManager;
import com.intellij.packaging.elements.*;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
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();
public static final PackagingElementType<DirectoryCopyPackagingElement> DIRECTORY_COPY_ELEMENT_TYPE = new DirectoryCopyElementType();
public static final PackagingElementType<ExtractedDirectoryPackagingElement> EXTRACTED_DIRECTORY_ELEMENT_TYPE = new ExtractedDirectoryElementType();
public static final PackagingElementType<ArtifactRootElement<?>> ARTIFACT_ROOT_ELEMENT_TYPE = new ArtifactRootElementType();
private static final PackagingElementType[] STANDARD_TYPES = {
DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE,
LibraryElementType.LIBRARY_ELEMENT_TYPE, ProductionModuleOutputElementType.ELEMENT_TYPE, TestModuleOutputElementType.ELEMENT_TYPE,
ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE, EXTRACTED_DIRECTORY_ELEMENT_TYPE
};
@NotNull
@Override
public PackagingElementType<?>[] getNonCompositeElementTypes() {
final List<PackagingElementType> elementTypes = new ArrayList<PackagingElementType>();
for (PackagingElementType elementType : getAllElementTypes()) {
if (!(elementType instanceof CompositePackagingElementType)) {
elementTypes.add(elementType);
}
}
return elementTypes.toArray(new PackagingElementType[elementTypes.size()]);
}
@Override
@NotNull
public ComplexPackagingElementType<?>[] getComplexElementTypes() {
List<ComplexPackagingElementType<?>> types = new ArrayList<ComplexPackagingElementType<?>>();
for (PackagingElementType type : getAllElementTypes()) {
if (type instanceof ComplexPackagingElementType) {
types.add((ComplexPackagingElementType)type);
}
}
return types.toArray(new ComplexPackagingElementType[types.size()]);
}
@NotNull
@Override
public CompositePackagingElementType<?>[] getCompositeElementTypes() {
final List<CompositePackagingElementType> elementTypes = new ArrayList<CompositePackagingElementType>();
for (PackagingElementType elementType : getAllElementTypes()) {
if (elementType instanceof CompositePackagingElementType) {
elementTypes.add((CompositePackagingElementType)elementType);
}
}
return elementTypes.toArray(new CompositePackagingElementType[elementTypes.size()]);
}
@Override
public PackagingElementType<?> findElementType(String id) {
for (PackagingElementType elementType : getAllElementTypes()) {
if (elementType.getId().equals(id)) {
return elementType;
}
}
if (id.equals(ARTIFACT_ROOT_ELEMENT_TYPE.getId())) {
return ARTIFACT_ROOT_ELEMENT_TYPE;
}
return null;
}
@NotNull
@Override
public PackagingElementType[] getAllElementTypes() {
final PackagingElementType[] types = Extensions.getExtensions(PackagingElementType.EP_NAME);
return ArrayUtil.mergeArrays(STANDARD_TYPES, types);
}
@NotNull
@Override
public PackagingElement<?> createArtifactElement(@NotNull Artifact artifact, @NotNull Project project) {
return new ArtifactPackagingElement(project, ArtifactPointerManager.getInstance(project).createPointer(artifact));
}
@NotNull
public DirectoryPackagingElement createDirectory(@NotNull @NonNls String directoryName) {
return new DirectoryPackagingElement(directoryName);
}
@NotNull
@Override
public ArtifactRootElement<?> createArtifactRootElement() {
return new ArtifactRootElementImpl();
}
@Override
@NotNull
public CompositePackagingElement<?> getOrCreateDirectory(@NotNull CompositePackagingElement<?> parent, @NotNull String relativePath) {
return getOrCreateDirectoryOrArchive(parent, relativePath, true);
}
@NotNull
@Override
public CompositePackagingElement<?> getOrCreateArchive(@NotNull CompositePackagingElement<?> parent, @NotNull String relativePath) {
return getOrCreateDirectoryOrArchive(parent, relativePath, false);
}
@Override
public void addFileCopy(@NotNull CompositePackagingElement<?> root, @NotNull String outputDirectoryPath, @NotNull String sourceFilePath) {
addFileCopy(root, outputDirectoryPath, sourceFilePath, null);
}
@Override
public void addFileCopy(@NotNull CompositePackagingElement<?> root, @NotNull String outputDirectoryPath, @NotNull String sourceFilePath,
@Nullable String outputFileName) {
final String fileName = PathUtil.getFileName(sourceFilePath);
if (outputFileName != null && outputFileName.equals(fileName)) {
outputFileName = null;
}
getOrCreateDirectory(root, outputDirectoryPath).addOrFindChild(createFileCopy(sourceFilePath, outputFileName));
}
@NotNull
private CompositePackagingElement<?> getOrCreateDirectoryOrArchive(@NotNull CompositePackagingElement<?> root,
@NotNull @NonNls String path, final boolean directory) {
path = StringUtil.trimStart(StringUtil.trimEnd(path, "/"), "/");
if (path.length() == 0) {
return root;
}
int index = path.lastIndexOf('/');
String lastName = path.substring(index + 1);
String parentPath = index != -1 ? path.substring(0, index) : "";
final CompositePackagingElement<?> parent = getOrCreateDirectoryOrArchive(root, parentPath, true);
final CompositePackagingElement<?> last = directory ? createDirectory(lastName) : createArchive(lastName);
return parent.addOrFindChild(last);
}
@NotNull
public PackagingElement<?> createModuleOutput(@NotNull String moduleName, @NotNull Project project) {
final ModulePointer pointer = ModulePointerManager.getInstance(project).create(moduleName);
return new ProductionModuleOutputPackagingElement(project, pointer);
}
@NotNull
@Override
public PackagingElement<?> createModuleOutput(@NotNull Module module) {
final ModulePointer modulePointer = ModulePointerManager.getInstance(module.getProject()).create(module);
return new ProductionModuleOutputPackagingElement(module.getProject(), modulePointer);
}
@NotNull
@Override
public PackagingElement<?> createTestModuleOutput(@NotNull Module module) {
ModulePointer pointer = ModulePointerManager.getInstance(module.getProject()).create(module);
return new TestModuleOutputPackagingElement(module.getProject(), pointer);
}
@NotNull
@Override
public List<? extends PackagingElement<?>> createLibraryElements(@NotNull Library library) {
final LibraryTable table = library.getTable();
final String libraryName = library.getName();
if (table != null) {
return Collections.singletonList(createLibraryFiles(libraryName, table.getTableLevel(), null));
}
if (libraryName != null) {
final Module module = ((LibraryImpl)library).getModule();
if (module != null) {
return Collections.singletonList(createLibraryFiles(libraryName, LibraryTableImplUtil.MODULE_LEVEL, module.getName()));
}
}
final List<PackagingElement<?>> elements = new ArrayList<PackagingElement<?>>();
for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
final String path = FileUtil.toSystemIndependentName(PathUtil.getLocalPath(file));
elements.add(file.isDirectory() && file.isInLocalFileSystem() ? new DirectoryCopyPackagingElement(path) : new FileCopyPackagingElement(path));
}
return elements;
}
@NotNull
@Override
public PackagingElement<?> createArtifactElement(@NotNull ArtifactPointer artifactPointer, @NotNull Project project) {
return new ArtifactPackagingElement(project, artifactPointer);
}
@NotNull
@Override
public PackagingElement<?> createLibraryFiles(@NotNull String libraryName, @NotNull String level, String moduleName) {
return new LibraryPackagingElement(level, libraryName, moduleName);
}
@NotNull
public CompositePackagingElement<?> createArchive(@NotNull @NonNls String archiveFileName) {
return new ArchivePackagingElement(archiveFileName);
}
@Nullable
private static PackagingElement<?> findArchiveOrDirectoryByName(@NotNull CompositePackagingElement<?> parent, @NotNull String name) {
for (PackagingElement<?> element : parent.getChildren()) {
if (element instanceof ArchivePackagingElement && ((ArchivePackagingElement)element).getArchiveFileName().equals(name) ||
element instanceof DirectoryPackagingElement && ((DirectoryPackagingElement)element).getDirectoryName().equals(name)) {
return element;
}
}
return null;
}
@NotNull
public static String suggestFileName(@NotNull CompositePackagingElement<?> parent, @NonNls @NotNull String prefix, @NonNls @NotNull String suffix) {
String name = prefix + suffix;
int i = 2;
while (findArchiveOrDirectoryByName(parent, name) != null) {
name = prefix + i++ + suffix;
}
return name;
}
@NotNull
@Override
public PackagingElement<?> createDirectoryCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath) {
return createParentDirectories(relativeOutputPath, new DirectoryCopyPackagingElement(filePath));
}
@Override
@NotNull
public PackagingElement<?> createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar,
@NotNull String relativeOutputPath) {
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) {
return createFileCopyWithParentDirectories(filePath, relativeOutputPath, null);
}
@NotNull
@Override
public PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath,
@NotNull String relativeOutputPath,
@Nullable String outputFileName) {
return createParentDirectories(relativeOutputPath, createFileCopy(filePath, outputFileName));
}
@Override
public PackagingElement<?> createFileCopy(@NotNull String filePath, String outputFileName) {
return new FileCopyPackagingElement(filePath, outputFileName);
}
@NotNull
@Override
public PackagingElement<?> createParentDirectories(@NotNull String relativeOutputPath, @NotNull PackagingElement<?> element) {
return createParentDirectories(relativeOutputPath, Collections.singletonList(element)).get(0);
}
@NotNull
@Override
public List<? extends PackagingElement<?>> createParentDirectories(@NotNull String relativeOutputPath, @NotNull List<? extends PackagingElement<?>> elements) {
relativeOutputPath = StringUtil.trimStart(relativeOutputPath, "/");
if (relativeOutputPath.length() == 0) {
return elements;
}
int slash = relativeOutputPath.indexOf('/');
if (slash == -1) slash = relativeOutputPath.length();
String rootName = relativeOutputPath.substring(0, slash);
String pathTail = relativeOutputPath.substring(slash);
final DirectoryPackagingElement root = createDirectory(rootName);
final CompositePackagingElement<?> last = getOrCreateDirectory(root, pathTail);
last.addOrFindChildren(elements);
return Collections.singletonList(root);
}
public static CompositePackagingElement<?> createDirectoryOrArchiveWithParents(@NotNull String path, final boolean archive) {
path = FileUtil.toSystemIndependentName(path);
final String parentPath = PathUtil.getParentPath(path);
final String fileName = PathUtil.getFileName(path);
final PackagingElement<?> element = archive ? new ArchivePackagingElement(fileName) : new DirectoryPackagingElement(fileName);
return (CompositePackagingElement<?>)getInstance().createParentDirectories(parentPath, element);
}
private static class ArtifactRootElementType extends PackagingElementType<ArtifactRootElement<?>> {
protected ArtifactRootElementType() {
super("root", "");
}
@Override
public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) {
return false;
}
@NotNull
public List<? extends ArtifactRootElement<?>> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
@NotNull CompositePackagingElement<?> parent) {
throw new UnsupportedOperationException("'create' not implemented in " + getClass().getName());
}
@NotNull
public ArtifactRootElement<?> createEmpty(@NotNull Project project) {
return new ArtifactRootElementImpl();
}
}
}