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

org.fujion.webjar.WebJar Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * #%L
 * fujion
 * %%
 * Copyright (C) 2008 - 2017 Regenstrief Institute, Inc.
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * #L%
 */
package org.fujion.webjar;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;

import org.fujion.common.MiscUtil;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;

/**
 * Information describing a single web jar resource.
 */
public class WebJar {

    private static final String[] EXTENSIONS = { "", ".js", ".css" };

    private final Resource resource;

    private final String name;
    
    private final String version;
    
    private final String absolutePath;

    private ObjectNode config;

    public WebJar(Resource resource) {
        try {
            this.resource = resource;
            absolutePath = resource.getURL().toString();
            int i = absolutePath.lastIndexOf("/webjars/") + 9;
            int j = absolutePath.indexOf("/", i);
            name = absolutePath.substring(i, j);
            i = absolutePath.indexOf("/", j + 1);
            version = absolutePath.substring(j + 1, i);
        } catch (IOException e) {
            throw MiscUtil.toUnchecked(e);
        }
    }
    
    /**
     * Returns the configuration for this webjar, after normalization.
     *
     * @return The normalized configuration.
     */
    protected ObjectNode getConfig() {
        if (config != null) {
            normalizePaths();
            normalizePackages();
        }
        
        return config;
    }
    
    /**
     * Sets the configuration for this web jar.
     *
     * @param config The root node of the configuration.
     */
    protected void setConfig(ObjectNode config) {
        this.config = config;
    }

    /**
     * Returns the absolute path of this web jar.
     *
     * @return The absolute path.
     */
    public String getAbsolutePath() {
        return absolutePath;
    }

    /**
     * Returns the relative root path of this web jar.
     *
     * @return The relative root path.
     */
    public String getRootPath() {
        return "webjars/" + name + "/";
    }
    
    /**
     * Returns the unique name for this web jar.
     *
     * @return The unique name.
     */
    public String getName() {
        return name;
    }
    
    /**
     * Returns the version of this web jar.
     *
     * @return The version.
     */
    public String getVersion() {
        return version;
    }

    /**
     * Returns a resource given its relative path.
     *
     * @param relativePath The relative path.
     * @return Resource corresponding to the relative path.
     */
    public Resource createRelative(String relativePath) {
        try {
            return resource.createRelative(relativePath);
        } catch (IOException e) {
            throw MiscUtil.toUnchecked(e);
        }
    }
    
    /**
     * Finds the first web jar resource that matches one of the specified file extensions.
     *
     * @param resourceLoader The resource loader that will perform the search.
     * @param extensions The file extensions to match.
     * @return The first matching resource encountered, or null if none found.
     */
    public Resource findResource(ResourcePatternResolver resourceLoader, String... extensions) {
        try {
            String path = getRootPath();
            
            for (String extension : extensions) {
                Resource[] resources = resourceLoader.getResources(path + "**/*." + extension);
                
                if (resources.length > 0) {
                    return resources[0];
                }
            }
        } catch (Exception e) {}
        
        return null;
    }

    @Override
    public String toString() {
        return "webjar:" + name + ":" + version;
    }

    /**
     * Add root path to the map and path entries of the parsed requirejs config.
     */
    private void normalizePaths() {
        normalizePaths("paths");
        normalizePaths("map");
    }

    /**
     * Add root path to the map and path entries of the parsed requirejs config.
     *
     * @param node One of: "paths", "map"
     */
    private void normalizePaths(String node) {
        ObjectNode paths = (ObjectNode) config.get(node);

        if (paths != null) {
            Iterator> iter = paths.fields();

            while (iter.hasNext()) {
                Entry entry = iter.next();
                JsonNode child = entry.getValue();

                if (child.isTextual()) {
                    String value = child.asText();
                    
                    if (!value.contains("webjars/")) {
                        entry.setValue(createPathNode(value));
                    }
                }
            }
        }
    }

    /**
     * Fix any package entries found in the config.
     */
    private void normalizePackages() {
        JsonNode packages = config.get("packages");

        if (packages != null) {
            if (packages.isArray()) {
                config.remove("packages");
                ObjectNode pkgs = config.objectNode();
                config.set("packages", pkgs);
                
                for (int i = 0; i < packages.size(); i++) {
                    fixPackage(packages.get(i), pkgs);
                }
            }
        }
    }

    /**
     * Fix a package entry, if necessary.
     *
     * @param entry The package entry.
     * @param pkgs The packages node to receive the parsed package.
     */
    private void fixPackage(JsonNode entry, ObjectNode pkgs) {
        String name;
        String main = null;
        ObjectNode pkg = pkgs.objectNode();
        
        if (entry.isTextual()) {
            name = entry.asText();
            main = "main";
        } else {
            JsonNode mainNode = entry.get("main");
            main = mainNode == null ? null : mainNode.asText();
            JsonNode nameNode = entry.get("name");
            name = nameNode == null ? null : nameNode.asText();
        }

        if (name != null) {
            pkg.set("main", new TextNode(main == null ? "main" : main));
            pkg.set("defaultExtension", new TextNode("js"));
            pkgs.set(name, pkg);
            getOrCreateMapNode().set(name, createPathNode(""));
        }
    }

    /**
     * Returns the map node for the configuration, creating one if it does not exist.
     *
     * @return The map node.
     */
    private ObjectNode getOrCreateMapNode() {
        ObjectNode map = (ObjectNode) config.get("map");
        
        if (map == null) {
            config.set("map", map = config.objectNode());
        }
        
        return map;
    }
    
    /**
     * Creates a path node.
     *
     * @param file The name of the file referenced in this path node.
     * @return The new path node.
     */
    private TextNode createPathNode(String file) {
        for (String ext : EXTENSIONS) {
            Resource resource = createRelative(file + ext);

            if (resource.exists() && resource.isReadable()) {
                file += ext;
                break;
            }
        }

        return new TextNode(getRootPath() + file);
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy