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

net.jawr.web.config.JawrConfig Maven / Gradle / Ivy

Go to download

Javascript/CSS bundling and compressing tool for java web apps. By using jawr resources are automatically bundled together and optionally minified and gzipped. Jawr provides tag libraries to reference a generated bundle either by id or by using the name of any of its members.

The newest version!
/**
 * Copyright 2007-2016 Jordi Hernández Sellés, Ibrahim Chaehoi, Matt Ruby
 * 
 * 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.
 */
package net.jawr.web.config;

import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletContext;

import net.jawr.web.JawrConstant;
import net.jawr.web.context.ThreadLocalJawrContext;
import net.jawr.web.exception.BundlingProcessException;
import net.jawr.web.resource.bundle.factory.util.ClassLoaderResourceUtils;
import net.jawr.web.resource.bundle.factory.util.PathNormalizer;
import net.jawr.web.resource.bundle.factory.util.RegexUtil;
import net.jawr.web.resource.bundle.generator.GeneratorRegistry;
import net.jawr.web.resource.bundle.generator.variant.css.CssSkinVariantResolver;
import net.jawr.web.resource.bundle.hashcode.BundleHashcodeGenerator;
import net.jawr.web.resource.bundle.hashcode.BundleStringHashcodeGenerator;
import net.jawr.web.resource.bundle.hashcode.MD5BundleHashcodeGenerator;
import net.jawr.web.resource.bundle.locale.DefaultLocaleResolver;
import net.jawr.web.resource.bundle.locale.LocaleResolver;
import net.jawr.web.resource.bundle.locale.LocaleVariantResolverWrapper;
import net.jawr.web.resource.bundle.renderer.CSSHTMLBundleLinkRenderer;
import net.jawr.web.resource.bundle.variant.VariantResolver;
import net.jawr.web.resource.bundle.variant.resolver.BrowserResolver;
import net.jawr.web.resource.bundle.variant.resolver.ConnectionTypeResolver;
import net.jawr.web.servlet.util.MIMETypesSupport;
import net.jawr.web.util.StringUtils;

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

/**
 * This class holds configuration details for Jawr in a given ServletContext.
 * 
 * @author Jordi Hernández Sellés
 * @author Ibrahim Chaehoi
 * @author Matt Ruby
 */
public class JawrConfig implements Serializable {

	/** The serial version UID */
	private static final long serialVersionUID = -6243263853446050289L;

	/** The logger */
	private static final Logger LOGGER = LoggerFactory.getLogger(JawrConfig.class);

	/** The unauthorized resource extensions */
	private static final List UNAUTHORIZED_RESOURCE_EXTENSIONS = Arrays.asList("xml", "properties", "text");

	/**
	 * The jawr property placeholder patten ex : ${my_property.id}
	 */
	public static final Pattern JAWR_PROPERY_PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{([a-zA-Z0-9_\\.\\-]+)}");

	/**
	 * The property name for the css link flavor
	 */
	public static final String JAWR_CSSLINKS_FLAVOR = "jawr.csslinks.flavor";

	/**
	 * The property name for the locale resolver
	 */
	public static final String JAWR_LOCALE_RESOLVER = "jawr.locale.resolver";

	/**
	 * The property name for the browser resolver
	 */
	public static final String JAWR_BROWSER_RESOLVER = "jawr.browser.resolver";

	/**
	 * The property name for the css skin resolver
	 */
	public static final String JAWR_CSS_SKIN_RESOLVER = "jawr.css.skin.resolver";

	/**
	 * The property name for the connection type resolver
	 */
	public static final String JAWR_CONNECTION_TYPE_SCHEME_RESOLVER = "jawr.url.connection.type.resolver";

	/**
	 * The property name for the bundle hashcode generator
	 */
	public static final String JAWR_BUNDLE_HASHCODE_GENERATOR = "jawr.bundle.hashcode.generator";

	/**
	 * The property name for the dwr mapping
	 */
	public static final String JAWR_DWR_MAPPING = "jawr.dwr.mapping";

	/**
	 * The property name for the url context path used to override
	 */
	public static final String JAWR_URL_CONTEXTPATH_OVERRIDE = "jawr.url.contextpath.override";

	/**
	 * The property name for the url context path used to override SSL path
	 */
	public static final String JAWR_URL_CONTEXTPATH_SSL_OVERRIDE = "jawr.url.contextpath.ssl.override";

	/**
	 * The property name for the flag indicating if we should use or not the url
	 * context path override even in debug mode
	 */
	public static final String JAWR_USE_URL_CONTEXTPATH_OVERRIDE_IN_DEBUG_MODE = "jawr.url.contextpath.override.used.in.debug.mode";

	/**
	 * The property name for the Gzip IE6 flag
	 */
	public static final String JAWR_GZIP_IE6_ON = "jawr.gzip.ie6.on";

	/**
	 * The property name to force the CSS bundle in debug mode
	 */
	public static final String JAWR_DEBUG_IE_FORCE_CSS_BUNDLE = "jawr.debug.ie.force.css.bundle";

	/**
	 * The property name for the charset name
	 */
	public static final String JAWR_CHARSET_NAME = "jawr.charset.name";

	/**
	 * The property name for the Gzip flag
	 */
	public static final String JAWR_GZIP_ON = "jawr.gzip.on";

	/**
	 * The property name for the debug override key
	 */
	public static final String JAWR_DEBUG_OVERRIDE_KEY = "jawr.debug.overrideKey";

	/**
	 * The property name for the debug use random parameter
	 */
	public static final String JAWR_USE_RANDOM_PARAM = "jawr.debug.use.random.parameter";

	/**
	 * The property name for the reload refresh key
	 */
	private static final String JAWR_CONFIG_RELOAD_REFRESH_KEY = "jawr.config.reload.refreshKey";

	/**
	 * The property name for the Debug flag
	 */
	public static final String JAWR_DEBUG_ON = "jawr.debug.on";

	/**
	 * The property name for the jawr working directory. By default it's
	 * jawrTemp in the application server working directory associated to the
	 * application.
	 */
	public static final String JAWR_WORKING_DIRECTORY = "jawr.working.directory";

	/**
	 * The property name for the flag indicating if we should process the bundle
	 * at startup
	 */
	public static final String JAWR_USE_BUNDLE_MAPPING = "jawr.use.bundle.mapping";

	/**
	 * The property name for the flag indicating if we should use "smart
	 * bundling".
	 */
	public static final String JAWR_USE_SMART_BUNDLING = "jawr.use.smart.bundling";

	/**
	 * The property name for the flag indicating if we should use "generator
	 * cache".
	 */
	public static final String JAWR_USE_GENERATOR_CACHE = "jawr.use.generator.cache";

	/**
	 * The property name for the debug mode system flag
	 */
	private static final String DEBUG_MODE_SYSTEM_FLAG = "net.jawr.debug.on";

	/**
	 * The property name for the ClientSideHandlerGenerator class
	 */
	public static final String JAWR_JS_CLIENTSIDE_HANDLER = "jawr.js.clientside.handler.generator.class";

	/**
	 * The property name for the JS Bundle link renderer
	 */
	public static final String JAWR_JS_BUNDLE_LINK_RENDERER_CLASS = "jawr.js.bundle.link.renderer.class";

	/**
	 * The property name for the CSS Bundle link renderer
	 */
	public static final String JAWR_CSS_BUNDLE_LINK_RENDERER_CLASS = "jawr.css.bundle.link.renderer.class";

	/**
	 * The property name for the CSS Bundle link renderer
	 */
	public static final String JAWR_IMG_RENDERER_CLASS = "jawr.img.bundle.link.renderer.class";

	/**
	 * The property name for the flag indicating if the CSS image for the CSS
	 * retrieved from classpath must be also retrieved from classpath
	 */
	public static final String JAWR_CSS_CLASSPATH_HANDLE_IMAGE = "jawr.css.classpath.handle.image";

	/**
	 * The property name for the name of the cookie used to store the CSS skin
	 */
	public static final String JAWR_CSS_SKIN_COOKIE = "jawr.css.skin.cookie";

	/**
	 * The property name for the binary hash algorithm.
	 */
	public static final String JAWR_BINARY_HASH_ALGORITHM = "jawr.binary.hash.algorithm";

	/**
	 * The property name for the binary resources.
	 */
	public static final String JAWR_BINARY_RESOURCES = "jawr.binary.resources";

	/**
	 * The property name for the Jawr strict mode.
	 */
	public static final String JAWR_STRICT_MODE = "jawr.strict.mode";

	/**
	 * The property name for the jawr servlet context reader class name
	 */
	public static final String JAWR_SERVLET_CTX_READER_CLASS = "jawr.servlet.context.reader.class";

	/**
	 * The generator registry
	 */
	private GeneratorRegistry generatorRegistry;

	/**
	 * The local resolver
	 */
	private LocaleResolver localeResolver;

	/**
	 * The bundle hashcode generator
	 */
	private BundleHashcodeGenerator bundleHashcodeGenerator;

	/**
	 * The servlet context
	 */
	private ServletContext context;

	/**
	 * The root configuration properties
	 */
	private Properties configProperties;

	/**
	 * Name of the charset to use to interpret and send resources. Defaults to
	 * UTF-8
	 */
	private String charsetName = "UTF-8";

	/**
	 * The charset to use to interpret and send resources.
	 */
	private Charset resourceCharset;

	/**
	 * Flag to switch on the strict mode. defaults to false. In strict mode,
	 * Jawr checks that the hashcode of the bundle requested is the right one or
	 * not.
	 */
	private boolean strictMode = false;

	/**
	 * Flag to switch on the debug mode. defaults to false.
	 */
	private boolean debugModeOn = false;

	/**
	 * Flag to switch on the debug use random parameter. defaults to true.
	 */
	private boolean debugUseRandomParam = true;

	/**
	 * Key that may be passed in to override production mode
	 */
	private String debugOverrideKey = "";

	/**
	 * Key that may be passed in to reload the bundles on the fly
	 */
	private String refreshKey = "";

	/**
	 * Flag to switch on the gzipped resources mode. defaults to true.
	 */
	private boolean gzipResourcesModeOn = true;

	/**
	 * Flag to switch on the gzipped resources mode for internet explorer 6.
	 * defaults to true.
	 */
	private boolean gzipResourcesForIESixOn = true;

	/**
	 * Flag to switch on css resources bundle in debug mode. defaults to false.
	 */
	private boolean forceCssBundleInDebugForIEOn = false;

	/**
	 * Flag which defines if we should process use information of bundle mapping at server startup.
	 * This is used to speed up server start up.
	 * defaults to true.
	 */
	private boolean useBundleMapping = true;

	/**
	 * Flag which defines if we should use the smart bundling feature. defaults
	 * to true.
	 */
	private boolean useSmartBundling = true;

	/**
	 * Flag which defines if we should use the generator cache feature. defaults
	 * to true.
	 */
	private boolean useGeneratorCache = true;

	/**
	 * The delay after last event, this is used to to ensure that a batch
	 * modification is ended before starting the build
	 */
	private int delayAfterLastEvent = JawrConstant.DEFAULT_DELAY_AFTER_LAST_EVENT;

	/**
	 * The jawr working directory path
	 */
	private String jawrWorkingDirectory;

	/**
	 * Servlet mapping corresponding to this config. Defaults to an empty string
	 */
	private String servletMapping = "";

	/**
	 * The type of resources handled by this config
	 */
	private String resourceType;

	/**
	 * The allowed resource extensions
	 */
	private final List allowedExtensions = new ArrayList<>();

	/**
	 * Override value to use instead of the context path of the application in
	 * generated urls. If null, contextPath is used. If blank, urls are
	 * generated to be relative.
	 */
	private String contextPathOverride;

	/**
	 * Override value to use instead of the context path of the application in
	 * generated urls for SSL page. If null, contextPath is used. If blank, urls
	 * are generated to be relative.
	 */
	private String contextPathSslOverride;

	/** The client side handler generator class name */
	private String clientSideHandlerGeneratorClass;

	/**
	 * The flag indicating that we should use the overridden context path even
	 * in debug mode. The default value is false.
	 */
	private boolean useContextPathOverrideInDebugMode = false;

	/**
	 * Determines if the servlet, which provide CSS image for CSS define in the
	 * classpath should be used or not
	 */
	private boolean classpathCssHandleImage = false;

	/**
	 * Defines the image resources definition.
	 */
	private String binaryResourcesDefinition;

	/**
	 * Defines the image hash algorithm. By default the value is CRC32. There
	 * are only 2 algorithm available CRC32 and MD5.
	 */
	private String binaryHashAlgorithm = "CRC32";

	/**
	 * Used to check if a configuration has not been outdated by a new one.
	 */
	private boolean valid = true;

	/**
	 * Mapping path to the dwr servlet, in case it is integrated with jawr.
	 */
	private String dwrMapping;

	/** The skin cookie name */
	private String skinCookieName = JawrConstant.JAWR_SKIN;

	/** The servletContext reader class name */
	private String servletContextRsReaderClass;

	/** The JS Bundle link renderer class name */
	private String jsBundleLinkRenderClass;

	/** The CSS Bundle link renderer class name */
	private String cssBundleLinkRenderClass;

	/** The Image renderer class name */
	private String imgRenderClass;

	/**
	 * Initialize configuration using params contained in the initialization
	 * properties file.
	 * 
	 * @param resourceType
	 *            the resource type
	 * @param props
	 *            the properties
	 */
	public JawrConfig(final String resourceType, final Properties props) {
		this(resourceType, props, null);
	}
	
	/**
	 * Initialize configuration using params contained in the initialization
	 * properties file.
	 * 
	 * @param resourceType
	 *            the resource type
	 * @param props
	 *            the properties
	 * @param resolver
	 *            the property resolver
	 */
	public JawrConfig(final String resourceType, final Properties props, ConfigPropertyResolver resolver) {
		this.resourceType = resourceType;

		this.configProperties = props;

		if (resolver != null) {
			for (Entry entry : this.configProperties.entrySet()) {
				String value = (String) entry.getValue();
				Matcher matcher = JAWR_PROPERY_PLACEHOLDER_PATTERN.matcher(value);
				StringBuffer sb = new StringBuffer();
				boolean resolved = false;
				while (matcher.find()) {
					String resolvedValue = resolver.resolve(matcher.group(1));
					if (value == null) {
						resolvedValue = matcher.group(1);
						LOGGER.warn("The property '" + matcher.group(1)
								+ "' has not been resolved. Please make sure that your configuration is correct.");
					} else {
						resolved = true;
					}

					matcher.appendReplacement(sb, RegexUtil.adaptReplacementToMatcher(resolvedValue));
				}
				matcher.appendTail(sb);
				// Sets the new value
				if (resolved) {
					entry.setValue(sb.toString());
					if (LOGGER.isDebugEnabled()) {
						LOGGER.debug(
								"The property '" + entry.getKey() + "' has been resolved to : " + entry.getValue());
					}
				}
			}
		}

		this.debugModeOn = getBooleanProperty(JAWR_DEBUG_ON, false);

		// If system flag is available, override debug mode from properties
		if (null != System.getProperty(DEBUG_MODE_SYSTEM_FLAG)) {
			this.debugModeOn = Boolean.parseBoolean(System.getProperty(DEBUG_MODE_SYSTEM_FLAG));
		}

		this.debugOverrideKey = getProperty(JAWR_DEBUG_OVERRIDE_KEY, "");

		this.debugUseRandomParam = getBooleanProperty(JAWR_USE_RANDOM_PARAM, true);

		this.strictMode = getBooleanProperty(JAWR_STRICT_MODE, false);

		if (null != props.getProperty("jawr." + resourceType + ".allowed.extensions")) {
			String[] strExtensions = props.getProperty("jawr." + resourceType + ".allowed.extensions").split(",");
			for (String extension : strExtensions) {
				if (UNAUTHORIZED_RESOURCE_EXTENSIONS.contains(extension)) {
					LOGGER.warn("The extension '" + extension
							+ "' is an unauthorized extension. It will not be added to the allowed extension.");
				} else {
					this.allowedExtensions.add(extension);
				}
			}
		}

		if (resourceType.equals(JawrConstant.BINARY_TYPE)) {
			for (Object key : MIMETypesSupport.getSupportedProperties(this).keySet()) {
				if (!this.allowedExtensions.contains((String) key)) {
					this.allowedExtensions.add((String) key);
				}
			}
		} else {

			// Add the default resource extension : js or css
			if (!this.allowedExtensions.contains(resourceType)) {
				this.allowedExtensions.add(resourceType);
			}
		}

		this.useBundleMapping = getBooleanProperty(JAWR_USE_BUNDLE_MAPPING, false);

		this.useSmartBundling = getBooleanProperty(JAWR_USE_SMART_BUNDLING, false);

		if(this.useSmartBundling && !this.useBundleMapping){
			if(LOGGER.isInfoEnabled()){
				LOGGER.info("As the property '"+JAWR_USE_SMART_BUNDLING+"' is set to true, the '"+JAWR_USE_BUNDLE_MAPPING+"' property has been forced to true.");
			}
			this.useBundleMapping = true;
		}
		
		this.useGeneratorCache = getBooleanProperty(JAWR_USE_GENERATOR_CACHE, true);

		String value = getProperty(JawrConstant.JAWR_SMART_BUNDLING_DELAY_AFTER_LAST_EVENT);
		if (StringUtils.isNotEmpty(value)) {
			delayAfterLastEvent = Integer.parseInt(value) * 1000;
		}

		this.jawrWorkingDirectory = getProperty(JAWR_WORKING_DIRECTORY);

		this.gzipResourcesModeOn = getBooleanProperty(JAWR_GZIP_ON, true);

		setCharsetName(getProperty(JAWR_CHARSET_NAME, "UTF-8"));

		this.gzipResourcesForIESixOn = getBooleanProperty(JAWR_GZIP_IE6_ON, true);

		this.forceCssBundleInDebugForIEOn = getBooleanProperty(JAWR_DEBUG_IE_FORCE_CSS_BUNDLE, false);

		this.contextPathOverride = getProperty(JAWR_URL_CONTEXTPATH_OVERRIDE);

		this.contextPathSslOverride = getProperty(JAWR_URL_CONTEXTPATH_SSL_OVERRIDE);

		this.useContextPathOverrideInDebugMode = getBooleanProperty(JAWR_USE_URL_CONTEXTPATH_OVERRIDE_IN_DEBUG_MODE,
				false);

		this.refreshKey = getProperty(JAWR_CONFIG_RELOAD_REFRESH_KEY, "");

		this.dwrMapping = getProperty(JAWR_DWR_MAPPING);

		String localResolverClassName = getProperty(JAWR_LOCALE_RESOLVER, DefaultLocaleResolver.class.getName());
		localeResolver = (LocaleResolver) ClassLoaderResourceUtils.buildObjectInstance(localResolverClassName);

		String bundleHashCodeGenerator = props.getProperty(JAWR_BUNDLE_HASHCODE_GENERATOR, "").trim();
		if (bundleHashCodeGenerator.length() == 0 || JawrConstant.DEFAULT.equalsIgnoreCase(bundleHashCodeGenerator)) {
			bundleHashcodeGenerator = new BundleStringHashcodeGenerator();
		} else if (JawrConstant.MD5_ALGORITHM.equalsIgnoreCase(bundleHashCodeGenerator)) {
			bundleHashcodeGenerator = new MD5BundleHashcodeGenerator();
		} else {
			bundleHashcodeGenerator = (BundleHashcodeGenerator) ClassLoaderResourceUtils
					.buildObjectInstance(bundleHashCodeGenerator);
		}

		this.clientSideHandlerGeneratorClass = getProperty(JAWR_JS_CLIENTSIDE_HANDLER,
				JawrConstant.DEFAULT_JS_CLIENTSIDE_HANDLER_CLASS);

		this.jsBundleLinkRenderClass = getProperty(JAWR_JS_BUNDLE_LINK_RENDERER_CLASS,
				JawrConstant.DEFAULT_JS_BUNDLE_LINK_RENDERER_CLASS);

		this.cssBundleLinkRenderClass = getProperty(JAWR_CSS_BUNDLE_LINK_RENDERER_CLASS,
				JawrConstant.DEFAULT_CSS_BUNDLE_LINK_RENDERER_CLASS);

		this.imgRenderClass = getProperty(JAWR_IMG_RENDERER_CLASS, JawrConstant.DEFAULT_IMG_RENDERER_CLASS);

		this.servletContextRsReaderClass = getProperty(JAWR_SERVLET_CTX_READER_CLASS,
				JawrConstant.DEFAULT_SERVLET_CTX_RESOURCE_READER_CLASS);

		skinCookieName = getProperty(JAWR_CSS_SKIN_COOKIE, JawrConstant.JAWR_SKIN);

		String cssLinkFlavor = getProperty(JAWR_CSSLINKS_FLAVOR);
		if (null != cssLinkFlavor) {
			setCssLinkFlavor(cssLinkFlavor);
		}

		this.classpathCssHandleImage = getBooleanProperty(JAWR_CSS_CLASSPATH_HANDLE_IMAGE, false);

		this.binaryHashAlgorithm = getProperty(JAWR_BINARY_HASH_ALGORITHM, "CRC32");

		this.binaryResourcesDefinition = getProperty(JAWR_BINARY_RESOURCES);

		// TODO : remove the below section in the next major release
		if (StringUtils.isNotEmpty(getProperty("jawr.css.image.classpath.use.servlet"))) {
			throw new BundlingProcessException(
					"The property 'jawr.css.image.classpath.use.servlet' is not supported anymore, please use '"
							+ JAWR_CSS_CLASSPATH_HANDLE_IMAGE + "' instead.");
		}

		if (StringUtils.isNotEmpty(getProperty("jawr.css.image.classpath.use.servlet"))) {
			throw new BundlingProcessException(
					"The property 'jawr.css.image.classpath.use.servlet' is not supported anymore, please use '"
							+ JAWR_CSS_CLASSPATH_HANDLE_IMAGE + "' instead.");
		}

		if (StringUtils.isNotEmpty(getProperty("jawr.image.hash.algorithm"))) {
			throw new BundlingProcessException(
					"The property 'jawr.image.hash.algorithm' is not supported anymore, please use '"
							+ JAWR_BINARY_HASH_ALGORITHM + "' instead.");
		}

		if (StringUtils.isNotEmpty(getProperty("jawr.image.resources"))) {
			throw new BundlingProcessException(
					"The property 'jawr.image.resources' is not supported anymore, please use '" + JAWR_BINARY_RESOURCES
							+ "' instead.");
		}

	}

	/**
	 * Returns the client side hanlder generator class name
	 * 
	 * @return the client side hanlder generator class name
	 */
	public String getClientSideHandlerGeneratorClass() {
		return clientSideHandlerGeneratorClass;
	}

	/**
	 * Returns the resource type
	 * 
	 * @return the resource type
	 */
	public String getResourceType() {
		return resourceType;
	}

	/**
	 * Returns the allowed extensions
	 * 
	 * @return the allowed extensions
	 */
	public List getAllowedExtensions() {
		return allowedExtensions;
	}

	/**
	 * Returns the flag indicating if we are in strict mode or not
	 * 
	 * @return the strict mode flag
	 */
	public boolean isStrictMode() {
		return strictMode;
	}

	/**
	 * Sets the flag indicating if we are in strict mode or not
	 * 
	 * @param strictMode
	 *            the flag to set
	 */
	public void setStrictMode(boolean strictMode) {
		this.strictMode = strictMode;
	}

	/**
	 * Get the debugOverrideKey
	 * 
	 * @return the debugOverrideKey that is used to override production mode per
	 *         request
	 */
	public String getDebugOverrideKey() {
		return debugOverrideKey;
	}

	/**
	 * Set the debugOverrideKey
	 * 
	 * @param debugOverrideKey
	 *            the String to set as the key
	 */
	public void setDebugOverrideKey(final String debugOverrideKey) {
		this.debugOverrideKey = debugOverrideKey;
	}

	/**
	 * @return the debugUseRandomParam
	 */
	public boolean isDebugUseRandomParam() {
		return debugUseRandomParam;
	}

	/**
	 * @param debugUseRandomParam
	 *            the debugUseRandomParam to set
	 */
	public void setDebugUseRandomParam(boolean debugUseRandomParam) {
		this.debugUseRandomParam = debugUseRandomParam;
	}

	/**
	 * Get debug mode status. This flag may be overridden using the
	 * debugOverrideKey
	 * 
	 * @return the debug mode flag.
	 */
	public boolean isDebugModeOn() {
		if (!debugModeOn && ThreadLocalJawrContext.isDebugOverriden()) {
			return true;
		}
		return debugModeOn;
	}

	/**
	 * Set debug mode.
	 * 
	 * @param debugMode
	 *            the flag to set
	 */
	public void setDebugModeOn(final boolean debugMode) {
		this.debugModeOn = debugMode;
	}

	/**
	 * Returns the refresh key
	 * 
	 * @return the refresh key
	 */
	public String getRefreshKey() {
		return refreshKey;
	}

	/**
	 * Sets the refresh key
	 * 
	 * @param refreshKey
	 *            the refresh key
	 */
	public void setRefreshKey(final String refreshKey) {
		this.refreshKey = refreshKey;
	}

	/**
	 * Returns the jawr working directory
	 * 
	 * @return the jawr working directory
	 */
	public String getJawrWorkingDirectory() {
		return jawrWorkingDirectory;
	}

	/**
	 * Sets the flag indicating if we should process the bundle at startup
	 * 
	 * @param dirPath
	 *            the directory path to set
	 */
	public void setJawrWorkingDirectory(final String dirPath) {
		this.jawrWorkingDirectory = dirPath;
	}

	/**
	 * Returns the flag indicating if we should use "generator cache".
	 * 
	 * @return the flag indicating if we should use "generator cache".
	 */
	public boolean isUseGeneratorCache() {
		return useGeneratorCache;
	}

	/**
	 * Sets the flag indicating if we should use "generator cache".
	 * 
	 * @param useGeneratorCache
	 *            the flag to set
	 */
	public void setUseGeneratorCache(boolean useGeneratorCache) {
		this.useGeneratorCache = useGeneratorCache;
	}

	/**
	 * Returns the flag indicating if we should use "smart bundling".
	 * 
	 * @return the flag indicating if we should use "smart bundling".
	 */
	public boolean getUseSmartBundling() {
		return useSmartBundling;
	}

	/**
	 * Sets the flag indicating if we should use "smart bundling".
	 * 
	 * @param useSmartBundling
	 *            the flag to set
	 */
	public void setUseSmartBundling(boolean useSmartBundling) {
		this.useSmartBundling = useSmartBundling;
	}

	/**
	 * Returns the delay after the last event before performing a build
	 * 
	 * @return the delay after the last event before performing a build
	 */
	public int getSmartBundlingDelayAfterLastEvent() {
		return delayAfterLastEvent;
	}

	/**
	 * Returns the flag indicating if we should use the bundle mapping
	 * properties file.
	 * 
	 * @return the flag indicating if we should use the bundle mapping
	 *         properties file.
	 */
	public boolean getUseBundleMapping() {
		return useBundleMapping;
	}

	/**
	 * Sets the flag indicating if we should use the bundle mapping properties
	 * file.
	 * 
	 * @param useBundleMapping
	 *            the flag to set
	 */
	public void setUseBundleMapping(boolean useBundleMapping) {
		this.useBundleMapping = useBundleMapping;
	}

	/**
	 * Get the charset to interpret and generate resource.
	 * 
	 * @return the resource charset
	 */
	public Charset getResourceCharset() {
		if (null == resourceCharset) {
			resourceCharset = Charset.forName(charsetName);
		}
		return resourceCharset;
	}

	/**
	 * Set the charsetname to be used to interpret and generate resource.
	 * 
	 * @param charsetName
	 *            the charset name to set
	 */
	public final void setCharsetName(String charsetName) {
		if (!Charset.isSupported(charsetName))
			throw new IllegalArgumentException(
					"The specified charset [" + charsetName + "] is not supported by the jvm.");
		this.charsetName = charsetName;
	}

	/**
	 * Returns the bundle hashcode generator
	 * 
	 * @return the bundleHashcodeGenerator
	 */
	public BundleHashcodeGenerator getBundleHashcodeGenerator() {
		return bundleHashcodeGenerator;
	}

	/**
	 * Get the servlet mapping corresponding to this config.
	 * 
	 * @return the servlet mapping corresponding to this config.
	 */
	public String getServletMapping() {
		return servletMapping;
	}

	/**
	 * Set the servlet mapping corresponding to this config.
	 * 
	 * @param servletMapping
	 *            the servelt mapping to set
	 */
	public void setServletMapping(String servletMapping) {
		this.servletMapping = PathNormalizer.normalizePath(servletMapping);
	}

	/**
	 * Get the flag indicating if the resource must be gzipped or not
	 * 
	 * @return the flag indicating if the resource must be gzipped or not
	 */
	public boolean isGzipResourcesModeOn() {
		return gzipResourcesModeOn;
	}

	/**
	 * Sets the flag indicating if the resource must be gzipped or not
	 * 
	 * @param gzipResourcesModeOn
	 *            the flag to set
	 */
	public void setGzipResourcesModeOn(boolean gzipResourcesModeOn) {
		this.gzipResourcesModeOn = gzipResourcesModeOn;
	}

	/**
	 * Get the flag indicating if the resource must be gzipped for IE6 or less
	 * 
	 * @return the flag indicating if the resource must be gzipped for IE6 or
	 *         less
	 */
	public boolean isGzipResourcesForIESixOn() {
		return gzipResourcesForIESixOn;
	}

	/**
	 * Sets the flag indicating if the resource must be gzipped for IE6 or less
	 * 
	 * @param gzipResourcesForIESixOn
	 *            the flag to set.
	 */
	public void setGzipResourcesForIESixOn(boolean gzipResourcesForIESixOn) {
		this.gzipResourcesForIESixOn = gzipResourcesForIESixOn;
	}

	/**
	 * Returns the flag indicating if the CSS resources must be bundle for IE in
	 * debug mode
	 * 
	 * @return the flag indicating if the CSS resources must be bundle for IE in
	 *         debug mode
	 */
	public boolean isForceCssBundleInDebugForIEOn() {
		return forceCssBundleInDebugForIEOn;
	}

	/**
	 * Sets the flag indicating if the CSS resources must be bundle for IE in
	 * debug mode
	 * 
	 * @param forceBundleCssForIEOn
	 *            the flag to set
	 */
	public void setForceCssBundleInDebugForIEOn(boolean forceBundleCssForIEOn) {
		this.forceCssBundleInDebugForIEOn = forceBundleCssForIEOn;
	}

	/**
	 * Get the the string to use instead of the regular context path. If it is
	 * an empty string, urls will be relative to the path (i.e, not start with a
	 * slash).
	 * 
	 * @return The string to use instead of the regular context path.
	 */
	public String getContextPathOverride() {
		return contextPathOverride;
	}

	/**
	 * Set the string to use instead of the regular context path. If it is an
	 * empty string, urls will be relative to the path (i.e, not start with a
	 * slash).
	 * 
	 * @param contextPathOverride
	 *            The string to use instead of the regular context path.
	 */
	public void setContextPathOverride(String contextPathOverride) {
		this.contextPathOverride = contextPathOverride;
	}

	/**
	 * @return the contextPathSslOverride
	 */
	public String getContextPathSslOverride() {
		return contextPathSslOverride;
	}

	/**
	 * @param contextPathSslOverride
	 *            the contextPathSslOverride to set
	 */
	public void setContextPathSslOverride(String contextPathSslOverride) {
		this.contextPathSslOverride = contextPathSslOverride;
	}

	/**
	 * @return the useContextPathOverrideInDebugMode
	 */
	public boolean isUseContextPathOverrideInDebugMode() {
		return useContextPathOverrideInDebugMode;
	}

	/**
	 * @param useContextPathOverrideInDebugMode
	 *            the useContextPathOverrideInDebugMode to set
	 */
	public void setUseContextPathOverrideInDebugMode(boolean useContextPathOverrideInDebugMode) {
		this.useContextPathOverrideInDebugMode = useContextPathOverrideInDebugMode;
	}

	/**
	 * Returns the JS Bundle link render class name
	 * 
	 * @return the JS Bundle link render class name
	 */
	public String getJsBundleLinkRenderClass() {
		return jsBundleLinkRenderClass;
	}

	/**
	 * Sets the the JS Bundle link render class name
	 * 
	 * @param jsBundleLinkRenderClass
	 *            the class name to set
	 */
	public void setJsBundleLinkRenderClass(String jsBundleLinkRenderClass) {
		this.jsBundleLinkRenderClass = jsBundleLinkRenderClass;
	}

	/**
	 * Returns the CSS Bundle link render class name
	 * 
	 * @return the CSS Bundle link render class name
	 */
	public String getCssBundleLinkRenderClass() {
		return cssBundleLinkRenderClass;
	}

	/**
	 * Sets the CSS Bundle link render class name
	 * 
	 * @param cssBundleLinkRenderClass
	 *            the class name to set
	 */
	public void setCssBundleLinkRenderClass(String cssBundleLinkRenderClass) {
		this.cssBundleLinkRenderClass = cssBundleLinkRenderClass;
	}

	/**
	 * Returns the img renderer class name
	 * 
	 * @return the img renderer class name
	 */
	public String getImgRendererClass() {
		return imgRenderClass;
	}

	/**
	 * Sets the image render class name
	 * 
	 * @param imgRenderClass
	 *            the class name to set
	 */
	public void setImgRendererClass(String imgRenderClass) {
		this.imgRenderClass = imgRenderClass;
	}

	/**
	 * Returns the servlet context reader class name
	 * 
	 * @return the servlet context reader class name
	 */
	public String getServletContextResourceReaderClass() {
		return servletContextRsReaderClass;
	}

	/**
	 * Sets the servlet context reader class name
	 * 
	 * @param servletContextReaderClass
	 *            the class name to set
	 */
	public void setServletContextResourceReaderClass(String servletContextReaderClass) {
		this.servletContextRsReaderClass = servletContextReaderClass;
	}

	/**
	 * Returns true if the URL of the image defines in CSS loaded from
	 * classpath, should be overridden for the classpath CSS image servlet.
	 * 
	 * @return true if the image defines in CSS load from classpath, should be
	 *         overridden for the classpath CSS image servlet, false otherwise.
	 * 
	 *         So if you have a CSS define in a jar file at
	 *         'style/default/assets/myStyle.css, where you have the following
	 *         statement: background:transparent
	 *         url(../../img/bkrnd/header_1_sprite.gif) no-repeat 0 0; Becomes:
	 *         background:transparent
	 *         url(getCssImageServletPath()+style/default/
	 *         img/bkrnd/header_1_sprite.gif) no-repeat 0 0; And the CSS image
	 *         servlet will be in charge of loading the image from the
	 *         classpath.
	 */
	public boolean isCssClasspathImageHandledByClasspathCss() {
		return classpathCssHandleImage;
	}

	/**
	 * Set the flag indicating if the URL of the image defines in CSS loaded
	 * from classpath, should be overridden for the classpath CSS image servlet.
	 * 
	 * @param classpathCssHandleImage
	 *            the flag to set
	 * 
	 *            So if you have a CSS define in a jar file at
	 *            'style/default/assets/myStyle.css, where you have the
	 *            following statement: background:transparent
	 *            url(../../img/bkrnd/header_1_sprite.gif) no-repeat 0 0;
	 *            Becomes: background:transparent
	 *            url(getCssImageServletPath()+style
	 *            /default/img/bkrnd/header_1_sprite.gif) no-repeat 0 0; And the
	 *            CSS image servlet will be in charge of loading the image from
	 *            the classpath.
	 */
	public void setCssClasspathImageHandledByClasspathCss(boolean classpathCssHandleImage) {
		this.classpathCssHandleImage = classpathCssHandleImage;
	}

	/**
	 * Get the binary hash algorithm
	 * 
	 * @return the binary hash algorithm
	 */
	public String getBinaryHashAlgorithm() {
		return binaryHashAlgorithm;
	}

	/**
	 * Sets the binary hash algorithm
	 * 
	 * @param binaryHashAlgorithm
	 *            , the hash algorithm to set
	 */
	public void setBinaryHashAlgorithm(String binaryHashAlgorithm) {
		this.binaryHashAlgorithm = binaryHashAlgorithm;
	}

	/**
	 * Returns the binary resources definition.
	 * 
	 * @return the binary resources definition.
	 */
	public String getBinaryResourcesDefinition() {
		return binaryResourcesDefinition;
	}

	/**
	 * Sets the binary resources definition.
	 * 
	 * @param binaryResourcesDefinition
	 *            the binary resources definition to set
	 */
	public void setBinaryResourcesDefinition(String binaryResourcesDefinition) {
		this.binaryResourcesDefinition = binaryResourcesDefinition;
	}

	/**
	 * Invalidate this configuration. Used to signal objects that have a hold on
	 * this instance but cannot be explicitly notified when the configuration is
	 * reloaded.
	 */
	public void invalidate() {
		this.valid = false;
	}

	/**
	 * Get the flag indicating if the configuration has been invalidated.
	 * 
	 * @return the flag indicating if the configuration has been invalidated.
	 */
	public boolean isValid() {
		return this.valid;
	}

	/**
	 * Get the generator registry
	 * 
	 * @return the generator registry
	 */
	public GeneratorRegistry getGeneratorRegistry() {
		return generatorRegistry;
	}

	/**
	 * Set the generator registry
	 * 
	 * @param generatorRegistry
	 *            the generatorRegistry to set
	 */
	public void setGeneratorRegistry(GeneratorRegistry generatorRegistry) {
		this.generatorRegistry = generatorRegistry;
		this.generatorRegistry.setConfig(this);
		localeResolver = null;
		if (configProperties.getProperty(JAWR_LOCALE_RESOLVER) == null) {
			localeResolver = new DefaultLocaleResolver();
		} else {
			localeResolver = (LocaleResolver) ClassLoaderResourceUtils
					.buildObjectInstance(configProperties.getProperty(JAWR_LOCALE_RESOLVER));
		}

		this.generatorRegistry.registerVariantResolver(new LocaleVariantResolverWrapper(localeResolver));

		registerResolver(new BrowserResolver(), JAWR_BROWSER_RESOLVER);
		registerResolver(new ConnectionTypeResolver(), JAWR_CONNECTION_TYPE_SCHEME_RESOLVER);
		registerResolver(new CssSkinVariantResolver(), JAWR_CSS_SKIN_RESOLVER);
	}

	/**
	 * Register a resolver in the generator registry
	 * 
	 * @param defaultResolver
	 *            the default resolver
	 * @param configPropertyName
	 *            the configuration property whose the value define the resolver
	 *            class
	 * @return
	 */
	private VariantResolver registerResolver(VariantResolver defaultResolver, String configPropertyName) {
		VariantResolver resolver = null;
		if (configProperties.getProperty(configPropertyName) == null) {
			resolver = defaultResolver;
		} else {
			resolver = (VariantResolver) ClassLoaderResourceUtils
					.buildObjectInstance(configProperties.getProperty(configPropertyName));
		}

		this.generatorRegistry.registerVariantResolver(resolver);
		return resolver;
	}

	/**
	 * Get the local resolver
	 * 
	 * @return the local resolver.
	 */
	public LocaleResolver getLocaleResolver() {
		return localeResolver;
	}

	/**
	 * Get the servlet context
	 * 
	 * @return the servlet context
	 */
	public ServletContext getContext() {
		return context;
	}

	/**
	 * Set the servlet context
	 * 
	 * @param context
	 *            the context to set
	 */
	public void setContext(ServletContext context) {
		this.context = context;
	}

	/**
	 * Get the dwrMapping
	 * 
	 * @return the dwrMapping
	 */
	public String getDwrMapping() {
		return dwrMapping;
	}

	/**
	 * Set the dwr mapping
	 * 
	 * @param dwrMapping
	 *            the dwrMapping to set
	 */
	public void setDwrMapping(String dwrMapping) {
		this.dwrMapping = dwrMapping;
	}

	/**
	 * Get the config properties
	 * 
	 * @return the config properties
	 */
	public Properties getConfigProperties() {
		return configProperties;
	}

	/**
	 * Sets the css link flavor
	 * 
	 * @param cssLinkFlavor
	 *            the cssLinkFlavor to set
	 */
	public final void setCssLinkFlavor(String cssLinkFlavor) {
		if (CSSHTMLBundleLinkRenderer.FLAVORS_HTML.equalsIgnoreCase(cssLinkFlavor)
				|| CSSHTMLBundleLinkRenderer.FLAVORS_XHTML.equalsIgnoreCase(cssLinkFlavor)
				|| CSSHTMLBundleLinkRenderer.FLAVORS_XHTML_EXTENDED.equalsIgnoreCase(cssLinkFlavor))
			CSSHTMLBundleLinkRenderer.setClosingTag(cssLinkFlavor);
		else {
			throw new IllegalArgumentException("The value for the jawr.csslinks.flavor " + "property [" + cssLinkFlavor
					+ "] is invalid. " + "Please check the docs for valid values ");
		}
	}

	/**
	 * Returns the boolean property value
	 * 
	 * @param propertyName
	 *            the property name
	 * @param defaultValue
	 *            the default value
	 * @return the boolean property value
	 */
	public boolean getBooleanProperty(String propertyName, boolean defaultValue) {

		return Boolean.valueOf(getProperty(propertyName, Boolean.toString(defaultValue)));
	}

	/**
	 * Returns the value of the property associated to the key passed in
	 * parameter
	 * 
	 * @param key
	 *            the key of the property
	 * @return the value of the property
	 */
	public String getProperty(String key) {

		return getProperty(key, null);
	}

	/**
	 * Returns the value of the property associated to the key passed in
	 * parameter
	 * 
	 * @param key
	 *            the key of the property
	 * @param defaultValue
	 *            the default value
	 * @return the value of the property
	 */
	public String getProperty(String key, String defaultValue) {

		String property = configProperties.getProperty(key, defaultValue);
		if (property != null) {
			property = property.trim();
		}
		return property;
	}

	/**
	 * Returns true if the Jawr working directory is defined in the web
	 * application.
	 * 
	 * @return true if the Jawr working directory is defined in the web
	 *         application.
	 */
	public boolean isWorkingDirectoryInWebApp() {

		return useBundleMapping && StringUtils.isNotEmpty(jawrWorkingDirectory)
				&& !jawrWorkingDirectory.startsWith(JawrConstant.FILE_URI_PREFIX);
	}

	/**
	 * Returns the skin cookie name
	 * 
	 * @return the skinCookieName
	 */
	public String getSkinCookieName() {
		return skinCookieName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(65);
		sb.append("[JawrConfig:'charset name:'").append(this.charsetName).append("'\ndebugModeOn:'")
				.append(isDebugModeOn()).append("'\nservletMapping:'").append(getServletMapping()).append("' ]");
		return sb.toString();
	}

	/**
	 * Returns the name of JS engine to use
	 * 
	 * @return the name of JS engine to use
	 */
	public String getJavascriptEngineName() {
		return getProperty(JawrConstant.JS_ENGINE_PROPERTY, JawrConstant.DEFAULT_JS_ENGINE);
	}

	/**
	 * Returns the name of JS engine to use
	 * 
	 * @param defaultJsEnginePropName
	 *            the default JS engine property name
	 * @return the name of JS engine to use
	 */
	public String getJavascriptEngineName(String defaultJsEnginePropName) {

		String jsEngineName = null;
		if (StringUtils.isEmpty(defaultJsEnginePropName)) {
			jsEngineName = getJavascriptEngineName();
		} else {
			jsEngineName = getProperty(defaultJsEnginePropName);
			if (StringUtils.isEmpty(jsEngineName)) {
				jsEngineName = getJavascriptEngineName();
			}
		}

		return jsEngineName;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy