diff --git a/core/pom.xml b/core/pom.xml index 3c3ec9db..9a010a46 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -45,6 +45,11 @@ junit-jupiter test + + com.flowpowered + flow-nbt + 1.0.1-SNAPSHOT + diff --git a/core/src/main/java/it/cavallium/warppi/Platform.java b/core/src/main/java/it/cavallium/warppi/Platform.java index c63da56e..709f8c62 100644 --- a/core/src/main/java/it/cavallium/warppi/Platform.java +++ b/core/src/main/java/it/cavallium/warppi/Platform.java @@ -3,11 +3,9 @@ package it.cavallium.warppi; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.PrintWriter; import java.net.URISyntaxException; import java.net.URL; import java.util.List; -import java.util.Map; import it.cavallium.warppi.boot.StartupArguments; import it.cavallium.warppi.device.DeviceStateDevice; @@ -23,7 +21,7 @@ public interface Platform { Gpio getGpio(); - StorageUtils getStorageUtils(); + PlatformStorage getPlatformStorage(); ImageUtils getImageUtils(); @@ -76,7 +74,7 @@ public interface Platform { * * @return a List of paths of files which contain DSL rules. * Each String in the returned List can be passed as an argument to - * {@link StorageUtils#getResourceStream(String)} to access the corresponding file's contents. + * {@link PlatformStorage#getResourceStream(String)} to access the corresponding file's contents. * @throws IOException if an IO error occurs while getting the list of rule file paths. */ List getRuleFilePaths() throws IOException; @@ -135,7 +133,7 @@ public interface Platform { } } - public interface StorageUtils { + public interface PlatformStorage { int OpenOptionWrite = 0; int OpenOptionCreate = 1; @@ -170,7 +168,7 @@ public interface Platform { List readAllLines(InputStream input) throws IOException; - String getBasePath(); + File getRootPath(); } public interface Semaphore { diff --git a/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/PngSkin.java b/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/PngSkin.java index eeb6d31c..9786c0c6 100644 --- a/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/PngSkin.java +++ b/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/PngSkin.java @@ -25,7 +25,7 @@ public abstract class PngSkin implements Skin { if (!file.startsWith("/")) { file = "/" + file; } - final ImageReader r = WarpPI.getPlatform().getImageUtils().load(WarpPI.getPlatform().getStorageUtils().getResourceStream(file)); + final ImageReader r = WarpPI.getPlatform().getImageUtils().load(WarpPI.getPlatform().getPlatformStorage().getResourceStream(file)); if (r == null) { skinData = new int[0]; skinSize = new int[] { 0, 0 }; diff --git a/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/RFTFont.java b/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/RFTFont.java index 52cfeb09..af940715 100644 --- a/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/RFTFont.java +++ b/core/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/common/RFTFont.java @@ -1,12 +1,8 @@ package it.cavallium.warppi.gui.graphicengine.impl.common; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.URISyntaxException; import java.util.LinkedList; -import java.util.logging.Level; -import java.util.logging.Logger; import it.cavallium.warppi.WarpPI; import it.cavallium.warppi.Platform.ConsoleUtils; @@ -101,7 +97,7 @@ public abstract class RFTFont implements BinaryFont { if (!string.startsWith("/")) { string = "/" + string; } - InputStream res = WarpPI.getPlatform().getStorageUtils().getResourceStream(string); + InputStream res = WarpPI.getPlatform().getPlatformStorage().getResourceStream(string); final int[] file = Utils.realBytes(Utils.convertStreamToByteArray(res, res.available())); final int filelength = file.length; if (filelength >= 16) { diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/RulesManager.java b/core/src/main/java/it/cavallium/warppi/math/rules/RulesManager.java index ffb0f88e..95b670dc 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/RulesManager.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/RulesManager.java @@ -80,8 +80,8 @@ public class RulesManager { ); final String source; - try (final InputStream resource = platform.getStorageUtils().getResourceStream(path)) { - source = platform.getStorageUtils().read(resource); + try (final InputStream resource = platform.getPlatformStorage().getResourceStream(path)) { + source = platform.getPlatformStorage().read(resource); } try { diff --git a/core/src/main/java/it/cavallium/warppi/util/Utils.java b/core/src/main/java/it/cavallium/warppi/util/Utils.java index 58cc123b..b8ca44e9 100644 --- a/core/src/main/java/it/cavallium/warppi/util/Utils.java +++ b/core/src/main/java/it/cavallium/warppi/util/Utils.java @@ -578,7 +578,7 @@ public class Utils { public static InputStream getResourceStreamSafe(final String string) throws IOException, URISyntaxException { try { - return WarpPI.getPlatform().getStorageUtils().getResourceStream(string); + return WarpPI.getPlatform().getPlatformStorage().getResourceStream(string); } catch (final Exception ex) { return null; } diff --git a/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatform.java b/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatform.java index 30379d10..fcc8804c 100644 --- a/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatform.java +++ b/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatform.java @@ -11,7 +11,6 @@ import java.util.function.Consumer; import it.cavallium.warppi.event.TouchEvent; import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLDisplayOutputDevice; -import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLEngine; import it.cavallium.warppi.gui.graphicengine.impl.swing.SwingDeviceState; import it.cavallium.warppi.gui.graphicengine.impl.swing.SwingTouchInputDevice; import org.apache.commons.io.FileUtils; @@ -35,7 +34,7 @@ public class DesktopPlatform implements Platform { private final DesktopConsoleUtils cu; private final DesktopGpio gi; - private final DesktopStorageUtils su; + private final DesktopPlatformStorage su; private final ImageUtils pu; private final String on; private final DesktopSettings settings; @@ -49,7 +48,7 @@ public class DesktopPlatform implements Platform { public DesktopPlatform() { cu = new DesktopConsoleUtils(); gi = new DesktopGpio(); - su = new DesktopStorageUtils(); + su = new DesktopPlatformStorage(); pu = new DesktopImageUtils(); on = System.getProperty("os.name").toLowerCase(); settings = new DesktopSettings(); @@ -66,7 +65,7 @@ public class DesktopPlatform implements Platform { } @Override - public StorageUtils getStorageUtils() { + public PlatformStorage getPlatformStorage() { return su; } @@ -159,10 +158,10 @@ public class DesktopPlatform implements Platform { @Override public List getRuleFilePaths() throws IOException { - final File dslRulesPath = getStorageUtils().get("rules/"); + final File dslRulesPath = getPlatformStorage().get("rules/"); List paths = new ArrayList<>(); if (dslRulesPath.exists()) { - for (final File file : getStorageUtils().walk(dslRulesPath)) { + for (final File file : getPlatformStorage().walk(dslRulesPath)) { final String path = file.toString(); if (path.endsWith(".rules")) { paths.add(path); diff --git a/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopStorageUtils.java b/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatformStorage.java similarity index 92% rename from desktop/src/main/java/it/cavallium/warppi/desktop/DesktopStorageUtils.java rename to desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatformStorage.java index 5ab0c3a2..0c78a069 100644 --- a/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopStorageUtils.java +++ b/desktop/src/main/java/it/cavallium/warppi/desktop/DesktopPlatformStorage.java @@ -1,219 +1,219 @@ -package it.cavallium.warppi.desktop; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.commons.io.IOUtils; - -import it.cavallium.warppi.Platform.StorageUtils; -import it.cavallium.warppi.util.ClassUtils; - -public class DesktopStorageUtils implements StorageUtils { - @Override - public boolean exists(final File f) { - return f.exists(); - } - - @Override - public File get(final String path) { - return Paths.get(path).toFile(); - } - - @Override - public File get(final String... path) { - if (path.length <= 1) - return Paths.get(path[0]).toFile(); - else - return Paths.get(path[0], Arrays.copyOfRange(path, 1, path.length)).toFile(); - } - - private final Map resourcesCache = new HashMap<>(); - - @Override - @Deprecated() - public File getResource(final String string) throws IOException, URISyntaxException { - final URL res = ClassUtils.classLoader.getResource(string); - final boolean isResource = res != null; - if (isResource) - try { - final URI uri = res.toURI(); - if (res.getProtocol().equalsIgnoreCase("jar")) { - if (resourcesCache.containsKey(string)) { - File f; - if ((f = resourcesCache.get(string)).exists()) - return f; - else - resourcesCache.remove(string); - } - try { - FileSystems.newFileSystem(uri, Collections.emptyMap()); - } catch (final FileSystemAlreadyExistsException e) { - FileSystems.getFileSystem(uri); - } - final Path myFolderPath = Paths.get(uri); - - final InputStream is = Files.newInputStream(myFolderPath); - final File tempFile = File.createTempFile("picalcresource-", ""); - tempFile.deleteOnExit(); - try (FileOutputStream out = new FileOutputStream(tempFile)) { - IOUtils.copy(is, out, (int) tempFile.length()); - } - resourcesCache.put(string, tempFile); - - return tempFile; - } else - return Paths.get(uri).toFile(); - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } - else - return Paths.get(string.substring(1)).toFile(); - } - - - @Override - public boolean doesResourceExist(String string) throws IOException { - final URL res = ClassUtils.classLoader.getResource(string); - final boolean isResource = res != null; - if (isResource) return true; - else { - if (string.length() > 0) { - final char ch = string.charAt(0); - if (ch == '/' || ch == File.separatorChar) - string = string.substring(1); - } - return Files.exists(Paths.get(string)); - } - } - - @Override - public InputStream getResourceStream(String string) throws IOException { - final URL res = ClassUtils.classLoader.getResource(string); - final boolean isResource = res != null; - if (isResource) - try { - final URI uri = res.toURI(); - if (res.getProtocol().equalsIgnoreCase("jar")) { - try { - FileSystems.newFileSystem(uri, Collections.emptyMap()); - } catch (final FileSystemAlreadyExistsException e) { - FileSystems.getFileSystem(uri); - } - final Path myFolderPath = Paths.get(uri); - return Files.newInputStream(myFolderPath); - } else - return Files.newInputStream(Paths.get(uri)); - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } catch (URISyntaxException e) { - throw (IOException) new IOException().initCause(e); - } - else { - if (string.length() > 0) { - final char ch = string.charAt(0); - if (ch == '/' || ch == File.separatorChar) - string = string.substring(1); - } - return Files.newInputStream(Paths.get(string)); - } - } - - @Override - public List readAllLines(final File file) throws IOException { - return Files.readAllLines(file.toPath()); - } - - @Override - public String read(final InputStream input) throws IOException { - try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { - return buffer.lines().collect(Collectors.joining("\n")); - } - } - - @Override - public List walk(final File dir) throws IOException { - final List out = new ArrayList<>(); - try (Stream paths = Files.walk(dir.toPath())) { - paths.filter(Files::isRegularFile).forEach((final Path p) -> { - out.add(p.toFile()); - }); - } - return out; - } - - @Override - public File relativize(final File rulesPath, final File f) { - return rulesPath.toPath().relativize(f.toPath()).toFile(); - } - - @Override - public File resolve(final File file, final String string) { - return file.toPath().resolve(string).toFile(); - } - - @Override - public File getParent(final File f) { - return f.toPath().getParent().toFile(); - } - - @Override - public void createDirectories(final File dir) throws IOException { - Files.createDirectories(dir.toPath()); - } - - @Override - public void write(final File f, final byte[] bytes, final int... options) throws IOException { - final StandardOpenOption[] noptions = new StandardOpenOption[options.length]; - int i = 0; - for (final int opt : options) { - switch (opt) { - case StorageUtils.OpenOptionCreate: { - noptions[i] = StandardOpenOption.CREATE; - break; - } - case StorageUtils.OpenOptionWrite: { - noptions[i] = StandardOpenOption.WRITE; - break; - } - default: { - break; - } - } - i++; - } - Files.write(f.toPath(), bytes, noptions); - } - - @Override - public List readAllLines(final InputStream input) throws IOException { - try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { - return buffer.lines().collect(Collectors.toList()); - } - } - - @Override - public String getBasePath() { - return ""; - } -} +package it.cavallium.warppi.desktop; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.FileSystemAlreadyExistsException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.io.IOUtils; + +import it.cavallium.warppi.Platform.PlatformStorage; +import it.cavallium.warppi.util.ClassUtils; + +public class DesktopPlatformStorage implements PlatformStorage { + @Override + public boolean exists(final File f) { + return f.exists(); + } + + @Override + public File get(final String path) { + return Paths.get(path).toFile(); + } + + @Override + public File get(final String... path) { + if (path.length <= 1) + return Paths.get(path[0]).toFile(); + else + return Paths.get(path[0], Arrays.copyOfRange(path, 1, path.length)).toFile(); + } + + private final Map resourcesCache = new HashMap<>(); + + @Override + @Deprecated() + public File getResource(final String string) throws IOException, URISyntaxException { + final URL res = ClassUtils.classLoader.getResource(string); + final boolean isResource = res != null; + if (isResource) + try { + final URI uri = res.toURI(); + if (res.getProtocol().equalsIgnoreCase("jar")) { + if (resourcesCache.containsKey(string)) { + File f; + if ((f = resourcesCache.get(string)).exists()) + return f; + else + resourcesCache.remove(string); + } + try { + FileSystems.newFileSystem(uri, Collections.emptyMap()); + } catch (final FileSystemAlreadyExistsException e) { + FileSystems.getFileSystem(uri); + } + final Path myFolderPath = Paths.get(uri); + + final InputStream is = Files.newInputStream(myFolderPath); + final File tempFile = File.createTempFile("picalcresource-", ""); + tempFile.deleteOnExit(); + try (FileOutputStream out = new FileOutputStream(tempFile)) { + IOUtils.copy(is, out, (int) tempFile.length()); + } + resourcesCache.put(string, tempFile); + + return tempFile; + } else + return Paths.get(uri).toFile(); + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } + else + return Paths.get(string.substring(1)).toFile(); + } + + + @Override + public boolean doesResourceExist(String string) throws IOException { + final URL res = ClassUtils.classLoader.getResource(string); + final boolean isResource = res != null; + if (isResource) return true; + else { + if (string.length() > 0) { + final char ch = string.charAt(0); + if (ch == '/' || ch == File.separatorChar) + string = string.substring(1); + } + return Files.exists(Paths.get(string)); + } + } + + @Override + public InputStream getResourceStream(String string) throws IOException { + final URL res = ClassUtils.classLoader.getResource(string); + final boolean isResource = res != null; + if (isResource) + try { + final URI uri = res.toURI(); + if (res.getProtocol().equalsIgnoreCase("jar")) { + try { + FileSystems.newFileSystem(uri, Collections.emptyMap()); + } catch (final FileSystemAlreadyExistsException e) { + FileSystems.getFileSystem(uri); + } + final Path myFolderPath = Paths.get(uri); + return Files.newInputStream(myFolderPath); + } else + return Files.newInputStream(Paths.get(uri)); + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } catch (URISyntaxException e) { + throw (IOException) new IOException().initCause(e); + } + else { + if (string.length() > 0) { + final char ch = string.charAt(0); + if (ch == '/' || ch == File.separatorChar) + string = string.substring(1); + } + return Files.newInputStream(Paths.get(string)); + } + } + + @Override + public List readAllLines(final File file) throws IOException { + return Files.readAllLines(file.toPath()); + } + + @Override + public String read(final InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + return buffer.lines().collect(Collectors.joining("\n")); + } + } + + @Override + public List walk(final File dir) throws IOException { + final List out = new ArrayList<>(); + try (Stream paths = Files.walk(dir.toPath())) { + paths.filter(Files::isRegularFile).forEach((final Path p) -> { + out.add(p.toFile()); + }); + } + return out; + } + + @Override + public File relativize(final File rulesPath, final File f) { + return rulesPath.toPath().relativize(f.toPath()).toFile(); + } + + @Override + public File resolve(final File file, final String string) { + return file.toPath().resolve(string).toFile(); + } + + @Override + public File getParent(final File f) { + return f.toPath().getParent().toFile(); + } + + @Override + public void createDirectories(final File dir) throws IOException { + Files.createDirectories(dir.toPath()); + } + + @Override + public void write(final File f, final byte[] bytes, final int... options) throws IOException { + final StandardOpenOption[] noptions = new StandardOpenOption[options.length]; + int i = 0; + for (final int opt : options) { + switch (opt) { + case PlatformStorage.OpenOptionCreate: { + noptions[i] = StandardOpenOption.CREATE; + break; + } + case PlatformStorage.OpenOptionWrite: { + noptions[i] = StandardOpenOption.WRITE; + break; + } + default: { + break; + } + } + i++; + } + Files.write(f.toPath(), bytes, noptions); + } + + @Override + public List readAllLines(final InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + return buffer.lines().collect(Collectors.toList()); + } + } + + @Override + public File getRootPath() { + return new File(""); + } +} diff --git a/desktop/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/swing/SwingWindow.java b/desktop/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/swing/SwingWindow.java index ef1a3fda..3100043d 100644 --- a/desktop/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/swing/SwingWindow.java +++ b/desktop/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/swing/SwingWindow.java @@ -205,7 +205,7 @@ public class SwingWindow extends JFrame { } private void createBtn(final int row, final int col) throws IOException, URISyntaxException { - final BufferedImage img = ImageIO.read(WarpPI.getPlatform().getStorageUtils().getResourceStream("/desktop-buttons.png")); + final BufferedImage img = ImageIO.read(WarpPI.getPlatform().getPlatformStorage().getResourceStream("/desktop-buttons.png")); final SwingAdvancedButton b = new SwingAdvancedButton(img, new Dimension((int) (BTN_SIZE * 1.5), BTN_SIZE)); b.drawDefaultComponent = false; b.setText(Keyboard.getKeyName(row, col)); diff --git a/engine-jogl/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/jogl/JOGLSkin.java b/engine-jogl/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/jogl/JOGLSkin.java index 7d231e25..f2f4acc1 100644 --- a/engine-jogl/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/jogl/JOGLSkin.java +++ b/engine-jogl/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/jogl/JOGLSkin.java @@ -1,7 +1,6 @@ package it.cavallium.warppi.gui.graphicengine.impl.jogl; import java.io.IOException; -import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; @@ -30,7 +29,7 @@ public class JOGLSkin implements Skin { @Override public void load(final String file) throws IOException { final boolean isResource = !Files.exists(Paths.get(file)); - if (isResource && WarpPI.getPlatform().getStorageUtils().getResourceStream(file) == null) + if (isResource && WarpPI.getPlatform().getPlatformStorage().getResourceStream(file) == null) throw new IOException("File '" + file + "' not found!"); texturePath = file; this.isResource = isResource; diff --git a/hardware/src/main/java/cz/adamh/utils/NativeUtils.java b/hardware/src/main/java/cz/adamh/utils/NativeUtils.java deleted file mode 100644 index a66a0148..00000000 --- a/hardware/src/main/java/cz/adamh/utils/NativeUtils.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Class NativeUtils is published under the The MIT License: - * - * Copyright (c) 2012 Adam Heinrich - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package cz.adamh.utils; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.ProviderNotFoundException; -import java.nio.file.StandardCopyOption; - -/** - * A simple library class which helps with loading dynamic libraries stored in - * the - * JAR archive. These libraries usualy contain implementation of some methods in - * native code (using JNI - Java Native Interface). - * - * @see http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar - * @see https://github.com/adamheinrich/native-utils - * - */ -public class NativeUtils { - - /** - * The minimum length a prefix for a file has to have according to - * {@link File#createTempFile(String, String)}}. - */ - private static final int MIN_PREFIX_LENGTH = 3; - - /** - * Temporary directory which will contain the DLLs. - */ - private static File temporaryDir; - - /** - * Private constructor - this class will never be instanced - */ - private NativeUtils() {} - - /** - * Loads library from current JAR archive - * - * The file from JAR is copied into system temporary directory and then - * loaded. The temporary file is deleted after - * exiting. - * Method uses String as filename because the pathname is "abstract", not - * system-dependent. - * - * @param path - * The path of file inside JAR as absolute path (beginning with - * '/'), e.g. /package/File.ext - * @throws IOException - * If temporary file creation or read/write operation fails - * @throws IllegalArgumentException - * If source file (param path) does not exist - * @throws IllegalArgumentException - * If the path is not absolute or if the filename is shorter - * than three characters - * (restriction of - * {@link File#createTempFile(java.lang.String, java.lang.String)}). - * @throws FileNotFoundException - * If the file could not be found inside the JAR. - */ - public static void loadLibraryFromJar(final String path) throws IOException { - - if (!path.startsWith("/")) - throw new IllegalArgumentException("The path has to be absolute (start with '/')."); - - // Obtain filename from path - final String[] parts = path.split("/"); - final String filename = parts.length > 1 ? parts[parts.length - 1] : null; - - // Check if the filename is okay - if (filename == null || filename.length() < NativeUtils.MIN_PREFIX_LENGTH) - throw new IllegalArgumentException("The filename has to be at least 3 characters long."); - - // Prepare temporary file - if (NativeUtils.temporaryDir == null) { - NativeUtils.temporaryDir = NativeUtils.createTempDirectory("nativeutils"); - NativeUtils.temporaryDir.deleteOnExit(); - } - - final File temp = new File(NativeUtils.temporaryDir, filename); - - try (InputStream is = NativeUtils.class.getResourceAsStream(path)) { - Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (final IOException e) { - temp.delete(); - throw e; - } catch (final NullPointerException e) { - temp.delete(); - throw new FileNotFoundException("File " + path + " was not found inside JAR."); - } - - try { - System.load(temp.getAbsolutePath()); - } finally { - if (NativeUtils.isPosixCompliant()) - // Assume POSIX compliant file system, can be deleted after loading - temp.delete(); - else - // Assume non-POSIX, and don't delete until last file descriptor closed - temp.deleteOnExit(); - } - } - - private static boolean isPosixCompliant() { - try { - if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) - return true; - return false; - } catch (FileSystemNotFoundException | ProviderNotFoundException | SecurityException e) { - return false; - } - } - - private static File createTempDirectory(final String prefix) throws IOException { - final String tempDir = System.getProperty("java.io.tmpdir"); - final File generatedDir = new File(tempDir, prefix + System.nanoTime()); - - if (!generatedDir.mkdir()) - throw new IOException("Failed to create temp directory " + generatedDir.getName()); - - return generatedDir; - } -} \ No newline at end of file diff --git a/hardware/src/main/java/it/cavallium/warppi/MmapByteBuffer.java b/hardware/src/main/java/it/cavallium/warppi/MmapByteBuffer.java deleted file mode 100644 index c6ef8256..00000000 --- a/hardware/src/main/java/it/cavallium/warppi/MmapByteBuffer.java +++ /dev/null @@ -1,33 +0,0 @@ -package it.cavallium.warppi; - -import java.nio.ByteBuffer; - -public class MmapByteBuffer { - private final int fd; - private final int address; - private final int length; - private final ByteBuffer buffer; - - public MmapByteBuffer(final int fd, final int address, final int length, final ByteBuffer buffer) { - this.fd = fd; - this.address = address; - this.length = length; - this.buffer = buffer; - } - - public int getFd() { - return fd; - } - - public int getAddress() { - return address; - } - - public int getLength() { - return length; - } - - public ByteBuffer getBuffer() { - return buffer; - } -} \ No newline at end of file diff --git a/hardware/src/main/java/it/cavallium/warppi/TestJNI.java b/hardware/src/main/java/it/cavallium/warppi/TestJNI.java deleted file mode 100644 index 3488ae36..00000000 --- a/hardware/src/main/java/it/cavallium/warppi/TestJNI.java +++ /dev/null @@ -1,23 +0,0 @@ -package it.cavallium.warppi; - -public class TestJNI { - public TestJNI() { - - } - - static { - System.load("/boot/libpicalc.so"); - } - - private native MmapByteBuffer getDisplayBuffer(); - - private native void disposeDisplayBuffer(); - - public MmapByteBuffer retrieveBuffer() { - return getDisplayBuffer(); - } - - public void deleteBuffer() { - disposeDisplayBuffer(); - } -} \ No newline at end of file diff --git a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBEngine.java b/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBEngine.java deleted file mode 100644 index 794af3c9..00000000 --- a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBEngine.java +++ /dev/null @@ -1,191 +0,0 @@ -package it.cavallium.warppi.gui.graphicengine.impl.framebuffer; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.util.concurrent.Semaphore; - -import it.cavallium.warppi.MmapByteBuffer; -import it.cavallium.warppi.StaticVars; -import it.cavallium.warppi.TestJNI; -import it.cavallium.warppi.flow.BehaviorSubject; -import it.cavallium.warppi.flow.Observable; -import it.cavallium.warppi.gui.graphicengine.GraphicEngine; -import it.cavallium.warppi.gui.graphicengine.Renderer; -import it.cavallium.warppi.gui.graphicengine.RenderingLoop; - -public class FBEngine implements GraphicEngine { - - @SuppressWarnings("unused") - private static final int FB_DISPLAY_WIDTH = 320; - @SuppressWarnings("unused") - private static final int FB_DISPLAY_HEIGHT = 480; - @SuppressWarnings("unused") - private static final int FB_DISPLAY_BPP = 32; - private static final int WIDTH = 480; - private static final int HEIGHT = 320; - private static final int[] SIZE = new int[] { FBEngine.WIDTH, FBEngine.HEIGHT }; - private BehaviorSubject onResize; - private final TestJNI jni = new TestJNI(); - public FBRenderer r; - private MappedByteBuffer fb; - MmapByteBuffer realFb; - private RandomAccessFile fbFileRW; - public volatile boolean initialized = false; - public Semaphore exitSemaphore = new Semaphore(0); - - @Override - public int[] getSize() { - return FBEngine.SIZE; - } - - @Override - public boolean isInitialized() { - return initialized; - } - - @Override - public void setTitle(final String title) {} - - @Override - public void setResizable(final boolean r) {} - - @Override - public void setDisplayMode(final int ww, final int wh) {} - - @Override - public void create(final Runnable onInitialized) { - onResize = BehaviorSubject.create(new Integer[] { FBEngine.SIZE[0], FBEngine.SIZE[1] }); - realFb = jni.retrieveBuffer(); - final long fbLen = realFb.getLength(); - fb = (MappedByteBuffer) ByteBuffer.allocateDirect((int) fbLen); - - r = new FBRenderer(this, fb); - - initialized = true; - if (onInitialized != null) - onInitialized.run(); - } - - @Override - public Observable onResize() { - return onResize; - } - - @Override - public int getWidth() { - return FBEngine.WIDTH; - } - - @Override - public int getHeight() { - return FBEngine.HEIGHT; - } - - @Override - public void destroy() { - try { - fbFileRW.close(); - } catch (final IOException e) { - e.printStackTrace(); - } - } - - @Override - public void start(final RenderingLoop d) { - final Thread th = new Thread(() -> { - try { - double extratime = 0; - while (initialized) { - final long start = System.currentTimeMillis(); - d.refresh(); - repaint(); - final long end = System.currentTimeMillis(); - final double delta = (end - start) / 1000d; - final int deltaInt = (int) Math.floor(delta); - final int extraTimeInt = (int) Math.floor(extratime); - if (extraTimeInt + deltaInt < 50) { - Thread.sleep(50 - (extraTimeInt + deltaInt)); - extratime = 0; - } else - extratime += delta - 50d; - } - } catch (final InterruptedException e) { - e.printStackTrace(); - } - }); - th.setName("CPU rendering thread"); - th.setDaemon(true); - th.start(); - } - - private int _________________TMP = 0; - - @Override - public void repaint() { - if (_________________TMP % 100 == 0) { - System.out.println(System.currentTimeMillis()); - _________________TMP = 0; - } - _________________TMP++; - realFb.getBuffer().clear(); - realFb.getBuffer().put(fb); - for (int i = 0; i < fb.capacity() / 2; i++) - realFb.getBuffer().put(i, (byte) (_________________TMP < 50 ? 0xFF : 0xF0)); - for (int i = fb.capacity() / 2; i < fb.capacity(); i++) - realFb.getBuffer().put(i, (byte) 0x18); - } - - @Override - public Renderer getRenderer() { - return r; - } - - @Override - public FBFont loadFont(final String fontName) throws IOException { - return new FBFont(fontName); - } - - @Override - public FBFont loadFont(final String path, final String fontName) throws IOException { - return new FBFont(path, fontName); - } - - @Override - public FBSkin loadSkin(final String file) throws IOException { - return new FBSkin(file); - } - - @Override - public void waitForExit() { - try { - exitSemaphore.acquire(); - } catch (final InterruptedException e) {} - } - - @Override - public boolean isSupported() { - if (StaticVars.startupArguments.isEngineForced() && StaticVars.startupArguments.isFrameBufferEngineForced() == false) - return false; - /* - File fbFile = new File("/dev/fb1"); - try { - fbFileRW = new RandomAccessFile(fbFile, "rw"); - fbFileRW.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, fbFile.length()); - fbFileRW.close(); - return true; - } catch (IOException ex) { - System.err.println("Cannot read framebuffer fb1."); - ex.printStackTrace(); - } - */ - return false; - } - - @Override - public boolean doesRefreshPauses() { - return true; - } - -} diff --git a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBFont.java b/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBFont.java deleted file mode 100644 index 480cc4b6..00000000 --- a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBFont.java +++ /dev/null @@ -1,25 +0,0 @@ -package it.cavallium.warppi.gui.graphicengine.impl.framebuffer; - -import java.io.IOException; - -import it.cavallium.warppi.device.display.DisplayOutputDevice; -import it.cavallium.warppi.gui.graphicengine.impl.common.RFTFont; - -public class FBFont extends RFTFont { - - public FBFont(final String fontName) throws IOException { - super(fontName); - } - - public FBFont(final String path, final String fontName) throws IOException { - super(path, fontName); - } - - @Override - public void use(final DisplayOutputDevice d) { - @SuppressWarnings("unused") - final FBEngine dfb = (FBEngine) d; - // TODO: implement - } - -} diff --git a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBRenderer.java b/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBRenderer.java deleted file mode 100644 index e42e343e..00000000 --- a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBRenderer.java +++ /dev/null @@ -1,139 +0,0 @@ -package it.cavallium.warppi.gui.graphicengine.impl.framebuffer; - -import java.nio.MappedByteBuffer; - -import it.cavallium.warppi.gui.graphicengine.BinaryFont; -import it.cavallium.warppi.gui.graphicengine.Renderer; - -public class FBRenderer implements Renderer { - - public FBRenderer(final FBEngine fbEngine, final MappedByteBuffer fb) {} - - @Override - public void glColor3i(final int r, final int gg, final int b) { - // TODO Auto-generated method stub - - } - - @Override - public void glColor(final int c) { - // TODO Auto-generated method stub - - } - - @Override - public void glColor4i(final int red, final int green, final int blue, final int alpha) { - // TODO Auto-generated method stub - - } - - @Override - public void glColor3f(final float red, final float green, final float blue) { - // TODO Auto-generated method stub - - } - - @Override - public void glColor4f(final float red, final float green, final float blue, final float alpha) { - // TODO Auto-generated method stub - - } - - @Override - public void glClearColor4i(final int red, final int green, final int blue, final int alpha) { - // TODO Auto-generated method stub - - } - - @Override - public void glClearColor4f(final float red, final float green, final float blue, final float alpha) { - // TODO Auto-generated method stub - - } - - @Override - public int glGetClearColor() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void glClearColor(final int c) { - // TODO Auto-generated method stub - - } - - @Override - public void glClear(final int screenWidth, final int screenHeight) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawLine(final float x0, final float y0, final float x1, final float y1) { - // TODO Auto-generated method stub - - } - - @Override - public void glFillRect(final float x, final float y, final float width, final float height, final float uvX, - final float uvY, final float uvWidth, final float uvHeight) { - // TODO Auto-generated method stub - - } - - @Override - public void glFillColor(final float x, final float y, final float width, final float height) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawCharLeft(final int x, final int y, final char ch) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawCharCenter(final int x, final int y, final char ch) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawCharRight(final int x, final int y, final char ch) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawStringLeft(final float x, final float y, final String text) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawStringCenter(final float x, final float y, final String text) { - // TODO Auto-generated method stub - - } - - @Override - public void glDrawStringRight(final float x, final float y, final String text) { - // TODO Auto-generated method stub - - } - - @Override - public void glClearSkin() { - // TODO Auto-generated method stub - - } - - @Override - public BinaryFont getCurrentFont() { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBSkin.java b/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBSkin.java deleted file mode 100644 index 919b1c06..00000000 --- a/hardware/src/main/java/it/cavallium/warppi/gui/graphicengine/impl/framebuffer/FBSkin.java +++ /dev/null @@ -1,21 +0,0 @@ -package it.cavallium.warppi.gui.graphicengine.impl.framebuffer; - -import java.io.IOException; - -import it.cavallium.warppi.device.display.DisplayOutputDevice; -import it.cavallium.warppi.gui.graphicengine.impl.common.PngSkin; - -public class FBSkin extends PngSkin { - - public FBSkin(final String file) throws IOException { - super(file); - } - - @Override - public void use(final DisplayOutputDevice d) { - @SuppressWarnings("unused") - final FBEngine dfb = (FBEngine) d; - // TODO: implement - } - -} diff --git a/hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatform.java b/hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatform.java index c13ff359..f8f37fa9 100644 --- a/hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatform.java +++ b/hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatform.java @@ -20,7 +20,6 @@ import it.cavallium.warppi.device.input.KeyboardInputDevice; import it.cavallium.warppi.device.input.PIHardwareTouchDevice; import it.cavallium.warppi.device.input.TouchInputDevice; import it.cavallium.warppi.gui.graphicengine.GraphicEngine; -import it.cavallium.warppi.gui.graphicengine.impl.framebuffer.FBEngine; import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLDisplayOutputDevice; import it.cavallium.warppi.gui.graphicengine.impl.jogl.JOGLEngine; import it.cavallium.warppi.util.Error; @@ -29,7 +28,7 @@ public class HardwarePlatform implements Platform { private final HardwareConsoleUtils cu; private final HardwareGpio gi; - private final HardwareStorageUtils su; + private final HardwarePlatformStorage su; private final ImageUtils pu; private final String on; private final Map el; @@ -44,12 +43,11 @@ public class HardwarePlatform implements Platform { public HardwarePlatform() { cu = new HardwareConsoleUtils(); gi = new HardwareGpio(); - su = new HardwareStorageUtils(); + su = new HardwarePlatformStorage(); pu = new HardwareImageUtils(); on = System.getProperty("os.name").toLowerCase(); el = new HashMap<>(); - el.put("GPU engine", new JOGLEngine()); - el.put("framebuffer engine", new FBEngine()); + el.put("GPU engine", new JOGLEngine(480, 320)); settings = new HardwareSettings(); } @@ -64,7 +62,7 @@ public class HardwarePlatform implements Platform { } @Override - public StorageUtils getStorageUtils() { + public PlatformStorage getPlatformStorage() { return su; } @@ -151,10 +149,10 @@ public class HardwarePlatform implements Platform { @Override public List getRuleFilePaths() throws IOException { - final File dslRulesPath = getStorageUtils().get("rules/"); + final File dslRulesPath = getPlatformStorage().get("rules/"); List paths = new ArrayList<>(); if (dslRulesPath.exists()) { - for (final File file : getStorageUtils().walk(dslRulesPath)) { + for (final File file : getPlatformStorage().walk(dslRulesPath)) { final String path = file.toString(); if (path.endsWith(".rules")) { paths.add(path); @@ -218,6 +216,11 @@ public class HardwarePlatform implements Platform { return backlightOutputDevice; } + @Override + public DeviceStateDevice getDeviceStateDevice() { + return null; + } + @Override public void setArguments(StartupArguments args) { this.args = args; diff --git a/hardware/src/main/java/it/cavallium/warppi/hardware/HardwareStorageUtils.java b/hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatformStorage.java similarity index 92% rename from hardware/src/main/java/it/cavallium/warppi/hardware/HardwareStorageUtils.java rename to hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatformStorage.java index a2763267..486e90ef 100644 --- a/hardware/src/main/java/it/cavallium/warppi/hardware/HardwareStorageUtils.java +++ b/hardware/src/main/java/it/cavallium/warppi/hardware/HardwarePlatformStorage.java @@ -1,219 +1,219 @@ -package it.cavallium.warppi.hardware; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.commons.io.IOUtils; - -import it.cavallium.warppi.Platform.StorageUtils; -import it.cavallium.warppi.util.ClassUtils; - -public class HardwareStorageUtils implements StorageUtils { - @Override - public boolean exists(final File f) { - return f.exists(); - } - - @Override - public File get(final String path) { - return Paths.get(path).toFile(); - } - - @Override - public File get(final String... path) { - if (path.length <= 1) - return Paths.get(path[0]).toFile(); - else - return Paths.get(path[0], Arrays.copyOfRange(path, 1, path.length)).toFile(); - } - - private final Map resourcesCache = new HashMap<>(); - - @Override - @Deprecated() - public File getResource(final String string) throws IOException, URISyntaxException { - final URL res = ClassUtils.classLoader.getResource(string); - final boolean isResource = res != null; - if (isResource) - try { - final URI uri = res.toURI(); - if (res.getProtocol().equalsIgnoreCase("jar")) { - if (resourcesCache.containsKey(string)) { - File f; - if ((f = resourcesCache.get(string)).exists()) - return f; - else - resourcesCache.remove(string); - } - try { - FileSystems.newFileSystem(uri, Collections.emptyMap()); - } catch (final FileSystemAlreadyExistsException e) { - FileSystems.getFileSystem(uri); - } - final Path myFolderPath = Paths.get(uri); - - final InputStream is = Files.newInputStream(myFolderPath); - final File tempFile = File.createTempFile("picalcresource-", ""); - tempFile.deleteOnExit(); - try (FileOutputStream out = new FileOutputStream(tempFile)) { - IOUtils.copy(is, out, (int) tempFile.length()); - } - resourcesCache.put(string, tempFile); - - return tempFile; - } else - return Paths.get(uri).toFile(); - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } - else - return Paths.get(string.substring(1)).toFile(); - } - - @Override - public boolean doesResourceExist(String string) throws IOException { - final URL res = ClassUtils.classLoader.getResource(string); - final boolean isResource = res != null; - if (isResource) - return true; - else { - if (string.length() > 0) { - final char ch = string.charAt(0); - if (ch == '/' || ch == File.separatorChar) - string = string.substring(1); - } - return Files.exists(Paths.get(string)); - } - } - - @Override - public InputStream getResourceStream(String string) throws IOException { - final URL res = ClassUtils.classLoader.getResource(string); - final boolean isResource = res != null; - if (isResource) - try { - final URI uri = res.toURI(); - if (res.getProtocol().equalsIgnoreCase("jar")) { - try { - FileSystems.newFileSystem(uri, Collections.emptyMap()); - } catch (final FileSystemAlreadyExistsException e) { - FileSystems.getFileSystem(uri); - } - final Path myFolderPath = Paths.get(uri); - return Files.newInputStream(myFolderPath); - } else - return Files.newInputStream(Paths.get(uri)); - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } catch (URISyntaxException e) { - throw (IOException) new IOException().initCause(e); - } - else { - if (string.length() > 0) { - final char ch = string.charAt(0); - if (ch == '/' || ch == File.separatorChar) - string = string.substring(1); - } - return Files.newInputStream(Paths.get(string)); - } - } - - @Override - public List readAllLines(final File file) throws IOException { - return Files.readAllLines(file.toPath()); - } - - @Override - public String read(final InputStream input) throws IOException { - try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { - return buffer.lines().collect(Collectors.joining("\n")); - } - } - - @Override - public List walk(final File dir) throws IOException { - final List out = new ArrayList<>(); - try (Stream paths = Files.walk(dir.toPath())) { - paths.filter(Files::isRegularFile).forEach((final Path p) -> { - out.add(p.toFile()); - }); - } - return out; - } - - @Override - public File relativize(final File rulesPath, final File f) { - return rulesPath.toPath().relativize(f.toPath()).toFile(); - } - - @Override - public File resolve(final File file, final String string) { - return file.toPath().resolve(string).toFile(); - } - - @Override - public File getParent(final File f) { - return f.toPath().getParent().toFile(); - } - - @Override - public void createDirectories(final File dir) throws IOException { - Files.createDirectories(dir.toPath()); - } - - @Override - public void write(final File f, final byte[] bytes, final int... options) throws IOException { - final StandardOpenOption[] noptions = new StandardOpenOption[options.length]; - int i = 0; - for (final int opt : options) { - switch (opt) { - case StorageUtils.OpenOptionCreate: { - noptions[i] = StandardOpenOption.CREATE; - break; - } - case StorageUtils.OpenOptionWrite: { - noptions[i] = StandardOpenOption.WRITE; - break; - } - default: { - break; - } - } - i++; - } - Files.write(f.toPath(), bytes, noptions); - } - - @Override - public List readAllLines(final InputStream input) throws IOException { - try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { - return buffer.lines().collect(Collectors.toList()); - } - } - - @Override - public String getBasePath() { - return ""; - } -} +package it.cavallium.warppi.hardware; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.FileSystemAlreadyExistsException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.io.IOUtils; + +import it.cavallium.warppi.Platform.PlatformStorage; +import it.cavallium.warppi.util.ClassUtils; + +public class HardwarePlatformStorage implements PlatformStorage { + @Override + public boolean exists(final File f) { + return f.exists(); + } + + @Override + public File get(final String path) { + return Paths.get(path).toFile(); + } + + @Override + public File get(final String... path) { + if (path.length <= 1) + return Paths.get(path[0]).toFile(); + else + return Paths.get(path[0], Arrays.copyOfRange(path, 1, path.length)).toFile(); + } + + private final Map resourcesCache = new HashMap<>(); + + @Override + @Deprecated() + public File getResource(final String string) throws IOException, URISyntaxException { + final URL res = ClassUtils.classLoader.getResource(string); + final boolean isResource = res != null; + if (isResource) + try { + final URI uri = res.toURI(); + if (res.getProtocol().equalsIgnoreCase("jar")) { + if (resourcesCache.containsKey(string)) { + File f; + if ((f = resourcesCache.get(string)).exists()) + return f; + else + resourcesCache.remove(string); + } + try { + FileSystems.newFileSystem(uri, Collections.emptyMap()); + } catch (final FileSystemAlreadyExistsException e) { + FileSystems.getFileSystem(uri); + } + final Path myFolderPath = Paths.get(uri); + + final InputStream is = Files.newInputStream(myFolderPath); + final File tempFile = File.createTempFile("picalcresource-", ""); + tempFile.deleteOnExit(); + try (FileOutputStream out = new FileOutputStream(tempFile)) { + IOUtils.copy(is, out, (int) tempFile.length()); + } + resourcesCache.put(string, tempFile); + + return tempFile; + } else + return Paths.get(uri).toFile(); + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } + else + return Paths.get(string.substring(1)).toFile(); + } + + @Override + public boolean doesResourceExist(String string) throws IOException { + final URL res = ClassUtils.classLoader.getResource(string); + final boolean isResource = res != null; + if (isResource) + return true; + else { + if (string.length() > 0) { + final char ch = string.charAt(0); + if (ch == '/' || ch == File.separatorChar) + string = string.substring(1); + } + return Files.exists(Paths.get(string)); + } + } + + @Override + public InputStream getResourceStream(String string) throws IOException { + final URL res = ClassUtils.classLoader.getResource(string); + final boolean isResource = res != null; + if (isResource) + try { + final URI uri = res.toURI(); + if (res.getProtocol().equalsIgnoreCase("jar")) { + try { + FileSystems.newFileSystem(uri, Collections.emptyMap()); + } catch (final FileSystemAlreadyExistsException e) { + FileSystems.getFileSystem(uri); + } + final Path myFolderPath = Paths.get(uri); + return Files.newInputStream(myFolderPath); + } else + return Files.newInputStream(Paths.get(uri)); + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } catch (URISyntaxException e) { + throw (IOException) new IOException().initCause(e); + } + else { + if (string.length() > 0) { + final char ch = string.charAt(0); + if (ch == '/' || ch == File.separatorChar) + string = string.substring(1); + } + return Files.newInputStream(Paths.get(string)); + } + } + + @Override + public List readAllLines(final File file) throws IOException { + return Files.readAllLines(file.toPath()); + } + + @Override + public String read(final InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + return buffer.lines().collect(Collectors.joining("\n")); + } + } + + @Override + public List walk(final File dir) throws IOException { + final List out = new ArrayList<>(); + try (Stream paths = Files.walk(dir.toPath())) { + paths.filter(Files::isRegularFile).forEach((final Path p) -> { + out.add(p.toFile()); + }); + } + return out; + } + + @Override + public File relativize(final File rulesPath, final File f) { + return rulesPath.toPath().relativize(f.toPath()).toFile(); + } + + @Override + public File resolve(final File file, final String string) { + return file.toPath().resolve(string).toFile(); + } + + @Override + public File getParent(final File f) { + return f.toPath().getParent().toFile(); + } + + @Override + public void createDirectories(final File dir) throws IOException { + Files.createDirectories(dir.toPath()); + } + + @Override + public void write(final File f, final byte[] bytes, final int... options) throws IOException { + final StandardOpenOption[] noptions = new StandardOpenOption[options.length]; + int i = 0; + for (final int opt : options) { + switch (opt) { + case PlatformStorage.OpenOptionCreate: { + noptions[i] = StandardOpenOption.CREATE; + break; + } + case PlatformStorage.OpenOptionWrite: { + noptions[i] = StandardOpenOption.WRITE; + break; + } + default: { + break; + } + } + i++; + } + Files.write(f.toPath(), bytes, noptions); + } + + @Override + public List readAllLines(final InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + return buffer.lines().collect(Collectors.toList()); + } + } + + @Override + public File getRootPath() { + return new File(""); + } +} diff --git a/hardware/src/main/jni/.gitignore b/hardware/src/main/jni/.gitignore deleted file mode 100644 index 50638950..00000000 --- a/hardware/src/main/jni/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/buffermanager.c diff --git a/hardware/src/main/jni/CMakeLists.txt b/hardware/src/main/jni/CMakeLists.txt deleted file mode 100644 index 0ffeefd5..00000000 --- a/hardware/src/main/jni/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(picalculatornative) -SET(COMPILE_DEFINITIONS -Werror) - -find_package(JNI REQUIRED) -include_directories(${JNI_INCLUDE_DIRS}) - -include_directories(/opt/vc/include) -include_directories(/opt/vc/include/interface/vcos/pthreads) -include_directories(/opt/vc/include/interface/vmcs_host) -include_directories(/opt/vc/include/interface/vmcs_host/linux) - -link_directories(/opt/vc/lib) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -set(SOURCE_FILES TestJNI.cpp) -add_library(picalculatornative SHARED ${SOURCE_FILES}) \ No newline at end of file diff --git a/hardware/src/main/jni/TestJNI.cpp b/hardware/src/main/jni/TestJNI.cpp deleted file mode 100644 index 9a951f7a..00000000 --- a/hardware/src/main/jni/TestJNI.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TestJNI.h" - -int fbfd = -1; -char *fbp = nullptr; -struct fb_var_screeninfo vinfo; -struct fb_fix_screeninfo finfo; - - -JNIEXPORT void JNICALL Java_org_warp_picalculator_TestJNI_disposeDisplayBuffer(JNIEnv *env, jobject thisObj) -{ - if (fbp != nullptr) { - munmap(fbp, finfo.smem_len); - fbp = nullptr; - } - if (fbfd != -1) { - close(fbfd); - fbfd = -1; - } - return; -} - -JNIEXPORT jobject JNICALL Java_org_warp_picalculator_TestJNI_getDisplayBuffer(JNIEnv *env, jobject thisObj) -{ - - syslog(LOG_INFO, "[JNI NATIVE] INIT"); - - fbfd = open("/dev/fb1", O_RDWR); - if (fbfd == -1) { - syslog(LOG_ERR, "Unable to open secondary display"); - return NULL; - } - if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) { - syslog(LOG_ERR, "Unable to get secondary display information"); - return NULL; - } - if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { - syslog(LOG_ERR, "Unable to get secondary display information"); - return NULL; - } - - syslog(LOG_INFO, "Second display is %d x %d %dbps\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); - - fbp = (char*) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); - if (fbp <= 0) { - syslog(LOG_ERR, "Unable to create mamory mapping"); - close(fbfd); - return NULL; - } - - char* class_name = "org/warp/picalculator/MmapByteBuffer"; - jclass clz = env->FindClass(class_name); - if (clz == NULL) { - printf("Error, could not find class '%s'\n", class_name); - return NULL; - } - char* signature = "(IIILjava/nio/ByteBuffer;)V"; - jmethodID constructor = env->GetMethodID( clz, "", signature); - if (constructor == NULL) { - printf("Error, could not find constructor %s %s\n", class_name, signature); - return NULL; - } - - syslog(LOG_INFO, "[JNI NATIVE] DONE"); - return env->NewObject(clz, constructor, fbfd, fbp, finfo.smem_len, - env->NewDirectByteBuffer(fbp, finfo.smem_len)); -} diff --git a/hardware/src/main/jni/TestJNI.h b/hardware/src/main/jni/TestJNI.h deleted file mode 100644 index 4604c785..00000000 --- a/hardware/src/main/jni/TestJNI.h +++ /dev/null @@ -1,29 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_warp_picalculator_TestJNI */ - -#ifndef _Included_org_warp_picalculator_TestJNI -#define _Included_org_warp_picalculator_TestJNI -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_warp_picalculator_TestJNI - * Method: getDisplayBuffer - * Signature: ()Lorg/warp/picalculator/MmapByteBuffer; - */ -JNIEXPORT jobject JNICALL Java_org_warp_picalculator_TestJNI_getDisplayBuffer - (JNIEnv *, jobject); - -/* - * Class: org_warp_picalculator_TestJNI - * Method: disposeDisplayBuffer - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_org_warp_picalculator_TestJNI_disposeDisplayBuffer - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/hardware/src/main/jni/libpicalc.so b/hardware/src/main/jni/libpicalc.so deleted file mode 100644 index 25c9e68c..00000000 Binary files a/hardware/src/main/jni/libpicalc.so and /dev/null differ diff --git a/hardware/src/main/jni/makefileOLD b/hardware/src/main/jni/makefileOLD deleted file mode 100644 index 17d2aa45..00000000 --- a/hardware/src/main/jni/makefileOLD +++ /dev/null @@ -1,32 +0,0 @@ -# Define a variable for classpath -CLASS_PATH = ../../../target/classes -PATH1A = it/cavallium/warppi -PATH1B = it.cavallium.warppi - -# Define a virtual path for .class in the bin directory -vpath %.class $(CLASS_PATH)/$(PATH1A) - -all : picalculatornative.so - -# $@ matches the target, $< matches the first dependancy -picalculatornative.so : TestJNI.o - gcc -m64 -mtune=generic -Wl,--add-stdcall-alias -shared -o ../resources/$@ $< - -# $@ matches the target, $< matches the first dependancy -picalculatornative.dll : windows_TestJNI.o - x86_64-w64-mingw32-gcc.exe -m64 -mtune=generic -Wl,--add-stdcall-alias -shared -o ../resources/$@ $< - -# $@ matches the target, $< matches the first dependancy -windows_TestJNI.o : TestJNI.c TestJNI.h - x86_64-w64-mingw32-gcc.exe -m64 -mtune=generic -I"G:\Program Files\Java\jdk1.8.0_144\include" -I"G:\Program Files\Java\jdk1.8.0_144\include\win32" -c $< -o $@ - -# $@ matches the target, $< matches the first dependancy -TestJNI.o : TestJNI.c TestJNI.h - gcc -m64 -mtune=generic -I"G:\Program Files\Java\jdk1.8.0_144\include" -I"G:\Program Files\Java\jdk1.8.0_144\include\win32" -c $< -o $@ - -# $* matches the target filename without the extension -TestJNI.h : TestJNI.class - javah -o "$*.h" -classpath "$(CLASS_PATH)" $(PATH1B).$* - -clean : - rm TestJNI.h TestJNI.o ../resources/picalculatornative.dll \ No newline at end of file diff --git a/teavm/pom.xml b/teavm/pom.xml index c66300ff..a5bc8ff0 100644 --- a/teavm/pom.xml +++ b/teavm/pom.xml @@ -91,10 +91,10 @@ it.cavallium.warppi.teavm.TeaVMBoot false - true - true + false + false SIMPLE - true + false diff --git a/teavm/src/main/java/it/cavallium/warppi/gui/graphicengine/html/HtmlSkin.java b/teavm/src/main/java/it/cavallium/warppi/gui/graphicengine/html/HtmlSkin.java index 7b3f4510..3cc7e82d 100644 --- a/teavm/src/main/java/it/cavallium/warppi/gui/graphicengine/html/HtmlSkin.java +++ b/teavm/src/main/java/it/cavallium/warppi/gui/graphicengine/html/HtmlSkin.java @@ -1,17 +1,21 @@ package it.cavallium.warppi.gui.graphicengine.html; +import java.io.File; import java.io.IOException; -import java.io.InputStream; +import java.net.URL; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.commons.lang3.ArrayUtils; +import it.cavallium.warppi.teavm.TeaVMStorageUtils; +import org.teavm.jso.JSBody; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; import org.teavm.jso.browser.Window; +import org.teavm.jso.canvas.CanvasImageSource; import org.teavm.jso.dom.events.Event; import org.teavm.jso.dom.html.HTMLDocument; import org.teavm.jso.dom.html.HTMLImageElement; import it.cavallium.warppi.WarpPI; -import it.cavallium.warppi.Platform.Semaphore; import it.cavallium.warppi.device.display.DisplayOutputDevice; import it.cavallium.warppi.gui.graphicengine.Skin; @@ -22,8 +26,7 @@ public class HtmlSkin implements Skin { private int[] skinSize; private boolean initd; - - private HTMLImageElement imgEl; + private CanvasImageSource imgEl; public HtmlSkin(final String file) throws IOException { load(file); @@ -38,25 +41,35 @@ public class HtmlSkin implements Skin { @Override public void load(String file) throws IOException { - url = WarpPI.getPlatform().getStorageUtils().getBasePath() + (!file.startsWith("/") ? "/" : "") + file; + File path = new File(WarpPI.getPlatform().getPlatformStorage().getRootPath(), file); + this.url = TeaVMStorageUtils.getUrl(path).toString(); } @Override public void initialize(final DisplayOutputDevice d) { final HTMLDocument doc = Window.current().getDocument(); AtomicBoolean done = new AtomicBoolean(false); - imgEl = doc.createElement("img").cast(); - imgEl.addEventListener("load", (Event e) -> { + + loadImage(url, (width, height, imageSource) -> { + skinSize = new int[] {width, height}; + this.imgEl = imageSource; done.set(true); }); - imgEl.setSrc(url); + while (!done.get()) { try {Thread.sleep(15);} catch (Exception e) {} } - skinSize = new int[] { imgEl.getNaturalWidth(), imgEl.getNaturalHeight() }; initd = true; } + @JSBody(params = { "url", "loadHandler" }, script = "var image = new Image(); image.onload = function(evt) { loadHandler(image.naturalWidth, image.naturalHeight, image);}; image.src = url;") + public static native void loadImage(String url, LoadHandler loadHandler); + + @JSFunctor + public interface LoadHandler extends JSObject { + void onLoad(int width, int height, CanvasImageSource imageSource); + } + @Override public boolean isInitialized() { return initd; @@ -76,7 +89,7 @@ public class HtmlSkin implements Skin { return url; } - public final HTMLImageElement getImgElement() { + public final CanvasImageSource getImgElement() { return imgEl; } } \ No newline at end of file diff --git a/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatform.java b/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatform.java index ce640fe0..57896f42 100644 --- a/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatform.java +++ b/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatform.java @@ -4,9 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.function.Consumer; import it.cavallium.warppi.boot.StartupArguments; @@ -24,7 +22,6 @@ import org.teavm.jso.dom.html.HTMLDocument; import it.cavallium.warppi.Platform; import it.cavallium.warppi.device.display.DisplayOutputDevice; -import it.cavallium.warppi.gui.graphicengine.GraphicEngine; import it.cavallium.warppi.gui.graphicengine.html.HtmlEngine; import it.cavallium.warppi.util.Error; @@ -32,7 +29,7 @@ public class TeaVMPlatform implements Platform { private final TeaVMConsoleUtils cu; private final TeaVMGpio gi; - private final TeaVMStorageUtils su; + private final TeaVMPlatformStorage su; private final String on; private final TeaVMImageUtils pu; private final TeaVMSettings settings; @@ -46,7 +43,7 @@ public class TeaVMPlatform implements Platform { public TeaVMPlatform() { cu = new TeaVMConsoleUtils(); gi = new TeaVMGpio(); - su = new TeaVMStorageUtils(); + su = new TeaVMPlatformStorage(); pu = new TeaVMImageUtils(); on = "JavaScript"; settings = new TeaVMSettings(); @@ -63,7 +60,7 @@ public class TeaVMPlatform implements Platform { } @Override - public StorageUtils getStorageUtils() { + public PlatformStorage getPlatformStorage() { return su; } @@ -157,8 +154,8 @@ public class TeaVMPlatform implements Platform { */ @Override public List getRuleFilePaths() throws IOException { - try (final InputStream listStream = getStorageUtils().getResourceStream("/rules.list")) { - return getStorageUtils().readAllLines(listStream); + try (final InputStream listStream = getPlatformStorage().getResourceStream("/rules.list")) { + return getPlatformStorage().readAllLines(listStream); } } diff --git a/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatformStorage.java b/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatformStorage.java new file mode 100644 index 00000000..cbe6948c --- /dev/null +++ b/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMPlatformStorage.java @@ -0,0 +1,223 @@ +package it.cavallium.warppi.teavm; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.teavm.jso.browser.Window; + +import it.cavallium.warppi.Platform.PlatformStorage; + +public class TeaVMPlatformStorage implements PlatformStorage { + @Override + public boolean exists(final File f) { + return f.exists(); + } + + @Override + public File get(final String path) { + return new File(path); + } + + private static String join(final String[] list, final String conjunction) { + final StringBuilder sb = new StringBuilder(); + boolean first = true; + for (final String item : list) { + if (first) + first = false; + else + sb.append(conjunction); + sb.append(item); + } + return sb.toString(); + } + + @Override + public File get(final String... path) { + return new File(TeaVMPlatformStorage.join(path, File.separator)); + } + + private static Map resourcesCache = new HashMap<>(); + + @Override + public File getResource(final String path) throws IOException, URISyntaxException { + try { + File targetFile; + if (TeaVMPlatformStorage.resourcesCache.containsKey(path)) + if ((targetFile = TeaVMPlatformStorage.resourcesCache.get(path)).exists()) + return targetFile; + else + TeaVMPlatformStorage.resourcesCache.remove(path); + final URL res = TeaVMStorageUtils.getUrl(new File(getRootPath(), path)); + final InputStream initialStream = res.openStream(); + final byte[] buffer = new byte[initialStream.available()]; + initialStream.read(buffer); + + targetFile = File.createTempFile("res", ".bin"); + targetFile.createNewFile(); + final FileOutputStream outStream = new FileOutputStream(targetFile); + outStream.write(buffer); + outStream.close(); + TeaVMPlatformStorage.resourcesCache.put(path, targetFile); + return targetFile; + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } + } + + @Override + public InputStream getResourceStream(final String path) throws IOException { + try { + File targetFile; + if (TeaVMPlatformStorage.resourcesCache.containsKey(path)) + if ((targetFile = TeaVMPlatformStorage.resourcesCache.get(path)).exists()) + return new FileInputStream(targetFile); + else + TeaVMPlatformStorage.resourcesCache.remove(path); + final URL res = TeaVMStorageUtils.getUrl(new File(getRootPath(), path)); + final InputStream initialStream = res.openStream(); + final byte[] buffer = new byte[initialStream.available()]; + initialStream.read(buffer); + + targetFile = File.createTempFile("res", ".bin"); + targetFile.createNewFile(); + final FileOutputStream outStream = new FileOutputStream(targetFile); + outStream.write(buffer); + outStream.close(); + TeaVMPlatformStorage.resourcesCache.put(path, targetFile); + return new FileInputStream(targetFile); + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } + } + + @Override + public boolean doesResourceExist(final String path) throws IOException { + try { + File targetFile; + if (TeaVMPlatformStorage.resourcesCache.containsKey(path)) + if ((targetFile = TeaVMPlatformStorage.resourcesCache.get(path)).exists()) + return true; + else + TeaVMPlatformStorage.resourcesCache.remove(path); + return true; + } catch (final java.lang.IllegalArgumentException e) { + throw e; + } + } + + @Override + public List readAllLines(final File file) throws IOException { + final Reader reader_ = new InputStreamReader(new FileInputStream(file), Charset.defaultCharset()); + final BufferedReader reader = reader_ instanceof BufferedReader ? (BufferedReader) reader_ : new BufferedReader(reader_); + final List list = new ArrayList<>(); + String line = reader.readLine(); + while (line != null) { + list.add(line); + line = reader.readLine(); + } + reader.close(); + return list; + } + + // Reading an InputStream as a String is implemented this way + // because, on TeaVM, more convenient methods (such as IOUtils.toString) hang. + @Override + public String read(final InputStream input) throws IOException { + final int BUFFER_SIZE = 1024; + + final StringBuilder builder = new StringBuilder(); + try (final Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) { + final char[] buffer = new char[BUFFER_SIZE]; + int readCount; + while ((readCount = reader.read(buffer)) != -1) { + builder.append(buffer, 0, readCount); + } + } + return builder.toString(); + } + + @Override + public List walk(final File dir) throws IOException { + final List out = new ArrayList<>(); + final File[] filesList = dir.listFiles(); + if (filesList == null) + out.add(dir); + else + for (final File f : filesList) + if (f.isDirectory()) { + if (f.canRead()) + out.addAll(walk(dir)); + } else if (f.isFile()) + if (f.canRead()) + out.add(f); + return out; + } + + @Override + public File relativize(final File rulesPath, final File f) { + return f; + } + + @Override + public File resolve(final File file, final String string) { + return new File(file.getAbsolutePath() + File.separatorChar + string); + } + + @Override + public File getParent(final File f) { + return f.getParentFile(); + } + + @Override + public void createDirectories(final File dir) throws IOException { + dir.mkdirs(); + } + + @Override + public void write(final File f, final byte[] bytes, final int... options) throws IOException { + boolean create = false; + for (final int opt : options) + if (opt == PlatformStorage.OpenOptionCreate) + create = true; + if (f.exists() == false) + if (create) { + if (!f.createNewFile()) + throw new IOException("File doesn't exist, can't create it!"); + } else + throw new IOException("File doesn't exist."); + final FileOutputStream stream = new FileOutputStream(f); + stream.write(bytes); + stream.close(); + } + + @Override + public List readAllLines(final InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + String thisLine = null; + final ArrayList output = new ArrayList<>(); + while ((thisLine = buffer.readLine()) != null) + output.add(thisLine); + return output; + } + } + + @Override + public File getRootPath() { + return new File("resources"); + } +} diff --git a/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMStorageUtils.java b/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMStorageUtils.java index 3d8cefd0..a8a2469d 100644 --- a/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMStorageUtils.java +++ b/teavm/src/main/java/it/cavallium/warppi/teavm/TeaVMStorageUtils.java @@ -1,226 +1,46 @@ -package it.cavallium.warppi.teavm; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.teavm.jso.browser.Window; - -import it.cavallium.warppi.Platform.StorageUtils; - -public class TeaVMStorageUtils implements StorageUtils { - @Override - public boolean exists(final File f) { - return f.exists(); - } - - @Override - public File get(final String path) { - return new File(path); - } - - private static String join(final String[] list, final String conjunction) { - final StringBuilder sb = new StringBuilder(); - boolean first = true; - for (final String item : list) { - if (first) - first = false; - else - sb.append(conjunction); - sb.append(item); - } - return sb.toString(); - } - - @Override - public File get(final String... path) { - return new File(TeaVMStorageUtils.join(path, File.separator)); - } - - private static Map resourcesCache = new HashMap<>(); - - @Override - public File getResource(final String path) throws IOException, URISyntaxException { - try { - File targetFile; - if (TeaVMStorageUtils.resourcesCache.containsKey(path)) - if ((targetFile = TeaVMStorageUtils.resourcesCache.get(path)).exists()) - return targetFile; - else - TeaVMStorageUtils.resourcesCache.remove(path); - final URL res = new URL(getBasePath() + path); - final InputStream initialStream = res.openStream(); - final byte[] buffer = new byte[initialStream.available()]; - initialStream.read(buffer); - - targetFile = File.createTempFile("res", ".bin"); - targetFile.createNewFile(); - final FileOutputStream outStream = new FileOutputStream(targetFile); - outStream.write(buffer); - outStream.close(); - TeaVMStorageUtils.resourcesCache.put(path, targetFile); - return targetFile; - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } - } - - @Override - public InputStream getResourceStream(final String path) throws IOException { - try { - File targetFile; - if (TeaVMStorageUtils.resourcesCache.containsKey(path)) - if ((targetFile = TeaVMStorageUtils.resourcesCache.get(path)).exists()) - return new FileInputStream(targetFile); - else - TeaVMStorageUtils.resourcesCache.remove(path); - final URL res = new URL(getBasePath() + (path.startsWith("/") ? path : "/" + path)); - final InputStream initialStream = res.openStream(); - final byte[] buffer = new byte[initialStream.available()]; - initialStream.read(buffer); - - targetFile = File.createTempFile("res", ".bin"); - targetFile.createNewFile(); - final FileOutputStream outStream = new FileOutputStream(targetFile); - outStream.write(buffer); - outStream.close(); - TeaVMStorageUtils.resourcesCache.put(path, targetFile); - return new FileInputStream(targetFile); - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } - } - - @Override - public boolean doesResourceExist(final String path) throws IOException { - try { - File targetFile; - if (TeaVMStorageUtils.resourcesCache.containsKey(path)) - if ((targetFile = TeaVMStorageUtils.resourcesCache.get(path)).exists()) - return true; - else - TeaVMStorageUtils.resourcesCache.remove(path); - return true; - } catch (final java.lang.IllegalArgumentException e) { - throw e; - } - } - - @Override - public List readAllLines(final File file) throws IOException { - final Reader reader_ = new InputStreamReader(new FileInputStream(file), Charset.defaultCharset()); - final BufferedReader reader = reader_ instanceof BufferedReader ? (BufferedReader) reader_ : new BufferedReader(reader_); - final List list = new ArrayList<>(); - String line = reader.readLine(); - while (line != null) { - list.add(line); - line = reader.readLine(); - } - reader.close(); - return list; - } - - // Reading an InputStream as a String is implemented this way - // because, on TeaVM, more convenient methods (such as IOUtils.toString) hang. - @Override - public String read(final InputStream input) throws IOException { - final int BUFFER_SIZE = 1024; - - final StringBuilder builder = new StringBuilder(); - try (final Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) { - final char[] buffer = new char[BUFFER_SIZE]; - int readCount; - while ((readCount = reader.read(buffer)) != -1) { - builder.append(buffer, 0, readCount); - } - } - return builder.toString(); - } - - @Override - public List walk(final File dir) throws IOException { - final List out = new ArrayList<>(); - final File[] filesList = dir.listFiles(); - if (filesList == null) - out.add(dir); - else - for (final File f : filesList) - if (f.isDirectory()) { - if (f.canRead()) - out.addAll(walk(dir)); - } else if (f.isFile()) - if (f.canRead()) - out.add(f); - return out; - } - - @Override - public File relativize(final File rulesPath, final File f) { - return f; - } - - @Override - public File resolve(final File file, final String string) { - return new File(file.getAbsolutePath() + File.separatorChar + string); - } - - @Override - public File getParent(final File f) { - return f.getParentFile(); - } - - @Override - public void createDirectories(final File dir) throws IOException { - dir.mkdirs(); - } - - @Override - public void write(final File f, final byte[] bytes, final int... options) throws IOException { - boolean create = false; - for (final int opt : options) - if (opt == StorageUtils.OpenOptionCreate) - create = true; - if (f.exists() == false) - if (create) { - if (!f.createNewFile()) - throw new IOException("File doesn't exist, can't create it!"); - } else - throw new IOException("File doesn't exist."); - final FileOutputStream stream = new FileOutputStream(f); - stream.write(bytes); - stream.close(); - } - - @Override - public List readAllLines(final InputStream input) throws IOException { - try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { - String thisLine = null; - final ArrayList output = new ArrayList<>(); - while ((thisLine = buffer.readLine()) != null) - output.add(thisLine); - return output; - } - } - - @Override - public String getBasePath() { - final String fullurl = Window.current().getLocation().getFullURL(); - if (fullurl.charAt(fullurl.length() - 1) == '/') - return fullurl + "resources"; - else - return fullurl + "/resources"; - } -} +package it.cavallium.warppi.teavm; + +import org.teavm.jso.browser.Window; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; + +public class TeaVMStorageUtils { + public static URL getUrl(File file) throws MalformedURLException { + String path = file.toString(); + if (path.startsWith("/")) { + path = path.substring(1); + } + + String protocol = Window.current().getLocation().getProtocol(); + String host = Window.current().getLocation().getHost(); + String indexPath = Window.current().getLocation().getPathName(); + String websiteDir; + if (indexPath.endsWith("/")) { + websiteDir = indexPath; + } else { + String[] parts = indexPath.split("/"); + String[] dirParts = Arrays.copyOf(parts, parts.length - 1); + StringBuilder dirBuilder = new StringBuilder("/"); + for (String dirPart : dirParts) { + dirBuilder.append(dirPart); + dirBuilder.append('/'); + } + websiteDir = dirBuilder.toString(); + } + String fullUrl = protocol + "//" + host + websiteDir; + if (fullUrl.endsWith("/")) { + fullUrl = fullUrl.substring(0, fullUrl.length() - 1); + } + + String urlString = fullUrl + "/" + path; + try { + return new URL(urlString); + } catch (MalformedURLException e) { + System.out.println("Errored URL: " + fullUrl + "/" + path); + throw e; + } + } +}