GccTools.java

package eu.javaexperience.gnu;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.util.ArrayList;

import eu.javaexperience.io.IOTools;
import eu.javaexperience.text.StringTools;

public class GccTools
{
	public static boolean loadArchDependSharedJavaLibraryOrCompileAndLoad(String searchPath,String SoStartName,String[] libs,String[] headerPaths, String[] switches, PrintStream out,PrintStream err)
	{
		searchPath = searchPath+"/";
		String arch = System.getProperty("os.arch");
		String file = SoStartName+"."+arch+".so";
		String labs = new File(file).getAbsolutePath();
		boolean loaded = false;

		try
		{
			System.load(labs);
			loaded = true;
		}catch(Throwable e){}

		try
		{
			InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(searchPath+file);
			
			if(is !=null)
			{
				IOTools.writeInputStreamToFile(is, file);
				System.load(labs);
				loaded = true;
			}
		}
		catch(Exception e)
		{}
		
		String[] dirs = System.getProperty("java.class.path").split(":");
		
		if(!loaded)
			for(String dir:dirs)
			try
			{
				File f = new File(dir);

				if(f.isDirectory())
				{
					System.load(dir+searchPath+file);
					loaded = true;
					break;
				}
				else
				{
					InputStream is = new URL("jar:file:"+dir+"!"+searchPath+file).openStream();
					if(is != null)
					try
					{
						IOTools.writeInputStreamToFile(is, file);
						System.load(labs);
						loaded = true;
						break;
					}catch(Exception e){}
				}
			}
			catch(Throwable e)
			{}

			if(loaded)
				return true;
			
			String sourceName = SoStartName+".cpp";
			
			
			boolean sourceFile = false;
			// Ha nincs meg az JUnix.arch.so akkor szedjük le a forráskódot és fordítsuk le (kell a build-essential)! ha kész próbáljuk betölteni!
			if(!loaded)
			try
			{
				InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(searchPath+sourceName);

				if(is != null)
				{
					IOTools.writeInputStreamToFile(is, sourceName);
					is.close();
					sourceFile = true;
				}
			}
			catch (Exception e)
			{}
			
			if(!sourceFile)
				for(String d:dirs)
				try
				{
					InputStream is = new FileInputStream(d+"/"+searchPath+sourceName);
					IOTools.writeInputStreamToFile(is, sourceName);
					is.close();
					sourceFile = true;
					break;
				}
				catch(Exception e)
				{}
			
			if(!sourceFile)//lehet hogy abszolut az útvonal
				try
				{
					InputStream is = new FileInputStream(searchPath+sourceName);
					IOTools.writeInputStreamToFile(is, sourceName);
					is.close();
					sourceFile = true;
				}
				catch(Exception e)
				{}
				
			try
			{
				if(!loaded && sourceFile)
				{
					//  g++ -fPIC -shared -o JUnix.amd64.so JUnix.cpp -lutil

					ArrayList<String> params = new ArrayList<>();
					params.add("g++");
					params.add("-fPIC");
					params.add("-I"+whereIsJNIandJNI_HMheaders());
					
					if(switches != null)
						for(String p:switches)
							params.add(p);
					
					if(headerPaths != null)
						for(String p:headerPaths)
							params.add("-I"+p);

					params.add("-shared");
					params.add("-o");
					params.add(file);
					params.add(sourceName);
					if(libs != null)
						for(String lib:libs)
							params.add("-l"+lib);
							
					if(out != null)
					{
						StringBuilder sb = new StringBuilder();
						for(String s:params)
						{
							sb.append(s);
							sb.append(" ");
						}
						
						out.println(sb.toString());
					}
					
					Process process = new ProcessBuilder(params.toArray(emptyStringArray)).start();
					
					int ret = process.waitFor(); 
					
					if(out != null)
						out.write(IOTools.loadAllFromInputStream(process.getInputStream()));
					
					if(err != null)
						err.write(IOTools.loadAllFromInputStream(process.getErrorStream()));
					
					
					if(ret == 0)
					{	
						System.load(labs);
						loaded = true;
					}
				}
			}catch(Exception e)
			{e.printStackTrace();}
			
			return loaded;
	}
	
	protected static final String[] emptyStringArray = new String[0];
	
	public static String whereIsJNIandJNI_HMheaders()
	{
		String home = System.getProperty("java.home");
		home = StringTools.getSubstringBeforeLastString(home, "/jre");
		
		File f = new File(home);
		if(!f.isDirectory())
		{
			throw new RuntimeException("Java home`"+home+"` doesn't exists");
		}
		
		String jni_h = home+"/include/jni.h";
		if(!new File(jni_h).exists())
		{
			throw new RuntimeException("Required file: `"+jni_h+"` doesn't exists");
		}
		
		String jni_md_h = home+"/include/jni_md.h"; 
		if(!new File(jni_md_h).exists())
		{
			throw new RuntimeException("Required file: `"+jni_md_h+"` doesn't exists");
		}
				
		return home+"/include/";
	}
}