blob: d920117de079f7e257e70ea5ba5a5056bafefb3a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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 org.apache.sling.feature.analyser.task.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Optional;
import org.apache.commons.lang3.SystemUtils;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
public class CheckJDeps extends AbstractApiRegionsAnalyserTask {
private static final String CLASSIFIER_APIS = "apis";
private static final String DEP_NOT_FOUND_TOKEN = "not found";
private static final String JDEPS_CMD = "jdeps";
private static final String PARAMETER_APIS_JARS_DIR = "apis-jars-dir";
private static final String PARAMETER_OWNED_PACKAGES = "owned-packages";
private static final String PARAMETER_EXCEPTION_PACKAGES = "exception-packages";
private static final String PARAMETER_SYSTEM_PACKAGES = "system-packages";
@Override
protected void execute(ApiRegions apiRegions, AnalyserTaskContext ctx) throws Exception {
File jDepsExe;
try {
jDepsExe = getJDepsExecutable();
} catch (Exception e) {
ctx.reportError(e.getMessage());
return;
}
Optional<String> apisJarDirLocation = getConfigurationParameterValue(PARAMETER_APIS_JARS_DIR, ctx);
if (!apisJarDirLocation.isPresent()) {
ctx.reportWarning("No apis-jars directory specified, skipping current analyser execution");
return;
}
File apisJarDir = new File(apisJarDirLocation.get());
if (!apisJarDir.exists() || !apisJarDir.isDirectory()) {
ctx.reportWarning("apis-jars directory "
+ apisJarDir
+ " does not exist or it is not a valid directory, skipping current analyser execution");
return;
}
String[] ownedPackages = getConfigurationParameterValues(PARAMETER_OWNED_PACKAGES, ctx);
String[] exceptionPackages = getConfigurationParameterValues(PARAMETER_EXCEPTION_PACKAGES, ctx);
String[] systemPackages = getConfigurationParameterValues(PARAMETER_SYSTEM_PACKAGES, ctx);
for (String apiRegion : apiRegions.getRegions()) {
execute(jDepsExe, apisJarDir, apiRegion, ownedPackages, exceptionPackages, systemPackages, ctx);
}
}
private void execute(File jDepsExe,
File apisJarDir,
String apiRegion,
String[] ownedPackages,
String[] exceptionPackages,
String[] systemPackages,
AnalyserTaskContext ctx) throws Exception {
ArtifactId featureId = ctx.getFeature().getId();
// classifier is built according to ApisJarMojo
StringBuilder classifierBuilder = new StringBuilder();
if (featureId.getClassifier() != null) {
classifierBuilder.append(featureId.getClassifier())
.append('-');
}
String finalClassifier = classifierBuilder.append(apiRegion)
.append('-')
.append(CLASSIFIER_APIS)
.toString();
String targetName = String.format("%s-%s-%s.jar", featureId.getArtifactId(), featureId.getVersion(), finalClassifier);
File apisJar = new File(apisJarDir, targetName);
if (!apisJar.exists() || !apisJar.isFile()) {
ctx.reportWarning("apis-jar file "
+ apisJar
+ " does not exist or it is not a valid file, skipping current region '"
+ apiRegion
+ "'analyser execution");
return;
}
String[] command = { jDepsExe.getAbsolutePath(), "-apionly", "-verbose", apisJar.getAbsolutePath() };
ProcessBuilder pb = new ProcessBuilder(command);
Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.contains(DEP_NOT_FOUND_TOKEN)
&& isAbout(line, ownedPackages)
&& !isAbout(line, exceptionPackages)
&& !isAbout(line, systemPackages)) {
line = line.replaceAll(DEP_NOT_FOUND_TOKEN, "");
ctx.reportError(line);
}
}
int exitValue = process.waitFor();
if (exitValue != 0) {
ctx.reportError(JDEPS_CMD + " terminated with code " + exitValue);
}
}
private static File getJDepsExecutable() throws Exception {
String jDepsCommand = JDEPS_CMD + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "");
File jDepsExe;
// For IBM's JDK 1.2
if (SystemUtils.IS_OS_AIX) {
jDepsExe = getFile(SystemUtils.getJavaHome(), "..", "sh", jDepsCommand);
} else {
jDepsExe = getFile(SystemUtils.getJavaHome(), "..", "bin", jDepsCommand);
}
// ----------------------------------------------------------------------
// Try to find jdeps exe from JAVA_HOME environment variable
// ----------------------------------------------------------------------
if (!jDepsExe.exists() || !jDepsExe.isFile()) {
String javaHome = System.getenv().get("JAVA_HOME");
if (javaHome == null || javaHome.isEmpty()) {
throw new Exception("The environment variable JAVA_HOME is not correctly set.");
}
File javaHomeDir = new File(javaHome);
if ((!javaHomeDir.exists()) || javaHomeDir.isFile()) {
throw new Exception("The environment variable JAVA_HOME="
+ javaHome
+ " does not exist or is not a valid directory.");
}
jDepsExe = getFile(javaHomeDir, "bin", jDepsCommand);
if (!jDepsExe.exists() || !jDepsExe.isFile()) {
throw new Exception("The jdeps executable '"
+ jDepsExe
+ "' doesn't exist or is not a file. Verify the JAVA_HOME environment variable.");
}
}
return jDepsExe;
}
private static Optional<String> getConfigurationParameterValue(String key, AnalyserTaskContext ctx) {
String value = ctx.getConfiguration().get(key);
if (value == null || value.isEmpty()) {
ctx.reportWarning("Configuration parameter '" + key + "' is missing.");
return Optional.empty();
}
return Optional.of(value);
}
private static String[] getConfigurationParameterValues(String key, AnalyserTaskContext ctx) {
Optional<String> value = getConfigurationParameterValue(key, ctx);
if (!value.isPresent()) {
return new String[] {};
}
return value.get().split(",");
}
private static boolean isAbout(String line, String[] packages) {
for (String adobePackage : packages) {
// adding . to avoid cases with packages that have the same prefixes
if (line.startsWith(adobePackage + ".")) {
return true;
}
}
return false;
}
private static File getFile(File parent, String... path) {
File tmp = parent;
for (String current : path) {
tmp = new File(tmp, current);
}
return tmp;
}
}