Java tutorial
/* * ### * Android Maven Plugin - android-maven-plugin * * Copyright (C) 1999 - 2012 Photon Infotech Inc. * * 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. * ### */ /* * Copyright (C) 2009 Jayway AB * * 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.photon.maven.plugins.android.common; import static com.photon.maven.plugins.android.common.AndroidExtension.APKLIB; import static org.apache.maven.RepositoryUtils.toDependency; import java.io.File; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.sonatype.aether.RepositorySystem; import org.sonatype.aether.RepositorySystemSession; import org.sonatype.aether.collection.CollectRequest; import org.sonatype.aether.graph.Dependency; import org.sonatype.aether.graph.DependencyFilter; import org.sonatype.aether.graph.DependencyNode; import org.sonatype.aether.repository.RemoteRepository; import org.sonatype.aether.resolution.DependencyRequest; import org.sonatype.aether.util.filter.AndDependencyFilter; import org.sonatype.aether.util.filter.ScopeDependencyFilter; import org.sonatype.aether.util.graph.PreorderNodeListGenerator; import com.photon.maven.plugins.android.AbstractAndroidMojo; import com.photon.maven.plugins.android.AndroidNdk; /** */ public class NativeHelper { public static final int NDK_REQUIRED_VERSION = 7; private MavenProject project; private RepositorySystemSession repoSession; private RepositorySystem repoSystem; private ArtifactFactory artifactFactory; private Log log; private List<RemoteRepository> projectRepos; public NativeHelper(MavenProject project, List<RemoteRepository> projectRepos, RepositorySystemSession repoSession, RepositorySystem repoSystem, ArtifactFactory artifactFactory, Log log) { this.project = project; this.projectRepos = projectRepos; this.repoSession = repoSession; this.repoSystem = repoSystem; this.artifactFactory = artifactFactory; this.log = log; } public static boolean hasStaticNativeLibraryArtifact(Set<Artifact> resolveNativeLibraryArtifacts) { for (Artifact resolveNativeLibraryArtifact : resolveNativeLibraryArtifacts) { if ("a".equals(resolveNativeLibraryArtifact.getType())) { return true; } } return false; } public static boolean hasSharedNativeLibraryArtifact(Set<Artifact> resolveNativeLibraryArtifacts) { for (Artifact resolveNativeLibraryArtifact : resolveNativeLibraryArtifacts) { if ("so".equals(resolveNativeLibraryArtifact.getType())) { return true; } } return false; } public Set<Artifact> getNativeDependenciesArtifacts(File unpackDirectory, boolean sharedLibraries) throws MojoExecutionException { final Set<Artifact> filteredArtifacts = new LinkedHashSet<Artifact>(); // Add all dependent artifacts declared in the pom file @SuppressWarnings("unchecked") final Set<Artifact> allArtifacts = project.getDependencyArtifacts(); // Add all attached artifacts as well - this could come from the NDK mojo for example boolean result = allArtifacts.addAll(project.getAttachedArtifacts()); for (Artifact artifact : allArtifacts) { // A null value in the scope indicates that the artifact has been attached // as part of a previous build step (NDK mojo) if (isNativeLibrary(sharedLibraries, artifact.getType()) && artifact.getScope() == null) { // Including attached artifact log.debug("Including attached artifact: " + artifact.getArtifactId() + "(" + artifact.getGroupId() + ")"); filteredArtifacts.add(artifact); } else if (isNativeLibrary(sharedLibraries, artifact.getType()) && (Artifact.SCOPE_COMPILE.equals(artifact.getScope()) || Artifact.SCOPE_RUNTIME.equals(artifact.getScope()))) { filteredArtifacts.add(artifact); } else if (APKLIB.equals(artifact.getType())) { // Check if the artifact contains a libs folder - if so, include it in the list File libsFolder = new File( AbstractAndroidMojo.getLibraryUnpackDirectory(unpackDirectory, artifact) + "/libs"); if (libsFolder.exists()) { filteredArtifacts.add(artifact); } } } Set<Artifact> transientArtifacts = processTransientDependencies(project.getDependencies(), sharedLibraries); filteredArtifacts.addAll(transientArtifacts); return filteredArtifacts; } private boolean isNativeLibrary(boolean sharedLibraries, String artifactType) { return (sharedLibraries ? "so".equals(artifactType) : "a".equals(artifactType)); } private Set<Artifact> processTransientDependencies(List<org.apache.maven.model.Dependency> dependencies, boolean sharedLibraries) throws MojoExecutionException { Set<Artifact> transientArtifacts = new LinkedHashSet<Artifact>(); for (org.apache.maven.model.Dependency dependency : dependencies) { if (!"provided".equals(dependency.getScope()) && !dependency.isOptional()) { transientArtifacts.addAll(processTransientDependencies( toDependency(dependency, repoSession.getArtifactTypeRegistry()), sharedLibraries)); } } return transientArtifacts; } private Set<Artifact> processTransientDependencies(Dependency dependency, boolean sharedLibraries) throws MojoExecutionException { try { final Set<Artifact> artifacts = new LinkedHashSet<Artifact>(); final CollectRequest collectRequest = new CollectRequest(); collectRequest.setRoot(dependency); collectRequest.setRepositories(projectRepos); final DependencyNode node = repoSystem.collectDependencies(repoSession, collectRequest).getRoot(); final DependencyRequest dependencyRequest = new DependencyRequest(node, new AndDependencyFilter( new ScopeDependencyFilter(Arrays.asList("compile", "runtime"), Arrays.asList("test")), // Also exclude any optional dependencies new DependencyFilter() { @Override public boolean accept(DependencyNode dependencyNode, List<DependencyNode> dependencyNodes) { return !dependencyNode.getDependency().isOptional(); } })); repoSystem.resolveDependencies(repoSession, dependencyRequest); PreorderNodeListGenerator nlg = new PreorderNodeListGenerator(); node.accept(nlg); final List<Dependency> dependencies = nlg.getDependencies(false); for (Dependency dep : dependencies) { final org.sonatype.aether.artifact.Artifact depAetherArtifact = dep.getArtifact(); if (isNativeLibrary(sharedLibraries, depAetherArtifact.getExtension())) { final Artifact mavenArtifact = artifactFactory.createDependencyArtifact( depAetherArtifact.getGroupId(), depAetherArtifact.getArtifactId(), VersionRange.createFromVersion(depAetherArtifact.getVersion()), depAetherArtifact.getExtension(), depAetherArtifact.getClassifier(), dep.getScope()); mavenArtifact.setFile(depAetherArtifact.getFile()); artifacts.add(mavenArtifact); } } return artifacts; } catch (Exception e) { throw new MojoExecutionException("Error while processing transient dependencies", e); } } public static void validateNDKVersion(File ndkHomeDir) throws MojoExecutionException { final File ndkVersionFile = new File(ndkHomeDir, "RELEASE.TXT"); if (!ndkVersionFile.exists()) { throw new MojoExecutionException("Could not locate RELEASE.TXT in the Android NDK base directory '" + ndkHomeDir.getAbsolutePath() + "'. Please verify your setup! " + AndroidNdk.PROPER_NDK_HOME_DIRECTORY_MESSAGE); } try { String versionStr = FileUtils.readFileToString(ndkVersionFile); validateNDKVersion(NDK_REQUIRED_VERSION, versionStr); } catch (Exception e) { throw new MojoExecutionException( "Error while extracting NDK version from '" + ndkVersionFile.getAbsolutePath() + "'. Please verify your setup! " + AndroidNdk.PROPER_NDK_HOME_DIRECTORY_MESSAGE); } } public static void validateNDKVersion(int desiredVersion, String versionStr) throws MojoExecutionException { int version = 0; if (versionStr != null) { versionStr = versionStr.trim(); Pattern pattern = Pattern.compile("[r]([0-9]{1,3})([a-z]{0,1}).*"); Matcher m = pattern.matcher(versionStr); if (m.matches()) { final String group = m.group(1); version = Integer.parseInt(group); } } if (version < desiredVersion) { throw new MojoExecutionException("You are running an old NDK (version " + versionStr + "), please update to at least r'" + desiredVersion + "' or later"); } } }