package xapi.jre.ui.css; import xapi.collect.X_Collect; import xapi.collect.api.CollectionOptions; import xapi.collect.api.StringTo; import xapi.fu.Out1; import xapi.io.X_IO; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; import java.nio.charset.Charset; /** * I abhor the name of this class, * but it must be called "Handler" in order for java.net.URL to be able to find us. * * It sucks, but it's not our api, and it's the only way to get dynamic stylesheets in JavaFx, * short of overriding the url stream handler directly (and this can only be done once in a single * JVM, and as framework-level code, it is unacceptable to prevent clients from choosing to * override the stream handler themselves). * * Created by James X. Nelson (james @wetheinter.net) on 8/21/16. */ public class Handler extends URLStreamHandler { private static final StringTo<Out1<String>> dynamicFiles; static { // Ensure that we are registered as a url protocol handler for JavaFxCss:/path css files. String was = System.getProperty("java.protocol.handler.pkgs", ""); System.setProperty("java.protocol.handler.pkgs", Handler.class.getPackage().getName().replace(".css", "") + (was.isEmpty() ? "" : "|" + was )); dynamicFiles = X_Collect.newStringMap(Out1.class, CollectionOptions.asConcurrent(true) .mutable(true) .insertionOrdered(false) .build()); } public static String registerStylesheet(String path, Out1<String> contents) { dynamicFiles.put(path, contents); return path; } @Override protected URLConnection openConnection(URL u) throws IOException { final String path = u.getPath(); final Out1<String> file = dynamicFiles.get(path); String query = u.getQuery(); if (query != null) { // parse the query params, and send them to the css builder (use something other than Out1) } return new StringURLConnection(u, file); } private static class StringURLConnection extends URLConnection { private final Out1<String> contents; public StringURLConnection(URL url, Out1<String> contents){ super(url); this.contents = contents; } @Override public void connect() throws IOException {} @Override public InputStream getInputStream() throws IOException { return X_IO.toStream(contents.out1(), Charset.defaultCharset().name()); } } }