blob: 21ddf9386bdb5baa46e34271a0ea5d55864b29d5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.wicket.resource;
import java.time.Duration;
import java.time.Instant;
import java.util.Locale;
import java.util.Map;
import org.apache.wicket.Application;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.request.resource.ResourceReferenceRegistry;
import org.apache.wicket.request.resource.ResourceStreamResource;
import org.apache.wicket.util.io.IClusterable;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
import org.apache.wicket.util.template.PackageTextTemplate;
import org.apache.wicket.util.template.TextTemplate;
/**
* A class which adapts a {@link PackageTextTemplate} to a {@link ResourceReference}.
*
* See <a href="https://cwiki.apache.org/confluence/display/WICKET/Dynamically+Generate+a+CSS+Stylesheet">Dynamically generate a CSS stylesheet</a>
*
* @author James Carman
*/
public class TextTemplateResourceReference extends ResourceReference implements IClusterable
{
private static final long serialVersionUID = 1L;
private final TextTemplate textTemplate;
private final IModel<Map<String, Object>> variablesModel;
private final ResourceStreamResource resource;
/**
* Creates a resource reference to a {@link PackageTextTemplate}.
*
* @param scope
* the <code>Class</code> to be used for retrieving the classloader for loading the
* <code>PackagedTextTemplate</code>
* @param fileName
* the file name
* @param variablesModel
* the template variables as a model
*/
public TextTemplateResourceReference(final Class<?> scope, final String fileName,
IModel<Map<String, Object>> variablesModel)
{
this(scope, fileName, PackageTextTemplate.DEFAULT_CONTENT_TYPE,
PackageTextTemplate.DEFAULT_ENCODING, variablesModel);
}
/**
* Creates a resource reference to a {@link PackageTextTemplate}.
*
* @param scope
* the <code>Class</code> to be used for retrieving the classloader for loading the
* <code>PackagedTextTemplate</code>
* @param fileName
* the file name
* @param contentType
* the mime type of this resource, such as "<code>image/jpeg</code>" or "
* <code>text/html</code>"
* @param variablesModel
* the template variables as a model
*/
public TextTemplateResourceReference(final Class<?> scope, final String fileName,
final String contentType, IModel<Map<String, Object>> variablesModel)
{
this(scope, fileName, contentType, PackageTextTemplate.DEFAULT_ENCODING, variablesModel);
}
/**
* Creates a resource reference to a {@link PackageTextTemplate}.
*
* @param scope
* the <code>Class</code> to be used for retrieving the classloader for loading the
* <code>PackagedTextTemplate</code>
* @param fileName
* the file name
* @param contentType
* the mime type of this resource, such as "<code>image/jpeg</code>" or "
* <code>text/html</code>"
* @param encoding
* the file's encoding, for example, "<code>UTF-8</code>"
* @param variablesModel
* the template variables as a model
*/
public TextTemplateResourceReference(final Class<?> scope, final String fileName,
final String contentType, final String encoding, IModel<Map<String, Object>> variablesModel)
{
this(scope, fileName, contentType, encoding, variablesModel, null, null, null);
}
/**
* Construct.
*
* @param scope
* the <code>Class</code> to be used for retrieving the classloader for loading the
* <code>PackagedTextTemplate</code>
* @param fileName
* the file name
* @param contentType
* the mime type of this resource, such as "<code>image/jpeg</code>" or "
* <code>text/html</code>"
* @param encoding
* the file's encoding, for example, "<code>UTF-8</code>"
* @param variablesModel
* the template variables as a model
* @param locale
* Preferred locale for the resource
* @param style
* Preferred style for the resource
* @param variation
* Preferred variation for the resource
*/
public TextTemplateResourceReference(final Class<?> scope, final String fileName,
final String contentType, final String encoding,
IModel<Map<String, Object>> variablesModel, Locale locale, String style, String variation)
{
super(scope, fileName, locale, style, variation);
textTemplate = new PackageTextTemplate(scope, fileName, contentType, encoding);
this.variablesModel = variablesModel;
resource = new ResourceStreamResource(null)
{
@Override
protected IResourceStream getResourceStream(Attributes attributes)
{
IModel<Map<String, Object>> variables = TextTemplateResourceReference.this.variablesModel;
String stringValue = textTemplate.asString(variables.getObject());
variables.detach(); // We're done with the model so detach it!
StringResourceStream resourceStream = new StringResourceStream(stringValue,
textTemplate.getContentType());
resourceStream.setLastModified(Instant.now());
return resourceStream;
}
};
resource.setCacheDuration(Duration.ZERO);
if (Application.exists())
{
// TextTemplateResourceReference should not be cached due to its dynamic nature
// Old entry in the registry would keep wrong 'variablesModel'
ResourceReferenceRegistry resourceReferenceRegistry = Application.get().getResourceReferenceRegistry();
resourceReferenceRegistry.unregisterResourceReference(getKey());
resourceReferenceRegistry.registerResourceReference(this);
}
}
/**
* Creates a new resource which returns the interpolated value of the text template.
*
* @return a new resource which returns the interpolated value of the text template
*/
@Override
public IResource getResource()
{
return resource;
}
}