001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.settings;
018
019import java.time.Duration;
020import java.util.ArrayList;
021import java.util.Comparator;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.wicket.Application;
026import org.apache.wicket.Component;
027import org.apache.wicket.IResourceFactory;
028import org.apache.wicket.Localizer;
029import org.apache.wicket.core.util.resource.locator.IResourceStreamLocator;
030import org.apache.wicket.core.util.resource.locator.ResourceStreamLocator;
031import org.apache.wicket.core.util.resource.locator.caching.CachingResourceStreamLocator;
032import org.apache.wicket.css.ICssCompressor;
033import org.apache.wicket.javascript.IJavaScriptCompressor;
034import org.apache.wicket.markup.head.PriorityFirstComparator;
035import org.apache.wicket.markup.head.ResourceAggregator.RecordedHeaderItem;
036import org.apache.wicket.markup.html.IPackageResourceGuard;
037import org.apache.wicket.markup.html.SecurePackageResourceGuard;
038import org.apache.wicket.request.http.WebResponse;
039import org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy;
040import org.apache.wicket.request.resource.caching.IResourceCachingStrategy;
041import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy;
042import org.apache.wicket.request.resource.caching.version.CachingResourceVersion;
043import org.apache.wicket.request.resource.caching.version.IResourceVersion;
044import org.apache.wicket.request.resource.caching.version.LastModifiedResourceVersion;
045import org.apache.wicket.request.resource.caching.version.MessageDigestResourceVersion;
046import org.apache.wicket.request.resource.caching.version.RequestCycleCachedResourceVersion;
047import org.apache.wicket.resource.IPropertiesFactoryContext;
048import org.apache.wicket.resource.PropertiesFactory;
049import org.apache.wicket.resource.loader.ClassStringResourceLoader;
050import org.apache.wicket.resource.loader.ComponentStringResourceLoader;
051import org.apache.wicket.resource.loader.IStringResourceLoader;
052import org.apache.wicket.resource.loader.InitializerStringResourceLoader;
053import org.apache.wicket.resource.loader.PackageStringResourceLoader;
054import org.apache.wicket.resource.loader.ValidatorStringResourceLoader;
055import org.apache.wicket.util.file.IFileCleaner;
056import org.apache.wicket.util.file.IResourceFinder;
057import org.apache.wicket.util.lang.Args;
058import org.apache.wicket.util.lang.Generics;
059import org.apache.wicket.util.resource.IResourceStream;
060import org.apache.wicket.util.watch.IModificationWatcher;
061import org.apache.wicket.util.watch.ModificationWatcher;
062
063/**
064 * Class for resource related settings
065 * <p>
066 * <i>resourcePollFrequency </i> (defaults to no polling frequency) - Frequency at which resources
067 * should be polled for changes.
068 * <p>
069 * <i>resourceFinders</i> - Add/modify this to alter the search path for resources.
070 * <p>
071 * <i>useDefaultOnMissingResource </i> (defaults to true) - Set to true to return a default value if
072 * available when a required string resource is not found. If set to false then the
073 * throwExceptionOnMissingResource flag is used to determine how to behave. If no default is
074 * available then this is the same as if this flag were false
075 * <p>
076 * <i>A ResourceStreamLocator </i>- An Application's ResourceStreamLocator is used to find resources
077 * such as images or markup files. You can supply your own ResourceStreamLocator if your prefer to
078 * store your application's resources in a non-standard location (such as a different filesystem
079 * location, a particular JAR file or even a database) by overriding the getResourceLocator()
080 * method.
081 * <p>
082 * <i>Resource Factories </i>- Resource factories can be used to create resources dynamically from
083 * specially formatted HTML tag attribute values. For more details, see {@link IResourceFactory},
084 * {@link org.apache.wicket.markup.html.image.resource.DefaultButtonImageResourceFactory} and
085 * especially {@link org.apache.wicket.markup.html.image.resource.LocalizedImageResource}.
086 * <p>
087 * <i>A Localizer </i> The getLocalizer() method returns an object encapsulating all of the
088 * functionality required to access localized resources. For many localization problems, even this
089 * will not be required, as there are convenience methods available to all components:
090 * {@link org.apache.wicket.Component#getString(String key)} and
091 * {@link org.apache.wicket.Component#getString(String key, org.apache.wicket.model.IModel model)}.
092 * <p>
093 * <i>stringResourceLoaders </i>- A chain of <code>IStringResourceLoader</code> instances that are
094 * searched in order to obtain string resources used during localization. By default the chain is
095 * set up to first search for resources against a particular component (e.g. page etc.) and then
096 * against the application.
097 * </p>
098 *
099 * @author Jonathan Locke
100 * @author Chris Turner
101 * @author Eelco Hillenius
102 * @author Juergen Donnerstag
103 * @author Johan Compagner
104 * @author Igor Vaynberg (ivaynberg)
105 * @author Martijn Dashorst
106 * @author James Carman
107 */
108public class ResourceSettings implements IPropertiesFactoryContext
109{
110        /** I18N support */
111        private Localizer localizer;
112
113        /** Map to look up resource factories by name */
114        private final Map<String, IResourceFactory> nameToResourceFactory = Generics.newHashMap();
115
116        /** The package resource guard. */
117        private IPackageResourceGuard packageResourceGuard = new SecurePackageResourceGuard(
118                new SecurePackageResourceGuard.SimpleCache(100));
119
120        /** The factory to be used for the property files */
121        private org.apache.wicket.resource.IPropertiesFactory propertiesFactory;
122
123        /** Filesystem Path to search for resources */
124        private List<IResourceFinder> resourceFinders = new ArrayList<>();
125
126        /** Frequency at which files should be polled */
127        private Duration resourcePollFrequency = null;
128
129        /** resource locator for this application */
130        private IResourceStreamLocator resourceStreamLocator;
131
132        /** ModificationWatcher to watch for changes in markup files */
133        private IModificationWatcher resourceWatcher;
134
135        /**
136         * A cleaner that removes files asynchronously.
137         * <p>
138         * Used internally to remove the temporary files created by FileUpload functionality.
139         */
140        private IFileCleaner fileCleaner;
141
142        /** Chain of string resource loaders to use */
143        private final List<IStringResourceLoader> stringResourceLoaders = Generics.newArrayList(6);
144
145        /** Flags used to determine how to behave if resources are not found */
146        private boolean throwExceptionOnMissingResource = true;
147
148        /** Determines behavior of string resource loading if string is missing */
149        private boolean useDefaultOnMissingResource = true;
150
151        /** Default cache duration */
152        private Duration defaultCacheDuration = WebResponse.MAX_CACHE_DURATION;
153
154        /** The JavaScript compressor */
155        private IJavaScriptCompressor javascriptCompressor;
156
157        /** The Css compressor */
158        private ICssCompressor cssCompressor;
159
160        /** escape string for '..' within resource keys */
161        private String parentFolderPlaceholder = "::";
162
163        // resource caching strategy
164        private IResourceCachingStrategy resourceCachingStrategy;
165
166        // application these settings are bound to
167        private final Application application;
168
169        private boolean useMinifiedResources = true;
170
171        private Comparator<? super RecordedHeaderItem> headerItemComparator = new PriorityFirstComparator(
172                false);
173
174        private boolean encodeJSessionId = false;
175        
176        /**
177         * Configures Wicket's default ResourceLoaders.<br>
178         * For an example in {@code FooApplication} let {@code bar.Foo} extend {@link Component}, this
179         * results in the following ordering:
180         * <dl>
181         * <dt>component specific</dt>
182         * <dd>
183         * <ul>
184         * <li>bar/Foo.properties</li>
185         * <li>org/apache/wicket/Component.properties</li>
186         * </ul>
187         * </dd>
188         * <dt>package specific</dt>
189         * <dd>
190         * <ul>
191         * <li>bar/package.properties</li>
192         * <li>package.properties (on Foo's class loader)</li>
193         * <li>org/apache/wicket/package.properties</li>
194         * <li>org/apache/package.properties</li>
195         * <li>org/package.properties</li>
196         * <li>package.properties (on Component's class loader)</li>
197         * </ul>
198         * </dd>
199         * <dt>application specific</dt>
200         * <dd>
201         * <ul>
202         * <li>FooApplication.properties</li>
203         * <li>Application.properties</li>
204         * </ul>
205         * </dd>
206         * <dt>validator specific</dt>
207         * <dt>Initializer specific</dt>
208         * <dd>
209         * <ul>
210         * <li>bar.Foo.properties (Foo implementing IInitializer)</li>
211         * </ul>
212         * </dd>
213         * </dl>
214         * 
215         * @param application
216         */
217        public ResourceSettings(final Application application)
218        {
219                this.application = application;
220                stringResourceLoaders.add(new ComponentStringResourceLoader());
221                stringResourceLoaders.add(new PackageStringResourceLoader());
222                stringResourceLoaders.add(new ClassStringResourceLoader(application.getClass()));
223                stringResourceLoaders.add(new ValidatorStringResourceLoader());
224                stringResourceLoaders.add(new InitializerStringResourceLoader(application.getInitializers()));
225        }
226
227        /**
228         * Adds a resource factory to the list of factories to consult when generating resources
229         * automatically
230         *
231         * @param name
232         *            The name to give to the factory
233         * @param resourceFactory
234         *            The resource factory to add
235         * @return {@code this} object for chaining
236         */
237        public ResourceSettings addResourceFactory(final String name, IResourceFactory resourceFactory)
238        {
239                nameToResourceFactory.put(name, resourceFactory);
240                return this;
241        }
242
243        @Override
244        public Localizer getLocalizer()
245        {
246                if (localizer == null)
247                {
248                        localizer = new Localizer();
249                }
250                return localizer;
251        }
252
253        /**
254         * Gets the {@link org.apache.wicket.markup.html.PackageResourceGuard package resource guard}.
255         *
256         * @return The package resource guard
257         */
258        public IPackageResourceGuard getPackageResourceGuard()
259        {
260                return packageResourceGuard;
261        }
262
263        /**
264         * Get the property factory which will be used to load property files
265         *
266         * @return PropertiesFactory
267         */
268        public org.apache.wicket.resource.IPropertiesFactory getPropertiesFactory()
269        {
270                if (propertiesFactory == null)
271                {
272                        propertiesFactory = new PropertiesFactory(this);
273                }
274                return propertiesFactory;
275        }
276
277        /**
278         * @param name
279         *            Name of the factory to get
280         * @return The IResourceFactory with the given name.
281         */
282        public IResourceFactory getResourceFactory(final String name)
283        {
284                return nameToResourceFactory.get(name);
285        }
286
287        /**
288         * Gets the resource finders to use when searching for resources. By default, a finder that
289         * looks in the classpath root is configured. {@link org.apache.wicket.protocol.http.WebApplication} adds the classpath
290         * directory META-INF/resources. To configure additional search paths or filesystem paths, add
291         * to this list.
292         *
293         * @return Returns the resourceFinders.
294         */
295        public List<IResourceFinder> getResourceFinders()
296        {
297                return resourceFinders;
298        }
299
300        /**
301         * @return Returns the resourcePollFrequency.
302         */
303        public Duration getResourcePollFrequency()
304        {
305                return resourcePollFrequency;
306        }
307
308        @Override
309        public IResourceStreamLocator getResourceStreamLocator()
310        {
311                if (resourceStreamLocator == null)
312                {
313                        // Create compound resource locator using source path from
314                        // application settings
315                        resourceStreamLocator = new ResourceStreamLocator(getResourceFinders());
316                        resourceStreamLocator = new CachingResourceStreamLocator(resourceStreamLocator);
317                }
318                return resourceStreamLocator;
319        }
320
321        @Override
322        public IModificationWatcher getResourceWatcher(boolean start)
323        {
324                if (resourceWatcher == null && start)
325                {
326                        synchronized (this)
327                        {
328                                if (resourceWatcher == null)
329                                {
330                                        final Duration pollFrequency = getResourcePollFrequency();
331                                        if (pollFrequency != null)
332                                        {
333                                                resourceWatcher = new ModificationWatcher(pollFrequency);
334                                        }
335                                }
336                        }
337                }
338                return resourceWatcher;
339        }
340
341        /**
342         * Sets the resource watcher
343         *
344         * @param watcher
345         * @return {@code this} object for chaining
346         */
347        public ResourceSettings setResourceWatcher(IModificationWatcher watcher)
348        {
349                resourceWatcher = watcher;
350                return this;
351        }
352
353        /**
354         * @return the a cleaner which can be used to remove files asynchronously.
355         */
356        public IFileCleaner getFileCleaner()
357        {
358                return fileCleaner;
359        }
360
361        /**
362         * Sets a cleaner that can be used to remove files asynchronously.
363         * <p>
364         * Used internally to delete the temporary files created by FileUpload functionality
365         *
366         * @param fileUploadCleaner
367         *            the actual cleaner implementation. Can be <code>null</code>
368         * @return {@code this} object for chaining
369         */
370        public ResourceSettings setFileCleaner(IFileCleaner fileUploadCleaner)
371        {
372                fileCleaner = fileUploadCleaner;
373                return this;
374        }
375
376        /**
377         * @return mutable list of all available string resource loaders
378         */
379        public List<IStringResourceLoader> getStringResourceLoaders()
380        {
381                return stringResourceLoaders;
382        }
383
384        public boolean getThrowExceptionOnMissingResource()
385        {
386                return throwExceptionOnMissingResource;
387        }
388
389        /**
390         * @return Whether to use a default value (if available) when a missing resource is requested
391         */
392        public boolean getUseDefaultOnMissingResource()
393        {
394                return useDefaultOnMissingResource;
395        }
396
397        /**
398         * Sets the localizer which will be used to find property values.
399         *
400         * @param localizer
401         * @since 1.3.0
402         * @return {@code this} object for chaining
403         */
404        public ResourceSettings setLocalizer(final Localizer localizer)
405        {
406                this.localizer = localizer;
407                return this;
408        }
409
410        /**
411         * Sets the {@link org.apache.wicket.markup.html.PackageResourceGuard package resource guard}.
412         *
413         * @param packageResourceGuard
414         *            The package resource guard
415         * @return {@code this} object for chaining
416         */
417        public ResourceSettings setPackageResourceGuard(IPackageResourceGuard packageResourceGuard)
418        {
419                this.packageResourceGuard = Args.notNull(packageResourceGuard, "packageResourceGuard");
420                return this;
421        }
422
423        /**
424         * Set the property factory which will be used to load property files
425         *
426         * @param factory
427         * @return {@code this} object for chaining
428         */
429        public ResourceSettings setPropertiesFactory(org.apache.wicket.resource.IPropertiesFactory factory)
430        {
431                propertiesFactory = factory;
432                return this;
433        }
434
435        /**
436         * Sets the finders to use when searching for resources. By default, the resources are located
437         * on the classpath. To add additional search paths, add to the list given by
438         * {@link #getResourceFinders()}. Use this method if you want to completely exchange the list of
439         * resource finders.
440         *
441         * @param resourceFinders
442         *            The resourceFinders to set
443         * @return {@code this} object for chaining
444         */
445        public ResourceSettings setResourceFinders(final List<IResourceFinder> resourceFinders)
446        {
447                Args.notNull(resourceFinders, "resourceFinders");
448                this.resourceFinders = resourceFinders;
449
450                // Cause resource locator to get recreated
451                resourceStreamLocator = null;
452                return this;
453        }
454
455        /**
456         * Sets the resource polling frequency. This is the duration of time between checks of resource
457         * modification times. If a resource, such as an HTML file, has changed, it will be reloaded.
458         * The default is one second in 'development' mode and 'never' in deployment mode.
459         *
460         * @param resourcePollFrequency
461         *            Frequency at which to poll resources or <code>null</code> if polling should be
462         *            disabled
463         * @return {@code this} object for chaining
464         */
465        public ResourceSettings setResourcePollFrequency(final Duration resourcePollFrequency)
466        {
467                this.resourcePollFrequency = resourcePollFrequency;
468                return this;
469        }
470
471        /**
472         * /**
473         * Sets the resource stream locator for this application
474         *
475         * Consider wrapping <code>resourceStreamLocator</code> in {@link CachingResourceStreamLocator}.
476         * This way the locator will not be asked more than once for {@link IResourceStream}s which do
477         * not exist.
478         * @param resourceStreamLocator
479         *            new resource stream locator
480         *
481         * @see #getResourceStreamLocator()
482         * @return {@code this} object for chaining
483         */
484        public ResourceSettings setResourceStreamLocator(IResourceStreamLocator resourceStreamLocator)
485        {
486                this.resourceStreamLocator = resourceStreamLocator;
487                return this;
488        }
489
490        /**
491         * @param throwExceptionOnMissingResource
492         * @return {@code this} object for chaining
493         */
494        public ResourceSettings setThrowExceptionOnMissingResource(final boolean throwExceptionOnMissingResource)
495        {
496                this.throwExceptionOnMissingResource = throwExceptionOnMissingResource;
497                return this;
498        }
499
500        /**
501         * @param useDefaultOnMissingResource
502         *            Whether to use a default value (if available) when a missing resource is requested
503         * @return {@code this} object for chaining
504         */
505        public ResourceSettings setUseDefaultOnMissingResource(final boolean useDefaultOnMissingResource)
506        {
507                this.useDefaultOnMissingResource = useDefaultOnMissingResource;
508                return this;
509        }
510
511        /**
512         * Get the the default cache duration for resources.
513         * <p/>
514         *
515         * @return cache duration (Duration.NONE will be returned if caching is disabled)
516         *
517         * @see org.apache.wicket.util.time.Duration#NONE
518         */
519        public final Duration getDefaultCacheDuration()
520        {
521                return defaultCacheDuration;
522        }
523
524        /**
525         * Set the the default cache duration for resources.
526         * <p/>
527         * Based on RFC-2616 this should not exceed one year. If you set Duration.NONE caching will be
528         * disabled.
529         *
530         * @param duration
531         *            default cache duration in seconds
532         *
533         * @see org.apache.wicket.util.time.Duration#NONE
534         * @see org.apache.wicket.request.http.WebResponse#MAX_CACHE_DURATION
535         * @return {@code this} object for chaining
536         */
537        public final ResourceSettings setDefaultCacheDuration(Duration duration)
538        {
539                Args.notNull(duration, "duration");
540                defaultCacheDuration = duration;
541                return this;
542        }
543
544        /**
545         * Get the javascript compressor to remove comments and whitespace characters from javascripts
546         *
547         * @return whether the comments and whitespace characters will be stripped from resources served
548         *         through {@link org.apache.wicket.request.resource.JavaScriptPackageResource
549         *         JavaScriptPackageResource}. Null is a valid value.
550         */
551        public IJavaScriptCompressor getJavaScriptCompressor()
552        {
553                return javascriptCompressor;
554        }
555
556        /**
557         * Set the javascript compressor implemententation use e.g. by
558         * {@link org.apache.wicket.request.resource.JavaScriptPackageResource
559         * JavaScriptPackageResource}. A typical implementation will remove comments and whitespace. But
560         * a no-op implementation is available as well.
561         *
562         * @param compressor
563         *            The implementation to be used
564         * @return The old value
565         */
566        public IJavaScriptCompressor setJavaScriptCompressor(IJavaScriptCompressor compressor)
567        {
568                IJavaScriptCompressor old = javascriptCompressor;
569                javascriptCompressor = compressor;
570                return old;
571        }
572
573        /**
574         * Get the CSS compressor to remove comments and whitespace characters from css resources
575         *
576         * @return whether the comments and whitespace characters will be stripped from resources served
577         *         through {@link org.apache.wicket.request.resource.CssPackageResource
578         *         CssPackageResource}. Null is a valid value.
579         */
580        public ICssCompressor getCssCompressor()
581        {
582                return cssCompressor;
583        }
584
585        /**
586         * Set the CSS compressor implemententation use e.g. by
587         * {@link org.apache.wicket.request.resource.CssPackageResource CssPackageResource}. A typical
588         * implementation will remove comments and whitespace. But a no-op implementation is available
589         * as well.
590         *
591         * @param compressor
592         *            The implementation to be used
593         * @return The old value
594         */
595        public ICssCompressor setCssCompressor(ICssCompressor compressor)
596        {
597                ICssCompressor old = cssCompressor;
598                cssCompressor = compressor;
599                return old;
600        }
601
602        /**
603         * Placeholder string for '..' within resource urls (which will be crippled by the browser and
604         * not work anymore). Note that by default the placeholder string is <code>::</code>. Resources
605         * are protected by a {@link org.apache.wicket.markup.html.IPackageResourceGuard
606         * IPackageResourceGuard} implementation such as
607         * {@link org.apache.wicket.markup.html.PackageResourceGuard} which you may use or extend based
608         * on your needs.
609         *
610         * @return placeholder
611         */
612        public String getParentFolderPlaceholder()
613        {
614                return parentFolderPlaceholder;
615        }
616
617        /**
618         * Placeholder string for '..' within resource urls (which will be crippled by the browser and
619         * not work anymore). Note that by default the placeholder string is <code>null</code> and thus
620         * will not allow to access parent folders. That is by purpose and for security reasons (see
621         * Wicket-1992). In case you really need it, a good value for placeholder would e.g. be "$up$".
622         * Resources additionally are protected by a
623         * {@link org.apache.wicket.markup.html.IPackageResourceGuard IPackageResourceGuard}
624         * implementation such as {@link org.apache.wicket.markup.html.PackageResourceGuard} which you
625         * may use or extend based on your needs.
626         *
627         * @see #getParentFolderPlaceholder()
628         *
629         * @param sequence
630         *            character sequence which must not be ambiguous within urls
631         * @return {@code this} object for chaining
632         */
633        public ResourceSettings setParentFolderPlaceholder(final String sequence)
634        {
635                parentFolderPlaceholder = sequence;
636                return this;
637        }
638
639        /**
640         * gets the resource caching strategy
641         *
642         * @return strategy
643         */
644        public IResourceCachingStrategy getCachingStrategy()
645        {
646                if (resourceCachingStrategy == null)
647                {
648                        final IResourceVersion resourceVersion;
649
650                        if (application.usesDevelopmentConfig())
651                        {
652                                // development mode:
653                                // use last-modified timestamp of packaged resource for resource caching
654                                // cache the version information for the lifetime of the current http request
655                                resourceVersion = new RequestCycleCachedResourceVersion(
656                                        new LastModifiedResourceVersion());
657                        }
658                        else
659                        {
660                                // deployment mode:
661                                // use message digest over resource content for resource caching
662                                // cache the version information for the lifetime of the application
663                                resourceVersion = new CachingResourceVersion(new MessageDigestResourceVersion());
664                        }
665                        // cache resource with a version string in the filename
666                        resourceCachingStrategy = new FilenameWithVersionResourceCachingStrategy(
667                                resourceVersion);
668                }
669                return resourceCachingStrategy;
670        }
671
672        /**
673         * sets the resource caching strategy
674         *
675         * @param strategy
676         *            instance of resource caching strategy
677         *
678         * @see IResourceCachingStrategy
679         * @return {@code this} object for chaining
680         */
681        public ResourceSettings setCachingStrategy(IResourceCachingStrategy strategy)
682        {
683                if (strategy == null)
684                {
685                        throw new NullPointerException(
686                                "It is not allowed to set the resource caching strategy to value NULL. " +
687                                        "Please use " + NoOpResourceCachingStrategy.class.getName() + " instead.");
688                }
689                resourceCachingStrategy = strategy;
690                return this;
691        }
692
693        /**
694         * Sets whether to use pre-minified resources when available. Minified resources are detected by
695         * name. The minified version of {@code x.js} is expected to be called {@code x.min.js}. For css
696         * files, the same convention is used: {@code x.min.css} is the minified version of
697         * {@code x.css}. When this is null, minified resources will only be used in deployment
698         * configuration.
699         *
700         * @param useMinifiedResources
701         *            The new value for the setting
702         * @return {@code this} object for chaining
703         */
704        public ResourceSettings setUseMinifiedResources(boolean useMinifiedResources)
705        {
706                this.useMinifiedResources = useMinifiedResources;
707                return this;
708        }
709
710        /**
711         * @return Whether pre-minified resources will be used.
712         */
713        public boolean getUseMinifiedResources()
714        {
715                return useMinifiedResources;
716        }
717
718        /**
719         * @return The comparator used to sort header items.
720         */
721        public Comparator<? super RecordedHeaderItem> getHeaderItemComparator()
722        {
723                return headerItemComparator;
724        }
725
726        /**
727         * Sets the comparator used by the {@linkplain org.apache.wicket.markup.head.ResourceAggregator resource aggregator} for
728         * sorting header items. It should be noted that sorting header items may break resource
729         * dependencies. This comparator should therefore at least respect dependencies declared by
730         * resource references. By default, items are sorted using the {@link PriorityFirstComparator}.
731         *
732         * @param headerItemComparator
733         *            The comparator used to sort header items, when null, header items will not be
734         *            sorted.
735         * @return {@code this} object for chaining
736         */
737        public ResourceSettings setHeaderItemComparator(Comparator<? super RecordedHeaderItem> headerItemComparator)
738        {
739                this.headerItemComparator = headerItemComparator;
740                return this;
741        }
742
743        /**
744         * A flag indicating whether static resources should have <tt>jsessionid</tt> encoded in their
745         * url.
746         *
747         * @return {@code true} if the jsessionid should be encoded in the url for resources
748         *         implementing
749         *         {@link org.apache.wicket.request.resource.caching.IStaticCacheableResource} when the
750         *         cookies are disabled and there is an active http session.
751         */
752        public boolean isEncodeJSessionId()
753        {
754                return encodeJSessionId;
755        }
756
757        /**
758         * Sets a flag indicating whether the jsessionid should be encoded in the url for resources
759         * implementing {@link org.apache.wicket.request.resource.caching.IStaticCacheableResource} when
760         * the cookies are disabled and there is an active http session.
761         *
762         * @param encodeJSessionId
763         *            {@code true} when the jsessionid should be encoded, {@code false} - otherwise
764         * @return {@code this} object for chaining
765         */
766        public ResourceSettings setEncodeJSessionId(boolean encodeJSessionId)
767        {
768                this.encodeJSessionId = encodeJSessionId;
769                return this;
770        }
771}