com.sun.jersey.api.core.ResourceConfig Maven / Gradle / Ivy
Show all versions of jersey-bundle Show documentation
/*
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://jersey.dev.java.net/CDDL+GPL.html
* or jersey/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at jersey/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.jersey.api.core;
import com.sun.jersey.core.util.FeaturesAndProperties;
import com.sun.jersey.server.wadl.WadlGenerator;
import com.sun.jersey.spi.container.ContainerListener;
import com.sun.jersey.spi.container.ContainerNotifier;
import com.sun.jersey.spi.container.ContainerRequestFilter;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import com.sun.jersey.spi.container.ResourceFilterFactory;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
/**
* The resource configuration for configuring a web application.
*/
public abstract class ResourceConfig extends Application implements FeaturesAndProperties {
private static final Logger LOGGER =
Logger.getLogger(ResourceConfig.class.getName());
/**
* If true the request URI will be normalized as specified by
* {@link java.net.URI#normalize}. If not true the request URI is not
* modified.
*
* The default value is false.
*/
public static final String FEATURE_NORMALIZE_URI
= "com.sun.jersey.config.feature.NormalizeURI";
/**
* If true the request URI path component will be canonicalized by removing
* contiguous slashes (i.e. all /+ will be replaced by /). If not true the
* request URI path component is mot modified.
*
* The default value is false.
*/
public static final String FEATURE_CANONICALIZE_URI_PATH
= "com.sun.jersey.config.feature.CanonicalizeURIPath";
/**
* If true, and either NORMALIZE_URI or CANONICALIZE_URI_PATH is true,
* and the normalization and/or path canonicalization operations on the
* request URI result in a new URI that is not equal to the request URI,
* then the client is (temporarily) redirected to the new URI. Otherwise
* the request URI is set to be the new URI.
*
* If true, and the path value of a {@link javax.ws.rs.Path} annotation ends
* in a slash, the request URI path does not end in a '/' and would otherwise
* match the path value if it did, then the client is (temporarily)
* redirected to a new URI that is the request URI with a '/' appended to the
* the end of the path.
*
* The default value is false.
*/
public static final String FEATURE_REDIRECT
= "com.sun.jersey.config.feature.Redirect";
/**
* If true matrix parameters (if present) in the request URI path component
* will be ignored when matching the path to URI templates declared by
* resource classes.
*
* The default value is false.
*/
public static final String FEATURE_MATCH_MATRIX_PARAMS
= "com.sun.jersey.config.feature.IgnoreMatrixParams";
/**
* If true then the matching algorithm will attempt to match and accept
* any static content or templates associated with a resource that were
* not explicitly decared by that resource.
*
* If a template is matched then the model for the viewable will be the
* resource instance associated with the template.
*
* The default value is false.
*/
public static final String FEATURE_IMPLICIT_VIEWABLES
= "com.sun.jersey.config.feature.ImplicitViewables";
/**
* If set the default resource component provider factory for the
* life-cycle of resource classes.
*
* The type of this property must be a Java class that implementations
* {@link com.sun.jersey.server.spi.component.ResourceComponentProviderFactory}.
*
* If not set the default resource component provider factory will be the
* per-request resource component provider factory.
*/
public static final String PROPERTY_DEFAULT_RESOURCE_COMPONENT_PROVIDER_FACTORY_CLASS
= "com.sun.jersey.config.property.DefaultResourceComponentProviderFactoryClass";
/**
* If set the instance of {@link ContainerNotifier} to register
* {@link ContainerListener} instances.
*
* If the instance does not implement the {@link ContainerNotifier}
* then the property is ignored.
*/
public static final String PROPERTY_CONTAINER_NOTIFIER =
"com.sun.jersey.spi.container.ContainerNotifier";
/**
* If set the list of {@link ContainerRequestFilter} that are applied
* to filter the request. When applying the list of request filters to
* a request each request filter is applied, in order, from the first to
* the last entry in the list.
*
* The instance may be a String[] or String that contains one or more fully
* qualified class name of a request filter class separeted by ';'.
* Otherwise the instance may be List<ContainerRequestFilter>.
*
* If a String[] or String of fully qualified class names then each
* class is instantiated as a singleton. Thus, if there is more than one
* class registered for this property or the same class is also registered for
* the {@link #PROPERTY_CONTAINER_RESPONSE_FILTERS} property then only
* one instance will be instatiated.
*
* @see com.sun.jersey.api.container.filter
*/
public static final String PROPERTY_CONTAINER_REQUEST_FILTERS =
"com.sun.jersey.spi.container.ContainerRequestFilters";
/**
* If set the list of {@link ContainerResponseFilter} that are applied
* to filter the response. When applying the list of response filters to
* a response each response filter is applied, in order, from the first to
* the last entry in the list.
*
* The instance may be a String[] or String that contains one or more fully
* qualified class name of a response filter class separeted by ';'.
* Otherwise the instance may be List<ContainerResponseFilter>.
*
* If a String[] or String of fully qualified class names then each
* class is instantiated as a singleton. Thus, if there is more than one
* class registered for this property or the same class is also registered for
* the {@link #PROPERTY_CONTAINER_REQUEST_FILTERS} property then only
* one instance will be instatiated.
*
* @see com.sun.jersey.api.container.filter
*/
public static final String PROPERTY_CONTAINER_RESPONSE_FILTERS =
"com.sun.jersey.spi.container.ContainerResponseFilters";
/**
* If set the list of {@link ResourceFilterFactory} that are applied
* to resources. When applying the list of resource filters factories to a
* request each resource filter factory is applied, in order, from the first
* to last entry in the list.
*
* The instance may be a String[] or String that contains one or more fully
* qualified class name of a response filter class separeted by ';'.
* Otherwise the instance may be List<ResourceFilterFactory>.
*
* If a String[] or String of fully qualified class names then each
* class is instantiated as a singleton. Thus, if there is more than one
* class registered for this property one instance will be instatiated.
*
* @see com.sun.jersey.api.container.filter
*/
public static final String PROPERTY_RESOURCE_FILTER_FACTORIES =
"com.sun.jersey.spi.container.ResourceFilters";
/**
* If set the wadl generator configuration that provides that {@link WadlGenerator}
* to be used by the {@link com.sun.jersey.server.impl.wadl.WadlFactory}.
*
* The type of this property must be a subclass or an instance of a subclass of
* {@link com.sun.jersey.api.wadl.config.WadlGeneratorConfig}.
*
*
* If this property is not set the default wadl generator will be used for generating wadl.
*
*/
public static final String PROPERTY_WADL_GENERATOR_CONFIG =
"com.sun.jersey.config.property.WadlGeneratorConfig";
/**
* Get the map of features associated with the Web application.
*
* @return the features.
* The returned value shall never be null.
*/
public abstract Map getFeatures();
/**
* Get the value of a feature.
*
* @param featureName the feature name.
* @return true if the feature is present and set to true, otherwise false
* if the feature is present and set to false or the feature is not
* present.
*/
public abstract boolean getFeature(String featureName);
/**
* Get the map of properties associated with the Web application.
*
* @return the properties.
* The returned value shall never be null.
*/
public abstract Map getProperties();
/**
* Get the value of a property.
*
* @param propertyName the property name.
* @return the property, or null if there is no property present for the
* given property name.
*/
public abstract Object getProperty(String propertyName);
/**
* Get a map of file extension to media type. This is used to drive
* URI-based content negotiation such that, e.g.:
* GET /resource.atom
* is equivalent to:
* GET /resource
*Accept: application/atom+xml
* The default implementation returns an empty map.
* @return a map of file extension to media type
*/
public Map getMediaTypeMappings() {
return Collections.emptyMap();
}
/**
* Get a map of file extension to language. This is used to drive
* URI-based content negotiation such that, e.g.:
* GET /resource.english
* is equivalent to:
* GET /resource
*Accept-Language: en
* The default implementation returns an empty map.
* @return a map of file extension to language
*/
public Map getLanguageMappings() {
return Collections.emptyMap();
}
/**
* Validate the set of classes and singletons.
*
* A registered class is removed from the set of registered classes
* if an instance of that class is a member of the set of registered
* singletons.
*
A registered class that is an interface or an abstract class
* is removed from the registered classes.
*
* @throws IllegalArgumentException if the set of registered singletons
* contains more than one instance of the same root resource class.
*/
public void validate() {
// Remove any registered classes if instances exist in registered
// singletons
Iterator> i = getClasses().iterator();
while (i.hasNext()) {
Class> c = i.next();
for (Object o : getSingletons()) {
if (c.isInstance(o)) {
i.remove();
LOGGER.log(Level.WARNING,
"Class " + c.getName() +
" is ignored as an instance is registered in the set of singletons");
}
}
}
// Remove any classes that cannot be instantiated
i = getClasses().iterator();
while (i.hasNext()) {
Class> c = i.next();
int modifiers = c.getModifiers();
if (Modifier.isAbstract(modifiers) && !Modifier.isInterface(modifiers)) {
LOGGER.warning("The abstract " + c + ", registered as a root resource class " +
"of the ResourceConfig cannot be instantiated" +
". This class will be ignored");
i.remove();
} else if (Modifier.isInterface(modifiers)) {
LOGGER.warning("The " + c + ", registered as a root resource class " +
"of the ResourceConfig cannot be instantiated" +
". This interface will be ignored");
i.remove();
}
}
// Find conflicts
Set> objectClassSet = new HashSet>();
Set> conflictSet = new HashSet>();
for (Object o : getSingletons()) {
if (o.getClass().isAnnotationPresent(Path.class)) {
if (objectClassSet.contains(o.getClass())) {
conflictSet.add(o.getClass());
} else {
objectClassSet.add(o.getClass());
}
}
}
if (!conflictSet.isEmpty()) {
for (Class> c : conflictSet) {
LOGGER.log(Level.SEVERE,
"Root resource class " + c.getName() +
" is instantated more than once in the set of registered singletons");
}
throw new IllegalArgumentException(
"The set of registered singletons contains " +
"more than one instance of the same root resource class");
}
}
/**
* Get the set of root resource classes.
*
* A root resource class is a registered class that is annotated with
* Path.
*
* @return the unmodifiable set of root resource classes.
*/
public Set> getRootResourceClasses() {
Set> s = new HashSet>();
for (Class> c : getClasses()) {
if (isRootResourceClass(c))
s.add(c);
}
return Collections.unmodifiableSet(s);
}
/**
* Get the set of provider classes.
*
* A provider class is a registered class that is not annotated with
* Path.
*
* @return the unmodifiable set of provider classes.
*/
public Set> getProviderClasses() {
Set> s = new HashSet>();
for (Class> c : getClasses()) {
if (!c.isAnnotationPresent(Path.class))
s.add(c);
}
return Collections.unmodifiableSet(s);
}
/**
* Get the set of root resource singleton instances.
*
* A root resource singleton instance is a registered instance whose class
* is annotated with Path.
*
* @return the unmodifiable set of root resource singleton instances.
*/
public Set