mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-75734 android+maven: support for external "apklib" dependencies
This commit is contained in:
@@ -293,4 +293,5 @@ android.logcat.edit.logcat.filter.button=Edit selected logcat filter
|
||||
android.logcat.remove.logcat.filter.button=Remove selected logcat filter
|
||||
android.logcat.add.logcat.filter.button=Add a new logcat filter
|
||||
android.logcat.new.logcat.dialog.label=<html>Filter logcat messages by different parameters.<br>Empty fields will match all messages.</html>
|
||||
android.logcat.new.filter.dialog.name.busy.error=Filter {0} already exists
|
||||
android.logcat.new.filter.dialog.name.busy.error=Filter {0} already exists
|
||||
android.compile.messages.processing.external.apklib.dependencies=Processing external apklib dependencies
|
||||
@@ -5,6 +5,7 @@
|
||||
<importer implementation="org.jetbrains.android.maven.AndroidFacetImporter2"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<compiler implementation="org.jetbrains.android.compiler.AndroidExternalApklibExtractingCompiler" order="first"/>
|
||||
<compiler implementation="org.jetbrains.android.compiler.AndroidMavenResourcesCompiler"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="org.jetbrains">
|
||||
|
||||
@@ -163,6 +163,8 @@
|
||||
serviceImplementation="org.jetbrains.android.uipreview.AndroidLayoutPreviewToolWindowSettings"/>
|
||||
<projectService serviceInterface="org.jetbrains.android.logcat.AndroidConfiguredLogFilters"
|
||||
serviceImplementation="org.jetbrains.android.logcat.AndroidConfiguredLogFilters"/>
|
||||
<projectService serviceInterface="org.jetbrains.android.maven.AndroidExternalApklibDependenciesManager"
|
||||
serviceImplementation="org.jetbrains.android.maven.AndroidExternalApklibDependenciesManager"/>
|
||||
<xml.xmlExtension implementation="org.jetbrains.android.dom.AndroidXmlExtension" order="first"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.android.AndroidIdIndex"/>
|
||||
<referencesSearch implementation="org.jetbrains.android.AndroidReferenceSearchExecutor"/>
|
||||
|
||||
@@ -369,11 +369,11 @@ public class AndroidCompileUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ContentEntry findContentEntryForRoot(@NotNull ModifiableRootModel model, @NotNull VirtualFile root) {
|
||||
public static ContentEntry findContentEntryForRoot(@NotNull ModifiableRootModel model, @NotNull VirtualFile root) {
|
||||
ContentEntry contentEntry = null;
|
||||
for (ContentEntry candidate : model.getContentEntries()) {
|
||||
VirtualFile contentRoot = candidate.getFile();
|
||||
if (contentRoot != null && VfsUtil.isAncestor(contentRoot, root, false)) {
|
||||
if (contentRoot != null && VfsUtilCore.isAncestor(contentRoot, root, false)) {
|
||||
contentEntry = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
package org.jetbrains.android.compiler;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.*;
|
||||
import com.intellij.openapi.compiler.ex.CompileContextEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.io.ZipUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.maven.AndroidExternalApklibDependenciesManager;
|
||||
import org.jetbrains.android.maven.AndroidMavenUtil;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidExternalApklibExtractingCompiler implements SourceGeneratingCompiler {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidExternalApklibExtractingCompiler");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile getPresentableFile(CompileContext context, Module module, VirtualFile outputRoot, VirtualFile generatedFile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationItem[] getGenerationItems(final CompileContext context) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<GenerationItem[]>() {
|
||||
@Override
|
||||
public GenerationItem[] compute() {
|
||||
final List<GenerationItem> result = new ArrayList<GenerationItem>();
|
||||
|
||||
for (Module module : ModuleManager.getInstance(context.getProject()).getModules()) {
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(module);
|
||||
if (facet == null || !facet.getConfiguration().LIBRARY_PROJECT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String mavenIdStr = AndroidMavenUtil.getMavenIdStringByExtApklibModule(facet.getModule());
|
||||
if (mavenIdStr == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final AndroidExternalApklibDependenciesManager manager =
|
||||
AndroidExternalApklibDependenciesManager.getInstance(context.getProject());
|
||||
final String artifactFilePath = manager.getArtifactFilePath(mavenIdStr);
|
||||
|
||||
if (artifactFilePath == null) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR,
|
||||
"Cannot find artifact file for generated module " + module.getName() + ". Try to force reimport Maven model",
|
||||
null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
final VirtualFile[] roots = ModuleRootManager.getInstance(module).getContentRoots();
|
||||
if (roots.length == 0) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot find any content root in generated module " +
|
||||
module.getName() +
|
||||
". Try to force reimport Maven model", null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
final VirtualFile root = roots[0];
|
||||
|
||||
result.add(new MyGenerationItem(module, FileUtil.toSystemDependentName(root.getPath()),
|
||||
FileUtil.toSystemDependentName(artifactFilePath)));
|
||||
}
|
||||
|
||||
return result.toArray(new GenerationItem[result.size()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerationItem[] generate(CompileContext context,
|
||||
GenerationItem[] items,
|
||||
VirtualFile outputRootDirectory) {
|
||||
if (items == null || items.length == 0) {
|
||||
return new GenerationItem[0];
|
||||
}
|
||||
|
||||
context.getProgressIndicator().setText(AndroidBundle.message("android.compile.messages.processing.external.apklib.dependencies"));
|
||||
|
||||
final GenerationItem[] generatedItems = doGenerate(context, items);
|
||||
final Set<VirtualFile> generatedVFiles = new HashSet<VirtualFile>();
|
||||
final HashSet<VirtualFile> visited = new HashSet<VirtualFile>();
|
||||
|
||||
for (GenerationItem item : generatedItems) {
|
||||
final MyGenerationItem genItem = (MyGenerationItem)item;
|
||||
|
||||
final File srcRoot = new File(genItem.getGenContentRootPath() + '/' +
|
||||
AndroidMavenUtil.APK_LIB_ARTIFACT_SOURCE_ROOT);
|
||||
|
||||
final VirtualFile vSrcRoot = LocalFileSystem.getInstance().findFileByIoFile(srcRoot);
|
||||
if (vSrcRoot != null) {
|
||||
vSrcRoot.getParent().refresh(false, true);
|
||||
AndroidUtils.collectFiles(vSrcRoot, visited, generatedVFiles);
|
||||
}
|
||||
}
|
||||
|
||||
if (context instanceof CompileContextEx) {
|
||||
((CompileContextEx)context).markGenerated(generatedVFiles);
|
||||
}
|
||||
|
||||
return generatedItems;
|
||||
}
|
||||
|
||||
private static GenerationItem[] doGenerate(CompileContext context, GenerationItem[] items) {
|
||||
final List<GenerationItem> result = new ArrayList<GenerationItem>();
|
||||
|
||||
for (GenerationItem item : items) {
|
||||
final Module module = item.getModule();
|
||||
|
||||
if (!AndroidCompileUtil.isModuleAffected(context, module)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final MyGenerationItem genItem = (MyGenerationItem)item;
|
||||
|
||||
final String artifactPath = genItem.getArtifactPath();
|
||||
final File artifactFile = new File(artifactPath);
|
||||
|
||||
if (!artifactFile.exists()) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot find file " + artifactPath, null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!artifactFile.isFile()) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, artifactPath + " is not file", null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
final String genContentRootPath = ((MyGenerationItem)item).getGenContentRootPath();
|
||||
final File genContentRootFile = new File(genContentRootPath);
|
||||
|
||||
if (genContentRootFile.exists()) {
|
||||
if (!FileUtil.delete(genContentRootFile)) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot delete old directory: " + genContentRootPath, null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!genContentRootFile.mkdir()) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot create directory " + genContentRootPath, null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
ZipUtil.extract(artifactFile, genContentRootFile, null);
|
||||
}
|
||||
catch (IOException e) {
|
||||
final String message = e.getMessage();
|
||||
if (message == null) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Unknown I/O error", null, -1, -1);
|
||||
LOG.error(e);
|
||||
}
|
||||
else {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1);
|
||||
LOG.info(e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(genItem);
|
||||
}
|
||||
|
||||
return result.toArray(new GenerationItem[result.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Android External Apklib Extracting Compiler";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateConfiguration(CompileScope scope) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidityState createValidityState(DataInput in) throws IOException {
|
||||
return TimestampValidityState.load(in);
|
||||
}
|
||||
|
||||
private static class MyGenerationItem implements GenerationItem {
|
||||
private final Module myModule;
|
||||
private final String myGenContentRootPath;
|
||||
private final String myArtifactPath;
|
||||
|
||||
private MyGenerationItem(@NotNull Module module, @NotNull String genContentRootPath, @NotNull String artifactPath) {
|
||||
myModule = module;
|
||||
myGenContentRootPath = genContentRootPath;
|
||||
myArtifactPath = artifactPath;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getPath() {
|
||||
return myGenContentRootPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidityState getValidityState() {
|
||||
return new TimestampValidityState(new File(myArtifactPath).lastModified());
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Module getModule() {
|
||||
return myModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestSource() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getGenContentRootPath() {
|
||||
return myGenContentRootPath;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getArtifactPath() {
|
||||
return myArtifactPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,13 @@ public final class AndroidApt {
|
||||
@NotNull String[] resourceDirsOsPaths,
|
||||
@NotNull String[] libPackages,
|
||||
boolean isLibrary) throws IOException {
|
||||
final File outOsDir = new File(outDirOsPath);
|
||||
if (!outOsDir.exists()) {
|
||||
if (!outOsDir.mkdirs()) {
|
||||
LOG.error("Unable to create directory " + outDirOsPath);
|
||||
}
|
||||
}
|
||||
|
||||
final String packageFolderOsPath = FileUtil.toSystemDependentName(outDirOsPath + '/' + aPackage.replace('.', '/'));
|
||||
|
||||
/* We actually need to delete the manifest.java as it may become empty and
|
||||
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
package org.jetbrains.android.maven;
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.xmlb.annotations.AbstractCollection;
|
||||
import com.intellij.util.xmlb.annotations.MapAnnotation;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.model.MavenId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
@State(
|
||||
name = "AndroidExternalApklibDependenciesManager",
|
||||
storages = {
|
||||
@Storage(file = "$WORKSPACE_FILE$")
|
||||
}
|
||||
)
|
||||
public class AndroidExternalApklibDependenciesManager implements PersistentStateComponent<AndroidExternalApklibDependenciesManager.State> {
|
||||
private State myState = new State();
|
||||
|
||||
public static AndroidExternalApklibDependenciesManager getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, AndroidExternalApklibDependenciesManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AndroidExternalApklibDependenciesManager.State getState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(AndroidExternalApklibDependenciesManager.State state) {
|
||||
myState = state;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MyResolvedInfo getResolvedInfoForArtifact(@NotNull MavenId mavenId) {
|
||||
final String key = AndroidMavenUtil.getMavenIdStringForFileName(mavenId);
|
||||
return myState.getResolvedInfoMap().get(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getArtifactFilePath(@NotNull String mavenIdStr) {
|
||||
return myState.getArtifactFilesMap().get(mavenIdStr);
|
||||
}
|
||||
|
||||
public void setSdkInfoForArtifact(@NotNull MavenId mavenId, @NotNull MyResolvedInfo info) {
|
||||
final String key = AndroidMavenUtil.getMavenIdStringForFileName(mavenId);
|
||||
myState.getResolvedInfoMap().put(key, info);
|
||||
}
|
||||
|
||||
public void setArtifactFilePath(@NotNull MavenId mavenId, @NotNull String path) {
|
||||
final String key = AndroidMavenUtil.getMavenIdStringForFileName(mavenId);
|
||||
myState.getArtifactFilesMap().put(key, path);
|
||||
}
|
||||
|
||||
public static class State {
|
||||
private Map<String, String> myArtifactFilesMap = new HashMap<String, String>();
|
||||
private Map<String, MyResolvedInfo> myResolvedInfoMap = new HashMap<String, MyResolvedInfo>();
|
||||
|
||||
@Tag("sdk-infos")
|
||||
@MapAnnotation(surroundWithTag = false)
|
||||
public Map<String, MyResolvedInfo> getResolvedInfoMap() {
|
||||
return myResolvedInfoMap;
|
||||
}
|
||||
|
||||
@Tag("artifacts")
|
||||
@MapAnnotation(surroundWithTag = false)
|
||||
public Map<String, String> getArtifactFilesMap() {
|
||||
return myArtifactFilesMap;
|
||||
}
|
||||
|
||||
public void setArtifactFilesMap(Map<String, String> artifactFilesMap) {
|
||||
myArtifactFilesMap = artifactFilesMap;
|
||||
}
|
||||
|
||||
public void setResolvedInfoMap(Map<String, MyResolvedInfo> artifactId2SdkData) {
|
||||
myResolvedInfoMap = artifactId2SdkData;
|
||||
}
|
||||
}
|
||||
|
||||
@Tag("resolved-info")
|
||||
public static class MyResolvedInfo {
|
||||
private String mySdkPath;
|
||||
private String myApiLevel;
|
||||
private List<MavenDependencyInfo> myApklibDependencies = new ArrayList<MavenDependencyInfo>();
|
||||
|
||||
public MyResolvedInfo(String sdkPath, String apiLevel, Collection<MavenDependencyInfo> dependencyInfos) {
|
||||
mySdkPath = sdkPath;
|
||||
myApiLevel = apiLevel;
|
||||
|
||||
myApklibDependencies = new ArrayList<MavenDependencyInfo>(dependencyInfos);
|
||||
}
|
||||
|
||||
public MyResolvedInfo() {
|
||||
}
|
||||
|
||||
public String getSdkPath() {
|
||||
return mySdkPath;
|
||||
}
|
||||
|
||||
public String getApiLevel() {
|
||||
return myApiLevel;
|
||||
}
|
||||
|
||||
@Tag("dependencies")
|
||||
@AbstractCollection(surroundWithTag = false)
|
||||
public List<MavenDependencyInfo> getApklibDependencies() {
|
||||
return myApklibDependencies;
|
||||
}
|
||||
|
||||
public void setApklibDependencies(List<MavenDependencyInfo> apklibDependencies) {
|
||||
myApklibDependencies = apklibDependencies;
|
||||
}
|
||||
|
||||
public void setSdkPath(String sdkPath) {
|
||||
mySdkPath = sdkPath;
|
||||
}
|
||||
|
||||
public void setApiLevel(String apiLevel) {
|
||||
myApiLevel = apiLevel;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MavenDependencyInfo {
|
||||
private String myGroupId;
|
||||
private String myArtifactId;
|
||||
private String myVersion;
|
||||
private String myType;
|
||||
private String myLibraryName;
|
||||
|
||||
public MavenDependencyInfo() {
|
||||
}
|
||||
|
||||
public MavenDependencyInfo(@NotNull MavenId mavenId, @NotNull String type, @NotNull String libraryName) {
|
||||
myGroupId = mavenId.getGroupId();
|
||||
myArtifactId = mavenId.getArtifactId();
|
||||
myVersion = mavenId.getVersion();
|
||||
myType = type;
|
||||
myLibraryName = libraryName;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return myGroupId;
|
||||
}
|
||||
|
||||
public String getArtifactId() {
|
||||
return myArtifactId;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
public String getLibraryName() {
|
||||
return myLibraryName;
|
||||
}
|
||||
|
||||
public void setGroupId(String groupId) {
|
||||
myGroupId = groupId;
|
||||
}
|
||||
|
||||
public void setArtifactId(String artifactId) {
|
||||
myArtifactId = artifactId;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
myVersion = version;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
myType = type;
|
||||
}
|
||||
|
||||
public void setLibraryName(String libraryName) {
|
||||
myLibraryName = libraryName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,29 @@ package org.jetbrains.android.maven;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.intellij.facet.FacetType;
|
||||
import com.intellij.ide.highlighter.ModuleFileType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.StdModuleTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.io.ZipUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.android.compiler.AndroidCompileUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidFacetConfiguration;
|
||||
import org.jetbrains.android.facet.AndroidFacetType;
|
||||
@@ -36,9 +51,16 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.importing.FacetImporter;
|
||||
import org.jetbrains.idea.maven.importing.MavenModifiableModelsProvider;
|
||||
import org.jetbrains.idea.maven.importing.MavenRootModelAdapter;
|
||||
import org.jetbrains.idea.maven.model.MavenArtifact;
|
||||
import org.jetbrains.idea.maven.model.MavenId;
|
||||
import org.jetbrains.idea.maven.project.*;
|
||||
import org.jetbrains.idea.maven.server.MavenEmbedderWrapper;
|
||||
import org.jetbrains.idea.maven.server.NativeMavenProjectHolder;
|
||||
import org.jetbrains.idea.maven.utils.MavenProcessCanceledException;
|
||||
import org.jetbrains.idea.maven.utils.MavenProgressIndicator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -47,6 +69,9 @@ import java.util.*;
|
||||
*/
|
||||
public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFacet, AndroidFacetConfiguration, AndroidFacetType> {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.maven.AndroidFacetImporterBase");
|
||||
|
||||
private static final Key<Boolean> MODULE_IMPORTED = Key.create("ANDROID_NEWLY_CREATED_KEY");
|
||||
private static final Key<Boolean> NEED_TO_DELETE_OBSOLETE_MODULES_KEY = Key.create("NEED_TO_DELETE_OBSOLETE_MODULES_KEY");
|
||||
|
||||
public AndroidFacetImporterBase(@NotNull String pluginId) {
|
||||
super("com.jayway.maven.plugins.android.generation2", pluginId, FacetType.findInstance(AndroidFacetType.class), "Android");
|
||||
@@ -66,7 +91,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
|
||||
@NotNull
|
||||
private static String[] getSupportedPackagingTypes() {
|
||||
return new String[] {"apk", AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE};
|
||||
return new String[]{AndroidMavenUtil.APK_PACKAGING_TYPE, AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,7 +106,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
facet.getConfiguration().init(facet.getModule(), mavenProjectDirPath);
|
||||
AndroidMavenProviderImpl.setPathsToDefault(mavenProject, facet.getModule(), facet.getConfiguration());
|
||||
AndroidMavenProviderImpl.configureAaptCompilation(mavenProject, facet.getModule(), facet.getConfiguration(),
|
||||
AndroidMavenProviderImpl.hasApkSourcesDependency(mavenProject));
|
||||
AndroidMavenProviderImpl.hasApkSourcesDependency(mavenProject));
|
||||
|
||||
if (AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE.equals(mavenProject.getPackaging())) {
|
||||
facet.getConfiguration().LIBRARY_PROJECT = true;
|
||||
@@ -100,17 +125,379 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
List<MavenProjectsProcessorTask> postTasks) {
|
||||
configurePaths(facet, mavenProject);
|
||||
configureAndroidPlatform(facet, mavenProject, modelsProvider);
|
||||
importExternalApklibDependencies(module.getProject(), rootModel, modelsProvider, mavenTree, mavenProject, postTasks);
|
||||
|
||||
if (hasApklibDependencies(mavenProject) &&
|
||||
MavenProjectsManager.getInstance(module.getProject()).getImportingSettings().isUseMavenOutput()) {
|
||||
// IDEA's apklibs building model is different from Maven's one, so we cannot use the same
|
||||
rootModel.useModuleOutput(mavenProject.getBuildDirectory() + "/idea-classes",
|
||||
mavenProject.getBuildDirectory() + "/idea-test-classes");
|
||||
}
|
||||
|
||||
postTasks.add(new MyDeleteObsoleteApklibModulesTask(module.getProject(), mavenProject, mavenTree));
|
||||
}
|
||||
|
||||
private static boolean hasApklibDependencies(@NotNull MavenProject mavenProject) {
|
||||
for (MavenArtifact depArtifact : mavenProject.getDependencies()) {
|
||||
if (AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE.equals(depArtifact.getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void importExternalApklibDependencies(Project project,
|
||||
MavenRootModelAdapter rootModelAdapter,
|
||||
MavenModifiableModelsProvider modelsProvider,
|
||||
MavenProjectsTree mavenTree,
|
||||
MavenProject mavenProject,
|
||||
List<MavenProjectsProcessorTask> tasks) {
|
||||
final ModifiableRootModel rootModel = rootModelAdapter.getRootModel();
|
||||
removeExtApklibDependencies(rootModel);
|
||||
|
||||
for (MavenArtifact depArtifact : mavenProject.getDependencies()) {
|
||||
if (AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE.equals(depArtifact.getType()) &&
|
||||
mavenTree.findProject(depArtifact) == null) {
|
||||
|
||||
final ModifiableModuleModel moduleModel = modelsProvider.getModuleModel();
|
||||
final String apklibModuleName = AndroidMavenUtil.getModuleNameForExtApklibArtifact(depArtifact.getMavenId());
|
||||
Module apklibModule = moduleModel.findModuleByName(apklibModuleName);
|
||||
|
||||
if (apklibModule == null || apklibModule.getUserData(MODULE_IMPORTED) == null) {
|
||||
apklibModule =
|
||||
importExternalApklibArtifact(project, rootModelAdapter, apklibModule, modelsProvider, mavenProject, mavenTree, depArtifact,
|
||||
moduleModel);
|
||||
if (apklibModule != null) {
|
||||
apklibModule.putUserData(MODULE_IMPORTED, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (apklibModule != null) {
|
||||
final Module finalGenModule = apklibModule;
|
||||
tasks.add(new MavenProjectsProcessorTask() {
|
||||
@Override
|
||||
public void perform(Project project,
|
||||
MavenEmbeddersManager embeddersManager,
|
||||
MavenConsole console,
|
||||
MavenProgressIndicator indicator)
|
||||
throws MavenProcessCanceledException {
|
||||
finalGenModule.putUserData(MODULE_IMPORTED, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (ArrayUtil.find(rootModel.getDependencyModuleNames(), apklibModuleName) < 0) {
|
||||
addCompileModuleDependency(modelsProvider, rootModel, apklibModuleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeExtApklibDependencies(ModifiableRootModel modifiableRootModel) {
|
||||
for (OrderEntry entry : modifiableRootModel.getOrderEntries()) {
|
||||
if (entry instanceof ModuleOrderEntry) {
|
||||
final Module depModule = ((ModuleOrderEntry)entry).getModule();
|
||||
if (depModule != null && AndroidMavenUtil.isExtApklibModule(depModule)) {
|
||||
modifiableRootModel.removeOrderEntry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addCompileModuleDependency(@NotNull MavenModifiableModelsProvider modelsProvider,
|
||||
@NotNull ModifiableRootModel rootModel,
|
||||
@NotNull final String moduleName) {
|
||||
if (findModuleDependency(rootModel, moduleName) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Module module = modelsProvider.getModuleModel().findModuleByName(moduleName);
|
||||
|
||||
final ModuleOrderEntry entry = module != null
|
||||
? rootModel.addModuleOrderEntry(module)
|
||||
: rootModel.addInvalidModuleEntry(moduleName);
|
||||
entry.setScope(DependencyScope.COMPILE);
|
||||
}
|
||||
|
||||
private static ModuleOrderEntry findModuleDependency(ModifiableRootModel rootModel, final String moduleName) {
|
||||
final Ref<ModuleOrderEntry> result = Ref.create(null);
|
||||
|
||||
rootModel.orderEntries().forEach(new Processor<OrderEntry>() {
|
||||
@Override
|
||||
public boolean process(OrderEntry entry) {
|
||||
if (entry instanceof ModuleOrderEntry) {
|
||||
final ModuleOrderEntry moduleEntry = (ModuleOrderEntry)entry;
|
||||
final String name = moduleEntry.getModuleName();
|
||||
if (moduleName.equals(name)) {
|
||||
result.set(moduleEntry);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return result.get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Module importExternalApklibArtifact(Project project,
|
||||
MavenRootModelAdapter rootModelAdapter,
|
||||
Module apklibModule,
|
||||
MavenModifiableModelsProvider modelsProvider,
|
||||
MavenProject mavenProject,
|
||||
MavenProjectsTree mavenTree,
|
||||
MavenArtifact artifact,
|
||||
ModifiableModuleModel moduleModel) {
|
||||
final MavenId artifactMavenId = artifact.getMavenId();
|
||||
|
||||
final String genModuleName = AndroidMavenUtil.getModuleNameForExtApklibArtifact(artifactMavenId);
|
||||
|
||||
String targetDirPath =
|
||||
AndroidMavenUtil.computePathToUnpackExtApklibArtifact(artifactMavenId, mavenProject, mavenTree.getProjects());
|
||||
|
||||
if (targetDirPath == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final File targetDir = new File(targetDirPath);
|
||||
if (targetDir.exists()) {
|
||||
if (!FileUtil.delete(targetDir)) {
|
||||
LOG.error("Cannot delete old " + targetDirPath);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetDir.mkdirs()) {
|
||||
LOG.error("Cannot create directory " + targetDirPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
final File artifactFile = artifact.getFile();
|
||||
|
||||
final AndroidExternalApklibDependenciesManager adm = AndroidExternalApklibDependenciesManager.getInstance(project);
|
||||
|
||||
adm.setArtifactFilePath(artifactMavenId, FileUtil.toSystemIndependentName(artifactFile.getPath()));
|
||||
|
||||
if (artifactFile.exists()) {
|
||||
try {
|
||||
ZipUtil.extract(artifactFile, targetDir, null);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.info("Cannot find file " + artifactFile.getPath());
|
||||
}
|
||||
|
||||
final VirtualFile vApklibDir = LocalFileSystem.getInstance().refreshAndFindFileByPath(targetDirPath);
|
||||
if (vApklibDir == null) {
|
||||
LOG.error("Cannot find file " + targetDirPath + " in VFS");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (apklibModule == null) {
|
||||
final String genModuleFilePath = vApklibDir.getPath() + '/' + genModuleName + ModuleFileType.DOT_DEFAULT_EXTENSION;
|
||||
apklibModule = moduleModel.newModule(genModuleFilePath, StdModuleTypes.JAVA);
|
||||
}
|
||||
|
||||
final ModifiableRootModel apklibModuleModel = modelsProvider.getRootModel(apklibModule);
|
||||
final ContentEntry contentEntry = apklibModuleModel.addContentEntry(vApklibDir);
|
||||
|
||||
final VirtualFile sourceRoot = vApklibDir.findChild(AndroidMavenUtil.APK_LIB_ARTIFACT_SOURCE_ROOT);
|
||||
if (sourceRoot != null) {
|
||||
contentEntry.addSourceFolder(sourceRoot, false);
|
||||
}
|
||||
else {
|
||||
LOG.info("Cannot find " + AndroidMavenUtil.APK_LIB_ARTIFACT_SOURCE_ROOT + " directory in " + vApklibDir.getPath());
|
||||
}
|
||||
|
||||
final AndroidFacet facet = AndroidUtils.addAndroidFacet(apklibModuleModel, vApklibDir, true);
|
||||
|
||||
final AndroidFacetConfiguration configuration = facet.getConfiguration();
|
||||
configuration.RES_FOLDER_RELATIVE_PATH = '/' + AndroidMavenUtil.APK_LIB_ARTIFACT_RES_DIR;
|
||||
configuration.LIBS_FOLDER_RELATIVE_PATH = '/' + AndroidMavenUtil.APK_LIB_ARTIFACT_NATIVE_LIBS_DIR;
|
||||
configuration.MANIFEST_FILE_RELATIVE_PATH = '/' + AndroidMavenUtil.APK_LIB_ARTIFACT_MANIFEST_FILE;
|
||||
|
||||
importSdkAndDependenciesForApklibArtifact(project, rootModelAdapter, apklibModuleModel, modelsProvider, mavenTree, artifact);
|
||||
|
||||
return apklibModule;
|
||||
}
|
||||
|
||||
private static void importSdkAndDependenciesForApklibArtifact(Project project,
|
||||
MavenRootModelAdapter rootModelAdapter,
|
||||
ModifiableRootModel apklibModuleModel,
|
||||
MavenModifiableModelsProvider modelsProvider,
|
||||
MavenProjectsTree mavenTree,
|
||||
MavenArtifact artifact) {
|
||||
final AndroidExternalApklibDependenciesManager adm = AndroidExternalApklibDependenciesManager.getInstance(project);
|
||||
final AndroidExternalApklibDependenciesManager.MyResolvedInfo resolvedInfo =
|
||||
adm.getResolvedInfoForArtifact(artifact.getMavenId());
|
||||
|
||||
for (OrderEntry entry : apklibModuleModel.getOrderEntries()) {
|
||||
if (entry instanceof ModuleOrderEntry || entry instanceof LibraryOrderEntry) {
|
||||
apklibModuleModel.removeOrderEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedInfo != null) {
|
||||
final Sdk sdk = findOrCreateAndroidPlatform(resolvedInfo.getSdkPath(), resolvedInfo.getApiLevel());
|
||||
|
||||
if (sdk != null) {
|
||||
apklibModuleModel.setSdk(sdk);
|
||||
}
|
||||
|
||||
for (AndroidExternalApklibDependenciesManager.MavenDependencyInfo depArtifactInfo : resolvedInfo.getApklibDependencies()) {
|
||||
final MavenId depMavenId = new MavenId(depArtifactInfo.getGroupId(), depArtifactInfo.getArtifactId(),
|
||||
depArtifactInfo.getVersion());
|
||||
|
||||
final String type = depArtifactInfo.getType();
|
||||
|
||||
if (AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE.equals(type)) {
|
||||
final MavenProject depProject = mavenTree.findProject(depMavenId);
|
||||
|
||||
if (depProject != null) {
|
||||
final Module depModule = MavenProjectsManager.getInstance(project).findModule(depProject);
|
||||
if (depModule != null && findModuleDependency(apklibModuleModel, depModule.getName()) == null) {
|
||||
apklibModuleModel.addModuleOrderEntry(depModule);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String depApklibGenModuleName = AndroidMavenUtil.getModuleNameForExtApklibArtifact(depMavenId);
|
||||
addCompileModuleDependency(modelsProvider, apklibModuleModel, depApklibGenModuleName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String libraryName = depArtifactInfo.getLibraryName();
|
||||
final ModifiableRootModel rootModel = rootModelAdapter.getRootModel();
|
||||
final LibraryOrderEntry libEntry = findLibraryByName(rootModel, libraryName);
|
||||
|
||||
if (libEntry != null) {
|
||||
final Library library = libEntry.getLibrary();
|
||||
|
||||
if (library != null && apklibModuleModel.findLibraryOrderEntry(library) == null) {
|
||||
final LibraryOrderEntry newLibEntry = apklibModuleModel.addLibraryEntry(library);
|
||||
newLibEntry.setExported(libEntry.isExported());
|
||||
newLibEntry.setScope(libEntry.getScope());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.info("Cannot find sdk info for artifact " + artifact.getMavenId().getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LibraryOrderEntry findLibraryByName(ModifiableRootModel model, final String libraryName) {
|
||||
final Ref<LibraryOrderEntry> result = Ref.create(null);
|
||||
model.orderEntries().forEach(new Processor<OrderEntry>() {
|
||||
@Override
|
||||
public boolean process(OrderEntry entry) {
|
||||
if (entry instanceof LibraryOrderEntry) {
|
||||
final LibraryOrderEntry libOrderEntry = (LibraryOrderEntry)entry;
|
||||
final Library library = libOrderEntry.getLibrary();
|
||||
|
||||
if (library != null && libraryName.equals(library.getName())) {
|
||||
result.set(libOrderEntry);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return result.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(final Project project,
|
||||
MavenProject mavenProject,
|
||||
NativeMavenProjectHolder nativeMavenProject,
|
||||
MavenEmbedderWrapper embedder)
|
||||
throws MavenProcessCanceledException {
|
||||
|
||||
for (MavenArtifact depArtifact : mavenProject.getDependencies()) {
|
||||
final MavenProjectsManager mavenProjectsManager = MavenProjectsManager.getInstance(project);
|
||||
|
||||
if (AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE.equals(depArtifact.getType()) &&
|
||||
mavenProjectsManager.findProject(depArtifact) == null) {
|
||||
|
||||
doResolveApklibArtifact(project, depArtifact, embedder, mavenProjectsManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doResolveApklibArtifact(Project project,
|
||||
MavenArtifact artifact,
|
||||
MavenEmbedderWrapper embedder,
|
||||
MavenProjectsManager mavenProjectsManager) throws MavenProcessCanceledException {
|
||||
final File depArtifacetFile = new File(FileUtil.getNameWithoutExtension(artifact.getPath()) + ".pom");
|
||||
if (!depArtifacetFile.exists()) {
|
||||
LOG.info("Cannot find file " + depArtifacetFile.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
final VirtualFile vDepArtifactFile = LocalFileSystem.getInstance().findFileByIoFile(depArtifacetFile);
|
||||
if (vDepArtifactFile == null) {
|
||||
LOG.error("Cannot find file " + depArtifacetFile.getPath() + " in VFS");
|
||||
return;
|
||||
}
|
||||
|
||||
final MavenProject projectForExternalApklib = new MavenProject(vDepArtifactFile);
|
||||
final MavenGeneralSettings generalSettings = mavenProjectsManager.getGeneralSettings();
|
||||
final MavenProjectReader mavenProjectReader = new MavenProjectReader();
|
||||
|
||||
final MavenProjectReaderProjectLocator locator = new MavenProjectReaderProjectLocator() {
|
||||
@Nullable
|
||||
@Override
|
||||
public VirtualFile findProjectFile(MavenId coordinates) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
projectForExternalApklib.read(generalSettings, mavenProjectsManager.getAvailableProfiles(), mavenProjectReader, locator);
|
||||
projectForExternalApklib.resolve(project, generalSettings, embedder, mavenProjectReader, locator);
|
||||
|
||||
final String apiLevel = getPlatformFromConfig(projectForExternalApklib);
|
||||
final String sdkPath = getSdkPathFromConfig(projectForExternalApklib);
|
||||
|
||||
final List<AndroidExternalApklibDependenciesManager.MavenDependencyInfo> dependencies =
|
||||
new ArrayList<AndroidExternalApklibDependenciesManager.MavenDependencyInfo>();
|
||||
|
||||
for (MavenArtifact depArtifact : projectForExternalApklib.getDependencies()) {
|
||||
final String depArtifactLibraryName = MavenRootModelAdapter.makeLibraryName(depArtifact);
|
||||
|
||||
dependencies.add(new AndroidExternalApklibDependenciesManager.MavenDependencyInfo(
|
||||
depArtifact.getMavenId(), depArtifact.getType(), depArtifactLibraryName));
|
||||
}
|
||||
|
||||
final AndroidExternalApklibDependenciesManager apklibDependenciesManager =
|
||||
AndroidExternalApklibDependenciesManager.getInstance(project);
|
||||
|
||||
final AndroidExternalApklibDependenciesManager.MyResolvedInfo info = new AndroidExternalApklibDependenciesManager.MyResolvedInfo(
|
||||
apiLevel != null ? apiLevel : "",
|
||||
sdkPath != null ? sdkPath : "",
|
||||
dependencies
|
||||
);
|
||||
|
||||
apklibDependenciesManager.setSdkInfoForArtifact(artifact.getMavenId(), info);
|
||||
}
|
||||
|
||||
private void configureAndroidPlatform(AndroidFacet facet, MavenProject project, MavenModifiableModelsProvider modelsProvider) {
|
||||
final Sdk currentSdk = modelsProvider.getRootModel(facet.getModule()).getSdk();
|
||||
final ModifiableRootModel model = modelsProvider.getRootModel(facet.getModule());
|
||||
configureAndroidPlatform(project, model);
|
||||
}
|
||||
|
||||
private void configureAndroidPlatform(MavenProject project, ModifiableRootModel model) {
|
||||
final Sdk currentSdk = model.getSdk();
|
||||
if (currentSdk != null && isAppropriateSdk(currentSdk, project)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sdk platformLib = findOrCreateAndroidPlatform(project);
|
||||
if (platformLib != null) {
|
||||
modelsProvider.getRootModel(facet.getModule()).setSdk(platformLib);
|
||||
model.setSdk(platformLib);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,11 +526,25 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
|
||||
@Nullable
|
||||
private Sdk findOrCreateAndroidPlatform(MavenProject project) {
|
||||
final String apiLevel = getPlatformFromConfig(project);
|
||||
final String predefinedSdkPath = getSdkPathFromConfig(project);
|
||||
return findOrCreateAndroidPlatform(apiLevel, predefinedSdkPath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Sdk findOrCreateAndroidPlatform(String apiLevel, String predefinedSdkPath) {
|
||||
if (predefinedSdkPath != null) {
|
||||
final Sdk sdk = doFindOrCreateAndroidPlatform(predefinedSdkPath, apiLevel);
|
||||
if (sdk != null) {
|
||||
return sdk;
|
||||
}
|
||||
}
|
||||
|
||||
String sdkPath = System.getenv(AndroidSdkUtils.ANDROID_HOME_ENV);
|
||||
LOG.info("android home: " + sdkPath);
|
||||
|
||||
if (sdkPath != null) {
|
||||
final Sdk sdk = findOrCreateAndroidPlatform(project, sdkPath);
|
||||
final Sdk sdk = doFindOrCreateAndroidPlatform(sdkPath, apiLevel);
|
||||
if (sdk != null) {
|
||||
return sdk;
|
||||
}
|
||||
@@ -153,7 +554,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
LOG.info("suggested sdks: " + candidates);
|
||||
|
||||
for (String candidate : candidates) {
|
||||
final Sdk sdk = findOrCreateAndroidPlatform(project, candidate);
|
||||
final Sdk sdk = doFindOrCreateAndroidPlatform(candidate, apiLevel);
|
||||
if (sdk != null) {
|
||||
return sdk;
|
||||
}
|
||||
@@ -162,10 +563,8 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Sdk findOrCreateAndroidPlatform(MavenProject project, String sdkPath) {
|
||||
private static Sdk doFindOrCreateAndroidPlatform(String sdkPath, String apiLevel) {
|
||||
if (sdkPath != null) {
|
||||
final String apiLevel = getPlatformFromConfig(project);
|
||||
|
||||
if (apiLevel == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -196,6 +595,18 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getSdkPathFromConfig(MavenProject project) {
|
||||
Element sdkRoot = getConfig(project, "sdk");
|
||||
if (sdkRoot != null) {
|
||||
Element path = sdkRoot.getChild("path");
|
||||
if (path != null) {
|
||||
return path.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void configurePaths(AndroidFacet facet, MavenProject project) {
|
||||
Module module = facet.getModule();
|
||||
@@ -355,8 +766,101 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyDeleteObsoleteApklibModulesTask extends MavenProjectsProcessorBasicTask {
|
||||
private final Project myProject;
|
||||
|
||||
public MyDeleteObsoleteApklibModulesTask(@NotNull Project project,
|
||||
@NotNull MavenProject mavenProject,
|
||||
@NotNull MavenProjectsTree mavenTree) {
|
||||
super(mavenProject, mavenTree);
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(final Project project,
|
||||
MavenEmbeddersManager embeddersManager,
|
||||
MavenConsole console,
|
||||
MavenProgressIndicator indicator)
|
||||
throws MavenProcessCanceledException {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ModifiableModuleModel moduleModel = ModuleManager.getInstance(project).getModifiableModel();
|
||||
final Set<Module> referredModules = new HashSet<Module>();
|
||||
|
||||
for (Module module : moduleModel.getModules()) {
|
||||
if (!AndroidMavenUtil.isExtApklibModule(module) &&
|
||||
!AndroidCompileUtil.isGenModule(module)) {
|
||||
collectDependenciesRecursively(module, referredModules);
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (final Module module : moduleModel.getModules()) {
|
||||
if (AndroidMavenUtil.isExtApklibModule(module) && !referredModules.contains(module)) {
|
||||
final VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
|
||||
|
||||
if (contentRoots.length > 0) {
|
||||
final VirtualFile contentRoot = contentRoots[0];
|
||||
try {
|
||||
contentRoot.delete(myProject);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
final Module genModule = AndroidCompileUtil.getGenModule(module);
|
||||
if (genModule != null) {
|
||||
moduleModel.disposeModule(genModule);
|
||||
}
|
||||
|
||||
moduleModel.disposeModule(module);
|
||||
}
|
||||
}
|
||||
|
||||
moduleModel.commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void collectDependenciesRecursively(@NotNull Module root, @NotNull Set<Module> result) {
|
||||
if (!result.add(root)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Module depModule : ModuleRootManager.getInstance(root).getDependencies()) {
|
||||
collectDependenciesRecursively(depModule, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
MyDeleteObsoleteApklibModulesTask task = (MyDeleteObsoleteApklibModulesTask)o;
|
||||
|
||||
if (!myProject.equals(task.myProject)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + myProject.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,22 +15,92 @@
|
||||
*/
|
||||
package org.jetbrains.android.maven;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.model.MavenId;
|
||||
import org.jetbrains.idea.maven.project.MavenProject;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidMavenUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.maven.AndroidMavenUtil");
|
||||
|
||||
@NonNls public static final String APKSOURCES_DEPENDENCY_TYPE = "apksources";
|
||||
@NonNls public static final String APKLIB_DEPENDENCY_AND_PACKAGING_TYPE = "apklib";
|
||||
@NonNls public static final String APK_PACKAGING_TYPE = "apk";
|
||||
|
||||
@NonNls public static final String APK_LIB_ARTIFACT_SOURCE_ROOT = "src";
|
||||
@NonNls public static final String APK_LIB_ARTIFACT_RES_DIR = "res";
|
||||
public static final String APK_LIB_ARTIFACT_NATIVE_LIBS_DIR = "libs";
|
||||
public static final String APK_LIB_ARTIFACT_MANIFEST_FILE = "AndroidManifest.xml";
|
||||
@NonNls private static final String APKLIB_MODULE_PREFIX = "~apklib-";
|
||||
|
||||
private AndroidMavenUtil() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String computePathToUnpackExtApklibArtifact(@NotNull MavenId mavenId,
|
||||
@NotNull MavenProject project,
|
||||
@NotNull Collection<MavenProject> allProjects) {
|
||||
String path = null;
|
||||
boolean resultUnderApp = false;
|
||||
|
||||
for (MavenProject p : allProjects) {
|
||||
if (p.findDependencies(mavenId).size() > 0) {
|
||||
final VirtualFile projectDir = p.getDirectoryFile();
|
||||
final boolean app = APK_PACKAGING_TYPE.equals(p.getPackaging());
|
||||
if (path == null || !resultUnderApp && app) {
|
||||
path = projectDir.getPath() + '/' + getDirNameToUnpackExtApklibArtifact(mavenId);
|
||||
resultUnderApp = app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
path = project.getDirectoryFile().getPath() + '/' + getDirNameToUnpackExtApklibArtifact(mavenId);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDirNameToUnpackExtApklibArtifact(@NotNull MavenId mavenId) {
|
||||
return "gen-external-apklibs/" + getMavenIdStringForFileName(mavenId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getModuleNameForExtApklibArtifact(MavenId mavenId) {
|
||||
return APKLIB_MODULE_PREFIX + getMavenIdStringForFileName(mavenId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getMavenIdStringByExtApklibModule(@NotNull Module module) {
|
||||
final String moduleName = module.getName();
|
||||
|
||||
if (!moduleName.startsWith(APKLIB_MODULE_PREFIX)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return moduleName.substring(APKLIB_MODULE_PREFIX.length());
|
||||
}
|
||||
|
||||
public static boolean isExtApklibModule(@NotNull Module module) {
|
||||
return module.getName().startsWith(APKLIB_MODULE_PREFIX);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getMavenIdStringForFileName(@NotNull MavenId mavenId) {
|
||||
final String artifactId = mavenId.getKey().replace(':', '_');
|
||||
return artifactId != null ? artifactId : "null";
|
||||
}
|
||||
|
||||
public static boolean isMavenizedModule(@NotNull Module module) {
|
||||
AndroidMavenProvider mavenProxy = getMavenProvider();
|
||||
return mavenProxy != null && mavenProxy.isMavenizedModule(module);
|
||||
|
||||
Reference in New Issue
Block a user