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

com.github.jsonldjava.tools.Playground Maven / Gradle / Ivy

The newest version!
package com.github.jsonldjava.tools;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.cache.BasicHttpCacheStorage;
import org.apache.http.impl.client.cache.CacheConfig;
import org.apache.http.impl.client.cache.CachingHttpClientBuilder;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.RDFParserRegistry;
import org.eclipse.rdf4j.rio.Rio;

import com.github.jsonldjava.core.DocumentLoader;
import com.github.jsonldjava.core.JsonLdApi;
import com.github.jsonldjava.core.JsonLdConsts;
import com.github.jsonldjava.core.JsonLdOptions;
import com.github.jsonldjava.core.JsonLdProcessor;
import com.github.jsonldjava.core.RDFDataset;
import com.github.jsonldjava.utils.JarCacheStorage;
import com.github.jsonldjava.utils.JsonUtils;

import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import joptsimple.ValueConversionException;
import joptsimple.ValueConverter;

/**
 * A command-line-interface used to load and process JSON-LD and RDF files.
 */
public class Playground {

    public static void main(String[] args) throws Exception {

        final Map formats = getOutputFormats();
        final Set outputForms = new LinkedHashSet(
                Arrays.asList("compacted", "expanded", "flattened"));

        final OptionParser parser = new OptionParser();

        final OptionSpec help = parser.accepts("help").forHelp();

        final OptionSpec base = parser.accepts("base").withRequiredArg()
                .ofType(String.class).defaultsTo("").describedAs("base URI");

        final OptionSpec inputFile = parser.accepts("inputFile").withRequiredArg()
                .ofType(File.class).required().describedAs("The input file");

        final OptionSpec context = parser.accepts("context").withRequiredArg()
                .ofType(File.class).describedAs("The context");

        final OptionSpec outputFormat = parser.accepts("format").withOptionalArg()
                .ofType(String.class).withValuesConvertedBy(new ValueConverter() {
                    @Override
                    public RDFFormat convert(String inputFormat) {
                        // Normalise the name to provide alternatives
                        final String formatName = inputFormat.replaceAll("-", "")
                                .replaceAll("/", "").toLowerCase();
                        if (formats.containsKey(formatName)) {
                            return formats.get(formatName);
                        }
                        throw new ValueConversionException("Format was not known: " + inputFormat
                                + " (Valid values are: " + formats.keySet() + ")");
                    }

                    @Override
                    public String valuePattern() {
                        return null;
                    }

                    @Override
                    public Class valueType() {
                        return RDFFormat.class;
                    }
                }).defaultsTo(RDFFormat.NQUADS)
                .describedAs("The output file format to use. Defaults to nquads. Valid values are: "
                        + formats.keySet());

        final OptionSpec processingOption = parser.accepts("process").withRequiredArg()
                .ofType(String.class).required()
                .withValuesConvertedBy(new ValueConverter() {
                    @Override
                    public String convert(String value) {
                        if (getProcessingOptions().contains(value.toLowerCase())) {
                            return value.toLowerCase();
                        }
                        throw new ValueConversionException("Processing option was not known: "
                                + value + " (Valid values are: " + getProcessingOptions() + ")");
                    }

                    @Override
                    public Class valueType() {
                        return String.class;
                    }

                    @Override
                    public String valuePattern() {
                        return null;
                    }
                }).describedAs("The processing to perform. Valid values are: "
                        + getProcessingOptions().toString());

        final OptionSpec outputForm = parser.accepts("outputForm").withOptionalArg()
                .ofType(String.class).defaultsTo("expanded")
                .withValuesConvertedBy(new ValueConverter() {
                    @Override
                    public String convert(String value) {
                        if (outputForms.contains(value.toLowerCase())) {
                            return value.toLowerCase();
                        }
                        throw new ValueConversionException("Output form was not known: " + value
                                + " (Valid values are: " + outputForms + ")");
                    }

                    @Override
                    public String valuePattern() {
                        return null;
                    }

                    @Override
                    public Class valueType() {
                        return String.class;
                    }
                }).describedAs(
                        "The way to output the results from fromRDF. Defaults to expanded. Valid values are: "
                                + outputForms);

        final OptionSpec usernameOption = parser.accepts("username").withOptionalArg()
                .ofType(String.class).describedAs("username for basic authentication credentials");

        final OptionSpec passwordOption = parser.accepts("password").withOptionalArg()
                .ofType(String.class).describedAs(
                        "password for basic authentication credentials (defaults to value of 'PASSWORD' environment property, if set, or empty string otherwise)");

        final OptionSpec authHostOption = parser.accepts("authHost").withOptionalArg()
                .ofType(String.class).defaultsTo("localhost")
                .describedAs("host authentication scope");

        final OptionSpec authPortOption = parser.accepts("authPort").withOptionalArg()
                .ofType(Integer.class).defaultsTo(443)
                .describedAs("host port authentication scope");

        final OptionSpec authInsecureOption = parser.accepts("insecure",
                "Similar to `curl -k` or `curl --insecure`: if unspecified, all SSL connections are secure by default; if specified, trust everything (do not use for production!)");

        OptionSet options = null;

        try {
            options = parser.parse(args);
        } catch (final OptionException e) {
            System.out.println(e.getMessage());
            parser.printHelpOn(System.out);
            throw e;
        }

        if (options.has(help)) {
            parser.printHelpOn(System.out);
            return;
        }

        final JsonLdOptions opts = new JsonLdOptions("");
        Object inobj = null;
        Object ctxobj = null;

        opts.setBase(options.valueOf(base));
        opts.outputForm = options.valueOf(outputForm);
        opts.format = options.has(outputFormat) ? options.valueOf(outputFormat).getDefaultMIMEType()
                : JsonLdConsts.APPLICATION_NQUADS;
        final RDFFormat sesameOutputFormat = options.valueOf(outputFormat);
        final RDFFormat sesameInputFormat = Rio
                .getParserFormatForFileName(options.valueOf(inputFile).getName())
                .orElse(RDFFormat.JSONLD);

        final String processingOptionValue = options.valueOf(processingOption);

        if (!options.valueOf(inputFile).exists()) {
            System.out.println(
                    "Error: input file \"" + options.valueOf(inputFile) + "\" doesn't exist");
            parser.printHelpOn(System.out);
            return;
        }
        // if base is currently null, set it
        if (opts.getBase() == null || opts.getBase().equals("")) {
            opts.setBase(options.valueOf(inputFile).toURI().toASCIIString());
        }

        if (options.hasArgument(usernameOption)) {
            final String username = options.valueOf(usernameOption);
            final String envPassword = System.getenv("PASSWORD");
            final String password = options.hasArgument(passwordOption)
                    ? options.valueOf(passwordOption)
                    : (null != envPassword) ? envPassword : "";
            final String authHost = options.valueOf(authHostOption);
            final Integer authPort = options.valueOf(authPortOption);

            final DocumentLoader documentLoader = new DocumentLoader();

            final CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(new AuthScope(authHost, authPort),
                    new UsernamePasswordCredentials(username, password));

            final CacheConfig cacheConfig = CacheConfig.custom().setMaxCacheEntries(1000)
                    .setMaxObjectSize(1024 * 128).build();

            HttpClientBuilder builder = CachingHttpClientBuilder.create()
                    // allow caching
                    .setCacheConfig(cacheConfig)
                    // Wrap the local JarCacheStorage around a
                    // BasicHttpCacheStorage
                    .setHttpCacheStorage(new JarCacheStorage(null, cacheConfig,
                            new BasicHttpCacheStorage(cacheConfig)))
                    .setDefaultCredentialsProvider(credsProvider);

            if (options.has(authInsecureOption)) {
                final SSLContext ctx = SSLContext.getInstance("TLS");
                ctx.init(null, new TrustManager[] { new InsecureX509TrustManager() }, null);
                final HostnameVerifier v = new HostnameVerifier() {
                    @Override
                    public boolean verify(String s, SSLSession sslSession) {
                        return true;
                    }
                };

                final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, v);
                // insecure ssl connections
                builder = builder.setSSLSocketFactory(sslsf);
            }

            documentLoader.setHttpClient(builder.build());
            opts.setDocumentLoader(documentLoader);
        }

        if ("fromrdf".equals(processingOptionValue)) {
            inobj = readFile(options.valueOf(inputFile));
        } else {
            inobj = JsonUtils.fromInputStream(new FileInputStream(options.valueOf(inputFile)));
        }

        if (hasContext(processingOptionValue) && options.has(context)) {
            if (!options.valueOf(context).exists()) {
                System.out.println(
                        "Error: context file \"" + options.valueOf(context) + "\" doesn't exist");
                parser.printHelpOn(System.out);
                return;
            }
            ctxobj = JsonUtils.fromInputStream(new FileInputStream(options.valueOf(context)));
        }

        Object outobj = null;
        if ("fromrdf".equals(processingOptionValue)) {
            final Model inModel = Rio.parse(new StringReader((String) inobj), opts.getBase(),
                    sesameInputFormat);

            outobj = JsonLdProcessor.fromRDF(inModel, opts, new RDF4JJSONLDRDFParser());
        } else if ("tordf".equals(processingOptionValue)) {
            opts.useNamespaces = true;
            outobj = JsonLdProcessor.toRDF(inobj,
                    new RDF4JJSONLDTripleCallback(Rio.createWriter(sesameOutputFormat, System.out)),
                    opts);
        } else if ("expand".equals(processingOptionValue)) {
            outobj = JsonLdProcessor.expand(inobj, opts);
        } else if ("compact".equals(processingOptionValue)) {
            if (ctxobj == null) {
                System.out.println("Error: The compaction context must not be null.");
                parser.printHelpOn(System.out);
                return;
            }
            outobj = JsonLdProcessor.compact(inobj, ctxobj, opts);
        } else if ("normalize".equals(processingOptionValue)) {
            // see https://github.com/jsonld-java/jsonld-java/issues/193
            // outobj = JsonLdProcessor.normalize(inobj, opts);

            // see https://github.com/jsonld-java/jsonld-java/issues/194
            // until this is fixed, it is necessary to clear the format so that
            // JsonLdProcessor won't try to interpret it.
            opts.format = null;

            // If an output format is specified, add a callback to show the
            // result.
            final Object result = JsonLdProcessor.toRDF(inobj,
                    options.has(outputFormat)
                            ? new RDF4JJSONLDTripleCallback(
                                    Rio.createWriter(sesameOutputFormat, System.out))
                            : null,
                    opts);
            if (RDFDataset.class.isInstance(result)) {
                final RDFDataset rdfds = RDFDataset.class.cast(result);
                outobj = new JsonLdApi(opts).normalize(rdfds);
            } else {
                outobj = result;
            }
        } else if ("frame".equals(processingOptionValue)) {
            if (ctxobj != null && !(ctxobj instanceof Map)) {
                System.out.println(
                        "Invalid JSON-LD syntax; a JSON-LD frame must be a single object.");
                parser.printHelpOn(System.out);
                return;
            }
            outobj = JsonLdProcessor.frame(inobj, ctxobj, opts);
        } else if ("flatten".equals(processingOptionValue)) {
            outobj = JsonLdProcessor.flatten(inobj, ctxobj, opts);
        } else {
            System.out
                    .println("Error: invalid processing option \"" + processingOptionValue + "\"");
            parser.printHelpOn(System.out);
            return;
        }

        if ("tordf".equals(processingOptionValue)) {
            // Already serialised above
        } else if ("normalize".equals(processingOptionValue)) {
            if (!options.has(outputFormat)) {
                // if no output format was specified, then show the result.
                System.out.println(JsonUtils.toPrettyString(outobj));
            }
        } else {
            System.out.println(JsonUtils.toPrettyString(outobj));
        }
    }

    private static Set getProcessingOptions() {
        return new LinkedHashSet(Arrays.asList("expand", "compact", "frame", "normalize",
                "flatten", "fromrdf", "tordf"));
    }

    private static boolean hasContext(String opt) {
        return "compact".equals(opt) || "frame".equals(opt) || "flatten".equals(opt);
    }

    private static Map getOutputFormats() {
        final Map outputFormats = new HashMap();

        for (final RDFFormat format : RDFParserRegistry.getInstance().getKeys()) {
            outputFormats.put(
                    format.getName().replaceAll("-", "").replaceAll("/", "").toLowerCase(), format);
        }

        return outputFormats;
    }

    private static String readFile(File in) throws IOException {
        final StringBuilder inobj = new StringBuilder(1024);
        try (BufferedReader buf = Files.newBufferedReader(in.toPath(), StandardCharsets.UTF_8)) {
            String line;
            while ((line = buf.readLine()) != null) {
                line = line.trim();
                inobj.append(line).append('\n');
            }
        }
        return inobj.toString();
    }

    private static class InsecureX509TrustManager extends X509ExtendedTrustManager
            implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] xcs, String string) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] xcs, String string)
                throws CertificateException {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket)
                throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket)
                throws CertificateException {
        }

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s,
                SSLEngine sslEngine) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s,
                SSLEngine sslEngine) throws CertificateException {
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy