io.qt.qtjambi.deployer.QMLGenerator Maven / Gradle / Ivy
/****************************************************************************
**
** 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