All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.qt.qtjambi.deployer.QMLGenerator Maven / Gradle / Ivy

There is a newer version: 6.8.1
Show newest version
/****************************************************************************
**
** Copyright (C) 2009-2022 Dr. Peter Droste, Omix Visualization GmbH & Co. KG. All rights reserved.
**
** This file is part of Qt Jambi.
**
** ** $BEGIN_LICENSE$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
** 
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
** $END_LICENSE$

**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
package io.qt.qtjambi.deployer;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.AbstractMap.SimpleEntry;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import io.qt.core.QCommandLineOption;
import io.qt.core.QCommandLineParser;
import io.qt.core.QDir;
import io.qt.core.QList;
import io.qt.core.QStringList;

class QMLGenerator {
	static void generate(QCommandLineParser parser, String[] args, QCommandLineOption dirOption, QCommandLineOption classPathOption, QCommandLineOption configurationOption) throws InterruptedException, IOException {
	    QCommandLineOption qmlTargetOption = new QCommandLineOption(QList.of("library"), "Java library for qml.", "jar");
	    QCommandLineOption qmlLibraryOption = new QCommandLineOption(QList.of("jarimport"), "Path to jarimport library.\nExamples:\n--jarimport=path"+File.separator+"jarimport.dll\n--jarimport=macos"+File.pathSeparator+"path"+File.separator+"jarimport.dylib", "file");
	    QCommandLineOption qmlLibraryLocationOption = new QCommandLineOption(QList.of("jarimport-location"), "Directory containing jarimport library", "path");
	    QCommandLineOption qmlNativeLibraryPathOption = new QCommandLineOption(QList.of("native-library-path"), "Native library path", "path");
	    
	    parser.addOptions(QList.of(
	    		configurationOption,
	    		qmlTargetOption,
	    		qmlLibraryOption,
	    		qmlLibraryLocationOption,
	    		qmlNativeLibraryPathOption,
	    		dirOption,
	    		classPathOption
			));
		if(args.length==1)
			parser.showHelp();
    	parser.process(new QStringList(args));
		QStringList unusedArguments = new QStringList(parser.positionalArguments());
		
		if(unusedArguments.size()==1)
			throw new Error("QML import library generation, illegal argument: "+unusedArguments.join(", "));
		if(unusedArguments.size()>1)
			throw new Error("QML import library generation, illegal argument: "+unusedArguments.join(", "));
		
		File library = null;
		if(parser.isSet(qmlTargetOption))
			library = new File(parser.value(qmlTargetOption));
		
		List classPaths = new ArrayList<>();
		if(parser.isSet(classPathOption))
			classPaths.addAll(Arrays.asList(parser.value(classPathOption).split(File.pathSeparator)));
		
		List natives = new ArrayList<>();
		if(parser.isSet(qmlNativeLibraryPathOption))
			classPaths.addAll(Arrays.asList(parser.value(qmlNativeLibraryPathOption).split(File.pathSeparator)));
		
		File dir = null;
		if(parser.isSet(dirOption))
			dir = new File(parser.value(dirOption));
		
        Boolean isDebug = null;
        if(parser.isSet(configurationOption))
        	isDebug = "debug".equals(parser.value(configurationOption));
        
        List> libraries = new ArrayList<>();
        if(parser.isSet(qmlLibraryOption)) {
        	String[] libinfo = parser.value(qmlLibraryOption).split(File.pathSeparator);
			if(libinfo.length==2){
				File libFile = new File(libinfo[1]);
				if(!libFile.isFile()) {
					throw new Error("Specified jarimport library does not exist: "+libinfo[1]);
				}
				libraries.add(new SimpleEntry<>(libinfo[0], libFile.toURI().toURL()));
			}else {
				String os = null;
				if(libinfo[0].endsWith(".dll")) {
					os = "windows";
				}else if(libinfo[0].endsWith(".dylib")) {
					os = "macos";
				}else if(libinfo[0].endsWith(".so")) {
					os = "linux";
				}
				if(os!=null) {
					File libFile = new File(libinfo[0]);
					if(!libFile.isFile()) {
						throw new Error("Specified jarimport library does not exist: "+libinfo[0]);
					}
					libraries.add(new SimpleEntry<>(os, libFile.toURI().toURL()));
				}else {
					throw new Error("Unable to determine platform for library "+libinfo[0]+". Please use --jarimport="+File.pathSeparatorChar+"");
				}
			}
        }else if(parser.isSet(qmlLibraryLocationOption)) {
        	QDir location = new QDir(parser.value(qmlLibraryLocationOption));
            if(isDebug==null){
                throw new Error("Please specify --configuration=debug or --configuration=release prior to --jarimport-location");
            }
			for(String entry : location.entryList(QDir.Filter.Files)) {
                String os = null;
                if(isDebug){
                    if(entry.equals("jarimportd.dll")) {
                        os = "windows";
                    }else if(entry.equals("libjarimport_debug.dylib") || entry.equals("libjarimport.dylib")) {
                        os = "macos";
                    }else if(entry.equals("libjarimport_debug.so") || entry.equals("libjarimport.so")) {
                        os = "linux";
                    }
                }else{
                    if(entry.equals("jarimport.dll")) {
                        os = "windows";
                    }else if(entry.equals("libjarimport.dylib")) {
                        os = "macos";
                    }else if(entry.equals("libjarimport.so")) {
                        os = "linux";
                    }
                }
                if(os!=null && entry.contains("jarimport")) {
                	File libFile = new File(location.absoluteFilePath(entry));
                    libraries.add(new SimpleEntry<>(os, libFile.toURI().toURL()));
                }
			}
        }
        
		if(library==null) {
			throw new Error("Missing qml library. Please use --library=...");
		}
		if(!library.isFile() || !library.getName().endsWith(".jar")) {
			throw new Error("Qml library is not a jar file.");
		}
		if(dir==null) {
			throw new Error("Missing target directory. Please use --dir=...");
		}
		if(dir.isFile()) {
			throw new Error("File not allowed as target directory. Please specify a directory --dir=...");
		}
		if(libraries.isEmpty()) {
			Enumeration specsFound = Main.findSpecs();
            Set specsUrls = new HashSet<>();
            while (specsFound.hasMoreElements()) {
                URL url = specsFound.nextElement();
                if(specsUrls.contains(url))
                	continue;
                specsUrls.add(url);
                String protocol = url.getProtocol();
                if (protocol.equals("jar")) {
                	String eform = url.toExternalForm();
                	int start = 4;
                	int end = eform.indexOf("!/", start);
                	if (end != -1) {
                		try {
	                        Document doc;
	                        try(InputStream inStream = url.openStream()){
	                        	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	                        	factory.setValidating(false);
	                			DocumentBuilder builder = factory.newDocumentBuilder();
	                			doc = builder.parse(inStream);
	                        }
	                        String system = doc.getDocumentElement().getAttribute("system");
	                        String configuration = doc.getDocumentElement().getAttribute("configuration");
	                        if(isDebug==null || isDebug.booleanValue()=="debug".equals(configuration)) {
		                        for(int i=0; i(system, libraryURL));
		                        		}
		                        	}
		                        }
	                        }
                		}catch (Exception e) {
            				Logger.getLogger("io.qt").log(Level.WARNING, "", e);
            			}
                	}
                }
            }
		}
		if(libraries.isEmpty()) {
			throw new Error("Missing paths to jarimport library. Please use --jarimport=, --jarimport="+File.pathSeparatorChar+" or --jarimport-location= in combination with --configuration=debug/release");
		}
		String packageName = null;
		try (JarFile jarFile = new JarFile(library)) {
			for(JarEntry entry : (Iterable)()->jarFile.entries().asIterator()) {
				if(!entry.isDirectory() && entry.getName().endsWith(".class")) {
					int idx = entry.getName().lastIndexOf('/');
					if(idx>=0) {
						packageName = entry.getName();
						packageName = packageName.substring(packageName.startsWith("/") ? 1 : 0, idx);
						break;
					}
				}
			}
		}catch(IOException e) {
			throw new Error("Unable to read jar file.", e);
		}
		if(packageName==null) {
			throw new Error(String.format("Unable to detect package in jar file %1$s.", library.getName()));
		}
		dir = new File(dir, packageName.replace('/', File.separatorChar));
		dir.mkdirs();
		if(dir.isDirectory()) {
			boolean found = false;
			for(Map.Entry entry : libraries) {
				String os = entry.getKey();
				if(os!=null) {
					File newFile;
                    switch(os.toLowerCase()) {
					case "win32":
					case "win64":
					case "windows":
					case "windows-aarch64":
					case "windows-arm64":
					case "windows-x86":
					case "windows-x64":
                        if(isDebug==null){
							newFile = new File(dir, "jarimport" + (entry.getValue().toExternalForm().endsWith("d.dll") ? "d.dll" : ".dll"));
						}else{
							newFile = new File(dir, "jarimport" + (isDebug ? "d.dll" : ".dll"));
                        }
						System.gc();
						break;
					case "macos":
					case "osx":
						newFile = new File(dir, "libjarimport.dylib");
                        break;
					case "linux":
					case "linux32":
					case "linux64":
					case "linux-arm64":
					case "linux-aarch64":
					case "linux-x86":
					case "linux-x64":
						newFile = new File(dir, "libjarimport.so");
						break;
						default: continue;
					}
                    try(InputStream in = entry.getValue().openStream()){
                    	Files.copy(in, newFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                    	found = true;
					}catch(IOException e) {
                        throw new Error("Unable to write file "+newFile, e);
					}
				}
				if(found) {
					try{
                    	Files.copy(library.toPath(), new File(dir, library.getName()).toPath(), StandardCopyOption.REPLACE_EXISTING);
					}catch(IOException e) {
                        throw new Error("Unable to write file "+new File(dir, library.getName()), e);
					}
                    if(!classPaths.isEmpty()) {
                    	for(String cp : classPaths) {
                    		if(cp.endsWith(".jar")) {
                        		File jar = new File(cp);
                        		if(jar.exists()) {
                        			try{
        	                        	Files.copy(jar.toPath(), new File(dir, jar.getName()).toPath(), StandardCopyOption.REPLACE_EXISTING);
        							}catch(IOException e) {
        	                            throw new Error("Unable to write file "+new File(dir, jar.getName()), e);
        							}
                        		}
                    		}
                    	}
                    }
                    try(PrintWriter writer = new PrintWriter(new File(dir, "qmldir"))){
                    	writer.print("module ");
                    	writer.println(packageName.replace('/', '.'));
                    	writer.println("plugin jarimport");
                    	if(!natives.isEmpty()) {
                    		writer.print("librarypath ");
                        	writer.println(new QStringList(natives).join(","));
                    	}
                    }catch(IOException e) {
                        throw new Error("Unable to write file "+new File(dir, "qmldir"), e);
					}
				}
			}
		}else {
			throw new Error(String.format("Unable to create directory %1$s.", dir.getAbsolutePath()));
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy