/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
* 1.0 (the "Licenses"). You can select the license that you prefer but you may
* not use this file except in compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.opensource.org/licenses/lgpl-3.0
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet
*/
package org.restlet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;
import org.restlet.data.Parameter;
//import org.restlet.engine.Engine;
import org.restlet.util.Series;
/**
* Contextual data and services provided to a set of Restlets. The context is
* the means by which a Restlet may access the software environment within the
* framework. It is typically provided by the immediate parent Restlet
* (Application is the most common case).<br>
* <br>
* Concurrency note: attributes and parameters of a context are stored in
* concurrent collections that guarantee thread safe access and modification. If
* several threads concurrently access objects and modify these collections,
* they should synchronize on the lock of the Context instance.
*
* @author Jerome Louvel
*/
public class Context {
private static final ThreadLocal<Context> CURRENT = new ThreadLocal<Context>();
/**
* Returns the context associated to the current {@link Restlet}. The
* context can be the one of a {@link Component}, an {@link Application}, a
* {@link org.restlet.routing.Filter} or any other {@link Restlet} subclass.<br>
* <br>
* Warning: this method should only be used under duress. You should by
* default prefer obtaining the current context using methods such as
* {@link org.restlet.Restlet#getContext()} or
* {@link org.restlet.resource.Resource#getContext()}.<br>
* <br>
* This variable is stored internally as a thread local variable and updated
* each time a request is handled by a {@link Restlet} via the
* {@link Restlet#handle(org.restlet.Request, org.restlet.Response)} method.
*
* @return The current context.
*/
public static Context getCurrent() {
return CURRENT.get();
}
/**
* Returns the current context's logger.
*
* @return The current context's logger.
*/
public static Logger getCurrentLogger() {
return (Context.getCurrent() != null) ? Context.getCurrent()
.getLogger() :
null;
}
/**
* Sets the context to associated with the current thread.
*
* @param context
* The thread's context.
*/
public static void setCurrent(Context context) {
CURRENT.set(context);
}
/** The modifiable attributes map. */
private final ConcurrentMap<String, Object> attributes;
/** The logger instance to use. */
private volatile Logger logger;
/** The modifiable series of parameters. */
private final Series<Parameter> parameters;
/**
* The verifier that can check the validity of user/secret couples based on
* Restlet default authorization model.
*/
private volatile org.restlet.security.Verifier defaultVerifier;
/** The executor service. */
private volatile ScheduledExecutorService executorService;
/**
* Constructor. Writes log messages to "org.restlet".
*/
public Context() {
this("org.restlet");
}
/**
* Constructor.
*
* @param logger
* The logger instance of use.
*/
public Context(Logger logger) {
this.attributes = new ConcurrentHashMap<String, Object>();
this.logger = logger;
this.parameters = new Series<Parameter>(Parameter.class,
new CopyOnWriteArrayList<Parameter>());
this.defaultVerifier = null;
}
/**
* Constructor.
*
* @param loggerName
* The name of the logger to use.
*/
public Context(String loggerName) {
this(getCurrentLogger());
}
/**
* Returns a modifiable attributes map that can be used by developers to
* save information relative to the context. This is a convenient means to
* provide common objects to all the Restlets and Resources composing an
* Application.<br>
* <br>
*
* In addition, this map is a shared space between the developer and the
* Restlet implementation. For this purpose, all attribute names starting
* with "org.restlet" are reserved. Currently the following attributes are
* used:
* <table>
* <tr>
* <th>Attribute name</th>
* <th>Class name</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>org.restlet.application</td>
* <td>org.restlet.Application</td>
* <td>The parent application providing this context, if any.</td>
* </tr>
* </table>
* </td>
*
* @return The modifiable attributes map.
*/
public ConcurrentMap<String, Object> getAttributes() {
return this.attributes;
}
/**
* Returns a verifier that can check the validity of the credentials
* associated to a request.
*
* @return A verifier.
*/
public org.restlet.security.Verifier getDefaultVerifier() {
return this.defaultVerifier;
}
/**
* Returns the executor service.
*
* @return The executor service.
*/
public ScheduledExecutorService getExecutorService() {
return this.executorService;
}
/**
* Returns the logger.
*
* @return The logger.
*/
public Logger getLogger() {
return this.logger;
}
/**
* Returns the modifiable series of parameters. A parameter is a pair
* composed of a name and a value and is typically used for configuration
* purpose, like Java properties. Note that multiple parameters with the
* same name can be declared and accessed.
*
* @return The modifiable series of parameters.
*/
public Series<Parameter> getParameters() {
return this.parameters;
}
/**
* Sets the modifiable map of attributes. This method clears the current map
* and puts all entries in the parameter map.
*
* @param attributes
* A map of attributes.
*/
public void setAttributes(Map<String, Object> attributes) {
synchronized (getAttributes()) {
if (attributes != getAttributes()) {
getAttributes().clear();
if (attributes != null) {
getAttributes().putAll(attributes);
}
}
}
}
/**
* Sets a local verifier that can check the validity of user/secret couples
* based on Restlet default authorization model.
*
* @param verifier
* A local verifier.
*/
public void setDefaultVerifier(org.restlet.security.Verifier verifier) {
this.defaultVerifier = verifier;
}
/**
* Sets the executor service.
*
* @param executorService
* The executor service.
*/
public void setExecutorService(ScheduledExecutorService executorService) {
this.executorService = executorService;
}
/**
* Sets the logger.
*
* @param logger
* The logger.
*/
public void setLogger(Logger logger) {
this.logger = logger;
}
/**
* Sets the modifiable series of parameters. This method clears the current
* series and adds all entries in the parameter series.
*
* @param parameters
* A series of parameters.
*/
public void setParameters(Series<Parameter> parameters) {
synchronized (getParameters()) {
if (parameters != getParameters()) {
getParameters().clear();
if (parameters != null) {
getParameters().addAll(parameters);
}
}
}
}
}