org.apache.wicket.ResourceReference Maven / Gradle / Ivy
Show all versions of org.ops4j.pax.wicket.service Show documentation
/*
* 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;
import java.util.Locale;
import org.apache.wicket.markup.html.PackageResource;
import org.apache.wicket.util.lang.Classes;
import org.apache.wicket.util.lang.Objects;
import org.apache.wicket.util.time.Time;
import org.apache.wicket.util.watch.IModifiable;
/**
* ResourceReference is essentially a reference to an actual resource which is shared through the
* Application. A ResourceReference has a name and a scope (within which the name must be unique).
* It may also have a locale or style. The locale and/or style do not need to be set on a resource
* reference because those values will automatically be determined based on the context in which the
* resource is being used. For example, if a ResourceReference is attached to an Image component,
* when the locale for the page switches, the Image component will notice this and automatically
* change the locale for the referenced resource as appropriate. It's for this reason that you don't
* typically have to use the constructor overloads taking a Locale or style (these details are
* essentially internal and so the framework uses setLocale/setStyle internally so you don't have to
* worry about it).
*
* Package resources (resources which can be pulled from the classpath) do not have to be
* pre-registered. For custom situations though, resources may be added to the Application when the
* Application is constructed using {@link Application#getSharedResources()} followed by
* {@link SharedResources#add(Class, String, Locale, String, Resource)},
* {@link SharedResources#add(String, Locale, Resource)}or
* {@link SharedResources#add(String, Resource)}.
*
* If a component has its own shared resource which should not be added to the application
* construction logic in this way, it can lazy-initialize the resource by overriding the
* {@link #newResource()} method. In this method, the component should supply logic that creates the
* shared resource. By default the {@link #newResource()} method tries to resolve to a package
* resource.
*
* @author Jonathan Locke
*/
public class ResourceReference implements IClusterable
{
private static final long serialVersionUID = 2L;
/** The locale of the resource */
protected Locale locale;
/** The name of the resource */
private final String name;
/** The actual resource */
private transient Resource resource;
/** The scope of the named resource */
private final String scopeName;
/** The style of the resource */
private String style;
/** Whether or not this resource reference is stateless */
private boolean stateless;
/** Whether to use the locale and style set in the session, dynamically */
private boolean useSessionLocale = false;
private boolean useSessionStyle;
/**
* Constructs a ResourceReference with the given scope and name. The scope is used as a
* namespace and the scope together with the name must uniquely identify the reference.
*
* @param scope
* The scope of the name
* @param name
* The name of the resource
*/
public ResourceReference(final Class> scope, final String name)
{
this(scope, name, null, null);
}
/**
* Constructs a ResourceReference with the given scope and name. The scope is used as a
* namespace and the scope together with the name must uniquely identify the reference. This
* constructor takes in the locale and style arguments. The locale might be overruled if this
* resource resolves to a package resource.
*
* @param scope
* The scope of the name
* @param name
* The name of the resource
* @param locale
* The Locale from which the search for the PackageResource must start
* @param style
* The Style of the PackageResource
*/
public ResourceReference(final Class> scope, final String name, Locale locale, String style)
{
scopeName = scope.getName();
this.name = name;
this.locale = locale;
this.style = style;
}
/**
* Constructs a ResourceReference with the given scope and name that optionally follows the
* locale and style settings in the {@link Session}.
*
* @see Session#getStyle()
* @see Session#getLocale()
* @param scope
* The scope of the name
* @param name
* The name of the resource
* @param useSessionLocale
* Whether to follow the locale settings in the session. If true
, the
* locale will be taken dynamically from the session. If this and useSessionStyle
* false
, this ResourceReference will behave exactly as one constructed
* with {@link #ResourceReference(Class, String)}.
* @param useSessionStyle
* Whether to follow the style settings in the session. If true
, the
* style will be taken dynamically from the session. If this and useSessionLocale are
* false
, this ResourceReference will behave exactly as one constructed
* with {@link #ResourceReference(Class, String)}.
*/
public ResourceReference(final Class> scope, final String name, boolean useSessionLocale,
boolean useSessionStyle)
{
this(scope, name);
this.useSessionLocale = useSessionLocale;
this.useSessionStyle = useSessionStyle;
}
/**
* Constructs a resource reference with Application.class scope and the given name. All resource
* references constructed with this constructor must have unique names since they all have the
* same Application-wide scope that is the org.apache.wicket.Application.class
*
* @param name
* The name of the resource
*/
public ResourceReference(final String name)
{
this(Application.class, name);
}
/**
* Constructs a ResourceReference with the given scope and name that optionally follows the
* locale and style settings in the {@link Session}. This is a convenience constructor that
* calls {@link #ResourceReference(Class, String, boolean, boolean)} supplying the value of
* useSessionLocaleAndStyle for both flags.
*
* @see Session#getStyle()
* @see Session#getLocale()
* @param scope
* The scope of the name
* @param name
* The name of the resource
* @param useSessionLocaleAndStyle
* Whether to follow the locale and style settings in the session. If
* true
, the locale and style will be taken dynamically from the
* session. If this is false
, this ResourceReference will behave exactly
* as one constructed with {@link #ResourceReference(Class, String)}.
*/
public ResourceReference(final Class> scope, final String name,
boolean useSessionLocaleAndStyle)
{
this(scope, name, useSessionLocaleAndStyle, useSessionLocaleAndStyle);
}
/**
* Binds this shared resource to the given application.
*
* @param application
* The application which holds the shared resource
*/
public final void bind(final Application application)
{
// Try to resolve resource
if (resource == null)
{
SharedResources sharedResources = application.getSharedResources();
// Try to get resource from Application repository
resource = sharedResources.get(getScope(), name, locale, style, true);
if ((resource != null) && (resource instanceof PackageResource))
{
// see newResource() as well.
locale = ((PackageResource)resource).getLocale();
}
// Not available yet?
if (resource == null)
{
// Create resource using lazy-init factory method
resource = newResource();
if (resource == null)
{
// If lazy-init did not create resource with correct locale
// and style then we should default the resource
resource = sharedResources.get(getScope(), name, locale, style, false);
if (resource == null)
{
// still null? try to see whether it is a package
// resource that should
// be lazily loaded
resource = PackageResource.get(getScope(), name);
// will throw an exception if not found, so if we come
// here, it was found
sharedResources.add(name, resource);
}
}
// Share through application
sharedResources.add(getScope(), name, locale, style, resource);
}
}
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (obj instanceof ResourceReference)
{
ResourceReference that = (ResourceReference)obj;
return Objects.equal(getScope().getName(), that.getScope().getName()) &&
Objects.equal(name, that.name) && Objects.equal(locale, that.locale) &&
Objects.equal(style, that.style);
}
return false;
}
/**
* @return Returns the locale.
*/
public final Locale getLocale()
{
return locale;
}
/**
* @return Name
*/
public final String getName()
{
return name;
}
/**
* Gets the resource for this resource reference. If the ResourceReference has not yet been
* bound to the application via {@link ResourceReference#bind(Application)}this method may
* return null.
*
* @return The resource, or null if the ResourceReference has not yet been bound.
*/
public final Resource getResource()
{
return resource;
}
/**
* @return Scope
*/
public final Class> getScope()
{
return Classes.resolveClass(scopeName);
}
/**
* @return the shared resource key for this resource reference.
*/
public final String getSharedResourceKey()
{
Application application = Application.get();
if (useSessionLocale)
{
if (!Objects.equal(locale, Session.get().getLocale()))
{
setLocale(Session.get().getLocale());
}
}
if (useSessionStyle)
{
if (!Objects.equal(style, Session.get().getStyle()))
{
setStyle(Session.get().getStyle());
}
}
bind(application);
return application.getSharedResources().resourceKey(getScope(), name, locale, style);
}
/**
* @return Returns the style. (see {@link org.apache.wicket.Session})
*/
public final String getStyle()
{
return style;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
int result = 17;
result = 37 * result + (scopeName != null ? scopeName.hashCode() : 0);
result = 37 * result + (name != null ? name.hashCode() : 0);
result = 37 * result + (locale != null ? locale.hashCode() : 0);
result = 37 * result + (style != null ? style.hashCode() : 0);
return result;
}
/**
* Sets any loaded resource to null, thus forcing a reload on the next request.
*/
public final void invalidate()
{
resource = null;
}
/**
* @param locale
* The locale to set.
*/
public final void setLocale(Locale locale)
{
this.locale = locale;
invalidate();
}
/**
* @param style
* The style to set (see {@link org.apache.wicket.Session}).
*/
public final void setStyle(String style)
{
this.style = style;
invalidate();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "[ResourceReference name = " + name + ", scope = " + scopeName + ", locale = " +
locale + ", style = " + style + ", useSessionLocale = " + useSessionLocale +
", useSessionStyle = " + useSessionStyle + "]";
}
/**
* Factory method for lazy initialization of shared resources.
*
* @return The resource
*/
protected Resource newResource()
{
PackageResource packageResource = PackageResource.get(getScope(), getName(), getLocale(),
getStyle());
if (packageResource != null)
{
locale = packageResource.getLocale();
}
else
{
throw new IllegalArgumentException("package resource [scope=" + getScope() + ",name=" +
getName() + ",locale=" + getLocale() + "style=" + getStyle() + "] not found");
}
return packageResource;
}
/**
* Returns the last modified time of resource referenced by this reference.
*
* @return last modified time or null if the time couldn't have been determined
*/
public Time lastModifiedTime()
{
Resource resource = getResource();
if (resource instanceof IModifiable)
{
return ((IModifiable)resource).lastModifiedTime();
}
else
{
return null;
}
}
/**
* @see #setStateless(boolean)
* @return stateless falg
*/
public boolean isStateless()
{
return stateless;
}
/**
* Sets whether or not the resource pointed to by this reference requires a session. Urls to
* resources that do not require a session will have their jsessionid stripped.
*
* @param stateless
*/
public void setStateless(boolean stateless)
{
this.stateless = stateless;
}
/**
* @return Whether or not to use the locale defined in the current session.
*/
public boolean isUseSessionLocale()
{
return useSessionLocale;
}
/**
* @param useSessionLocale
* Whether or not to use the locale defined in the current session.
*/
public void setUseSessionLocale(boolean useSessionLocale)
{
this.useSessionLocale = useSessionLocale;
}
/**
* @return Whether or not to use the style defined in the current session.
*/
public boolean isUseSessionStyle()
{
return useSessionStyle;
}
/**
* @param useSessionStyle
* Whether or not to use the style defined in the current session.
*/
public void setUseSessionStyle(boolean useSessionStyle)
{
this.useSessionStyle = useSessionStyle;
}
}