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

org.duelengine.duel.CDNLinkInterceptor Maven / Gradle / Ivy

package org.duelengine.duel;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CDNLinkInterceptor implements LinkInterceptor {

	private static final Logger log = LoggerFactory.getLogger(CDNLinkInterceptor.class);
	protected final boolean isDevMode;
	protected final String cdnHost;
	private final Map cdnMap;

	/**
	 * @param cdnHost the CDN server hostname (e.g., "cdn.example.com")
	 * @param cdnMap a mapping of paths to their compacted form (e.g., "/foo.js" => "/foo.min.js")
	 * @param isDevMode uses normal paths unless compacted form has a dev form (e.g., "/foo.js" => "/foo.min.js" => "/foo.test.js", else "/foo.js")
	 * @throws URISyntaxException
	 */
	public CDNLinkInterceptor(String cdnHost, ResourceBundle cdnBundle, boolean isDevMode)
			throws URISyntaxException {

		this(cdnHost, bundleAsMap(cdnBundle, isDevMode), isDevMode);
	}

	/**
	 * @param cdnHost the CDN server hostname (e.g., "cdn.example.com")
	 * @param cdnMap a mapping of paths to their compacted form (e.g., "/foo.js" => "/foo.min.js")
	 * @param isDevMode uses normal paths unless compacted form has a dev form (e.g., "/foo.js" => "/foo.min.js" => "/foo.test.js", else "/foo.js")
	 * @throws URISyntaxException
	 */
	public CDNLinkInterceptor(String cdnHost, Map cdnMap, boolean isDevMode)
			throws URISyntaxException {

		if (cdnMap == null) {
			cdnMap = Collections.emptyMap();
		}

		this.isDevMode = isDevMode;
		this.cdnMap = cdnMap;

		// use URI class to check for proper host syntax
		this.cdnHost = formatURL(cdnHost);

		log.info("cdnHost="+cdnHost);
		log.info("isDevMode="+isDevMode);
	}

	private static String formatURL(String path) {
		path = path == null ? "" : path.trim();
		if (path.isEmpty() || path.equals("/")) {
			return "";
		}

		if (!path.startsWith(".")) {
			try {
				int index = path.indexOf('/');
				if (index < 0) {
					path = new URI("http", path, null, null).getRawSchemeSpecificPart();
				} else {
					path = new URI("http", path.substring(0, index), path.substring(index), null).getRawSchemeSpecificPart();
				}
	
			} catch (URISyntaxException ex) {
				log.error(ex.getMessage(), ex);
			}

			if (!path.startsWith("/")) {
				path = "//"+path;
			}
		}

		if (path.endsWith("/")) {
			path = path.substring(0, path.length()-1);
		}

		return path;
	 }

	public String transformURL(String url) {
		// query and hash
		String suffix = "";
		int query = url.indexOf('?');
		if (query >= 0) {
			suffix += url.substring(query);
			url = url.substring(0, query);
		}
		int hash = url.indexOf('#');
		if (hash >= 0) {
			suffix += url.substring(hash);
			url = url.substring(0, hash);
		}

		if (!cdnMap.containsKey(url)) {
			return url + suffix;
		}

		// lookup CDN resource
		String cdnURL = cdnMap.get(url);

		if (isDevMode) {
			if (!cdnMap.containsKey(cdnURL)) {
				// scripts & stylesheets served directly
				return url + suffix;
			}

			// merge files serve generated placeholder
			cdnURL = cdnMap.get(cdnURL);
		}

		// CDN resources are compacted and optionally served from a different root
		return cdnHost + cdnURL + suffix;
	}

	/**
	 * Converts ResourceBundle to a Map
	 * @param cdnBundle
	 * @return
	 */
	protected static Map bundleAsMap(final ResourceBundle bundle, boolean isDevMode) {

		if (bundle == null) {
			return null;
		}
		
		if (!isDevMode) {
			// dump key-value pairs into simple map
			Set keys = bundle.keySet();
			Map map = new HashMap(keys.size());
			for (String key : keys) {
				map.put(key, bundle.getString(key));
			}
			return map;
		}

		// wrap bundle with an adaptor to allow dynamic reloading of bundle
		return new Map() {

			@Override
			public void clear() {}

			@Override
			public boolean containsKey(Object arg0) {
				return bundle.containsKey((String)arg0);
			}

			@Override
			public boolean containsValue(Object arg0) { return false; }

			@Override
			public Set> entrySet() { return null; }

			@Override
			public String get(Object arg0) {
				return (String)bundle.getObject((String)arg0);
			}

			@Override
			public boolean isEmpty() { return false; }

			@Override
			public Set keySet() { return null; }

			@Override
			public String put(String arg0, String arg1) { return null; }

			@Override
			public void putAll(Map arg0) {}

			@Override
			public String remove(Object arg0) { return null; }

			@Override
			public int size() { return 0; }

			@Override
			public Collection values() { return null; }
		};
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy