diff --git a/build.gradle b/build.gradle index c207759..5481565 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,7 @@ dependencies { testCompile 'com.google.code.findbugs:jsr305:3.0.1' testCompile 'de.inetsoftware:jwebassembly-api:+' testCompile 'junit:junit:+' + testCompile 'org.apache.commons:commons-compress:1.2' } sourceSets { diff --git a/test/de/inetsoftware/jwebassembly/Wat2Wasm.java b/test/de/inetsoftware/jwebassembly/Wat2Wasm.java new file mode 100644 index 0000000..a6d8c71 --- /dev/null +++ b/test/de/inetsoftware/jwebassembly/Wat2Wasm.java @@ -0,0 +1,155 @@ +/* + * Copyright 2019 Volker Berlin (i-net software) + * + * Licensed 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 de.inetsoftware.jwebassembly; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.time.Instant; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.junit.Assert; + +/** + * Download the wat2wasm tool from github + * + * @author Volker Berlin + */ +class Wat2Wasm { + + private String command; + + /** + * Check if there is a new version of the script engine + * + * @throws IOException + * if any error occur + */ + private void download( File target ) throws IOException { + boolean is32 = "32".equals( System.getProperty( "sun.arch.data.model" ) ); + String fileName; + final String os = System.getProperty( "os.name", "" ).toLowerCase(); + if( os.contains( "windows" ) ) { + fileName = is32 ? "win32.zip" : "win64.zip"; + } else if( os.contains( "mac" ) ) { + fileName = "osx.tar.gz"; + } else if( os.contains( "linux" ) ) { + fileName = "linux.tar.gz"; + } else { + throw new IllegalStateException( "Unknown OS: " + os ); + } + + HttpURLConnection conn = (HttpURLConnection)new URL( "https://api.github.com/repos/WebAssembly/wabt/releases/latest" ).openConnection(); + InputStream input = conn.getInputStream(); + String json = WasmRule.readStream( input ); + + Pattern pattern = Pattern.compile( "https://github.com/WebAssembly/wabt/releases/download/[0-9.]*/wabt-[0-9.]*-" + fileName ); + Matcher matcher = pattern.matcher( json ); + Assert.assertTrue( matcher.find() ); + String downloadUrl = matcher.group(); + System.out.println( "\tDownload: " + downloadUrl ); + + conn = (HttpURLConnection)new URL( downloadUrl ).openConnection(); + if( target.exists() ) { + conn.setIfModifiedSince( target.lastModified() ); + } + + input = conn.getInputStream(); + if( conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED ) { + System.out.println( "\tUP-TO-DATE, use version from " + Instant.ofEpochMilli( target.lastModified() ) ); + return; + } + + long lastModfied = conn.getLastModified(); + + ArchiveInputStream archiv; + if( fileName.endsWith( ".tar.gz" ) ) { + input = new GZIPInputStream( input ); + archiv = new TarArchiveInputStream( input ); + } else { + archiv = new ZipArchiveInputStream( input ); + } + + do { + ArchiveEntry entry = archiv.getNextEntry(); + if( entry == null ) { + break; + } + if( entry.isDirectory() ) { + continue; + } + File file = new File( target, entry.getName() ); + file.getParentFile().mkdirs(); + + Files.copy( archiv, file.toPath(), StandardCopyOption.REPLACE_EXISTING ); + file.setLastModified( entry.getLastModifiedDate().getTime() ); + file.setExecutable( true ); + } while( true ); + + target.setLastModified( lastModfied ); + System.out.println( "\tUse Version from " + Instant.ofEpochMilli( lastModfied ) ); + } + + /** + * Search the tool in the directory recursively and set the command. + * + * @param dir + * the directory + */ + private void searchExecuteable( File dir ) { + File[] list = dir.listFiles(); + if( list != null ) { + for( File file : list ) { + if( file.isDirectory() ) { + searchExecuteable( file ); + } else { + if( file.getName().contains( "wat2wasm" ) ) { + command = file.getAbsolutePath(); + } + } + if( command != null ) { + return; + } + } + } + } + + /** + * Get the executable command + * + * @return the command + * @throws IOException + * if any I/O error occur + */ + public String getCommand() throws IOException { + if( command == null ) { + File target = new File( System.getProperty( "java.io.tmpdir" ) + "/wabt" ); + download( target ); + searchExecuteable( target ); + } + return command; + } +}