// Copyright 2005-2007, FreeHEP.
package org.freehep.maven.nar;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;
import org.apache.bcel.classfile.ClassFormatException;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.PropertyUtils;
import org.codehaus.plexus.util.cli.Commandline;
/**
* @author Mark Donszelmann
* @version $Id: NarUtil.java 13350 2007-09-20 18:42:29Z duns $
*/
public class NarUtil {
private static Properties defaults;
public static Properties getDefaults() throws MojoFailureException {
// read properties file with defaults
if (defaults == null) {
defaults = PropertyUtils.loadProperties(NarUtil.class
.getResourceAsStream("aol.properties"));
}
if (defaults == null)
throw new MojoFailureException(
"NAR: Could not load default properties file: 'aol.properties'.");
return defaults;
}
public static String getOS(String os) {
// adjust OS if not given
if (os == null) {
os = System.getProperty("os.name");
if (os.startsWith("Windows"))
os = OS.WINDOWS;
if (os.startsWith("windows"))
os = OS.WINDOWS;
if (os.equals("Mac OS X"))
os = OS.MACOSX;
}
return os;
}
public static String getArchitecture(String architecture) {
return architecture;
}
public static Linker getLinker(Linker linker) {
if (linker == null) {
linker = new Linker();
}
return linker;
}
public static String getLinkerName(String architecture, String os,
Linker linker) throws MojoFailureException {
return getLinker(linker).getName(getDefaults(),
getArchitecture(architecture) + "." + getOS(os) + ".");
}
public static AOL getAOL(String architecture, String os, Linker linker,
String aol) throws MojoFailureException {
// adjust aol
return aol == null ? new AOL(getArchitecture(architecture), getOS(os),
getLinkerName(architecture, os, linker)) : new AOL(aol);
}
// FIXME, should go to AOL.
public static String getAOLKey(String architecture, String os, Linker linker)
throws MojoFailureException {
// construct AOL key prefix
return getArchitecture(architecture) + "." + getOS(os) + "."
+ getLinkerName(architecture, os, linker) + ".";
}
public static String getAOLKey(String aol) {
// FIXME, this may not always work correctly
return replace("-", ".", aol);
}
public static File getJavaHome(File javaHome, String os) {
// adjust JavaHome
if (javaHome == null) {
javaHome = new File(System.getProperty("java.home"));
if (!getOS(os).equals("MacOSX")) {
javaHome = new File(javaHome, "..");
}
}
return javaHome;
}
public static void makeExecutable(File file, final Log log)
throws MojoExecutionException, MojoFailureException {
if (!file.exists())
return;
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
makeExecutable(files[i], log);
}
}
if (file.isFile() && file.canRead() && file.canWrite()
&& !file.isHidden()) {
// chmod +x file
int result = runCommand("chmod", new String[] { "+x",
file.getPath() }, null, log);
if (result != 0) {
throw new MojoExecutionException("Failed to execute 'chmod +x "
+ file.getPath() + "'" + " return code: \'" + result
+ "\'.");
}
}
}
public static void runRanlib(File file, final Log log)
throws MojoExecutionException, MojoFailureException {
if (!file.exists()) {
return;
}
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
runRanlib(files[i], log);
}
}
if (file.isFile() && file.canRead() && file.canWrite()
&& !file.isHidden() && file.getName().endsWith(".a")) {
// ranlib file
int result = runCommand("ranlib", new String[] { file.getPath() },
null, log);
if (result != 0) {
throw new MojoExecutionException("Failed to execute 'ranlib "
+ file.getPath() + "'" + " return code: \'" + result
+ "\'.");
}
}
}
/**
* Returns the Bcel Class corresponding to the given class filename
*
* @param filename
* the absolute file name of the class
* @return the Bcel Class.
* @throws IOException,
* ClassFormatException
*/
public static final JavaClass getBcelClass(String filename)
throws IOException, ClassFormatException {
ClassParser parser = new ClassParser(filename);
return parser.parse();
}
/**
* Returns the header file name (javah) corresponding to the given class
* file name
*
* @param filename
* the absolute file name of the class
* @return the header file name.
*/
public static final String getHeaderName(String base, String filename) {
base = base.replaceAll("\\\\", "/");
filename = filename.replaceAll("\\\\", "/");
if (!filename.startsWith(base)) {
throw new IllegalArgumentException("Error " + filename
+ " does not start with " + base);
}
String header = filename.substring(base.length() + 1);
header = header.replaceAll("/", "_");
header = header.replaceAll("\\.class", ".h");
return header;
}
/**
* Replaces target with replacement in string. For jdk 1.4 compatiblity.
*
* @param target
* @param replacement
* @param string
* @return
*/
public static String replace(CharSequence target, CharSequence replacement,
String string) {
return Pattern.compile(quote(target.toString())/*
* , Pattern.LITERAL jdk
* 1.4
*/).matcher(string).replaceAll(
/* Matcher. jdk 1.4 */quoteReplacement(replacement.toString()));
}
/* for jdk 1.4 */
private static String quote(String s) {
int slashEIndex = s.indexOf("\\E");
if (slashEIndex == -1)
return "\\Q" + s + "\\E";
StringBuffer sb = new StringBuffer(s.length() * 2);
sb.append("\\Q");
slashEIndex = 0;
int current = 0;
while ((slashEIndex = s.indexOf("\\E", current)) != -1) {
sb.append(s.substring(current, slashEIndex));
current = slashEIndex + 2;
sb.append("\\E\\\\E\\Q");
}
sb.append(s.substring(current, s.length()));
sb.append("\\E");
return sb.toString();
}
/* for jdk 1.4 */
private static String quoteReplacement(String s) {
if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1))
return s;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\') {
sb.append('\\');
sb.append('\\');
} else if (c == '$') {
sb.append('\\');
sb.append('$');
} else {
sb.append(c);
}
}
return sb.toString();
}
public static final String DEFAULT_EXCLUDES = "**/*~,**/#*#,**/.#*,**/%*%,**/._*,"
+ "**/CVS,**/CVS/**,**/.cvsignore,"
+ "**/SCCS,**/SCCS/**,**/vssver.scc,"
+ "**/.svn,**/.svn/**,**/.DS_Store";
public static int copyDirectoryStructure(File sourceDirectory,
File destinationDirectory, String includes, String excludes)
throws IOException {
if (!sourceDirectory.exists()) {
throw new IOException("Source directory doesn't exists ("
+ sourceDirectory.getAbsolutePath() + ").");
}
List files = FileUtils.getFiles(sourceDirectory, includes, excludes);
String sourcePath = sourceDirectory.getAbsolutePath();
int copied = 0;
for (Iterator i = files.iterator(); i.hasNext();) {
File file = (File) i.next();
String dest = file.getAbsolutePath();
dest = dest.substring(sourcePath.length() + 1);
File destination = new File(destinationDirectory, dest);
if (file.isFile()) {
destination = destination.getParentFile();
FileUtils.copyFileToDirectory(file, destination);
copied++;
} else if (file.isDirectory()) {
if (!destination.exists() && !destination.mkdirs()) {
throw new IOException(
"Could not create destination directory '"
+ destination.getAbsolutePath() + "'.");
}
copied += copyDirectoryStructure(file, destination, includes,
excludes);
} else {
throw new IOException("Unknown file type: "
+ file.getAbsolutePath());
}
}
return copied;
}
public static String getEnv(String envKey, String alternateSystemProperty,
String defaultValue) {
String envValue = null;
try {
envValue = System.getenv(envKey);
if (envValue == null && alternateSystemProperty != null) {
envValue = System.getProperty(alternateSystemProperty);
}
} catch (Error e) {
// JDK 1.4?
if (alternateSystemProperty != null) {
envValue = System.getProperty(alternateSystemProperty);
}
}
if (envValue == null) {
envValue = defaultValue;
}
return envValue;
}
public static String addLibraryPathToEnv(String path, Map environment,
String os) {
String pathName = null;
char separator = ' ';
if (os.equals(OS.WINDOWS)) {
pathName = "PATH";
separator = ';';
} else if (os.equals(OS.MACOSX)) {
pathName = "DYLD_LIBRARY_PATH";
separator = ':';
} else {
pathName = "LD_LIBRARY_PATH";
separator = ':';
}
String value = environment != null ? (String) environment.get(pathName)
: null;
if (value == null) {
value = NarUtil.getEnv(pathName, pathName, null);
}
path = path.replace(File.pathSeparatorChar, separator);
if (value != null) {
value += separator + path;
} else {
value = path;
}
if (environment != null) {
environment.put(pathName, value);
}
return pathName + "=" + value;
}
public static int runCommand(String cmd, String[] args, String[] env,
Log log) throws MojoExecutionException, MojoFailureException {
log.debug("RunCommand: " + cmd);
Commandline cmdLine = new Commandline();
cmdLine.setExecutable(cmd);
if (args != null) {
for (int i = 0; i < args.length; i++) {
log.debug(" '" + args[i] + "'");
}
cmdLine.addArguments(args);
}
if (env != null) {
log.debug("with Env:");
for (int i = 0; i < env.length; i++) {
String[] nameValue = env[i].split("=", 2);
if (nameValue.length < 2)
throw new MojoFailureException(" Misformed env: '"
+ env[i] + "'");
log.debug(" '" + env[i] + "'");
cmdLine.addEnvironment(nameValue[0], nameValue[1]);
}
}
try {
Process process = cmdLine.execute();
StreamGobbler errorGobbler = new StreamGobbler(process
.getErrorStream(), true, log);
StreamGobbler outputGobbler = new StreamGobbler(process
.getInputStream(), false, log);
errorGobbler.start();
outputGobbler.start();
process.waitFor();
return process.exitValue();
} catch (Throwable e) {
throw new MojoExecutionException("Could not launch " + cmdLine, e);
}
}
static class StreamGobbler extends Thread {
InputStream is;
boolean error;
Log log;
StreamGobbler(InputStream is, boolean error, Log log) {
this.is = is;
this.error = error;
this.log = log;
}
public void run() {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
if (error) {
log.error(line);
} else {
log.debug(line);
}
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}