/*
* Copyright (c) 2010, 2017 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package javax.ws.rs.ext;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.Variant.VariantListBuilder;
import java.lang.reflect.ReflectPermission;
import java.net.URL;
Implementations of this API provide a concrete subclass of RuntimeDelegate and
various API methods defer to methods of RuntimeDelegate for their
functionality. Regular users of the API are not expected to use this class
directly and overriding an implementation of this class with a user supplied
subclass may cause unexpected behavior.
Author: Paul Sandoz, Marc Hadley Since: 1.0
/**
* Implementations of this API provide a concrete subclass of RuntimeDelegate and
* various API methods defer to methods of RuntimeDelegate for their
* functionality. Regular users of the API are not expected to use this class
* directly and overriding an implementation of this class with a user supplied
* subclass may cause unexpected behavior.
*
* @author Paul Sandoz
* @author Marc Hadley
* @since 1.0
*/
public abstract class RuntimeDelegate {
Name of the property identifying the RuntimeDelegate
implementation to be returned from getInstance()
. /**
* Name of the property identifying the {@link RuntimeDelegate} implementation
* to be returned from {@link RuntimeDelegate#getInstance()}.
*/
public static final String JAXRS_RUNTIME_DELEGATE_PROPERTY = "javax.ws.rs.ext.RuntimeDelegate";
private static final String JAXRS_DEFAULT_RUNTIME_DELEGATE = "org.glassfish.jersey.internal.RuntimeDelegateImpl";
private static final Object RD_LOCK = new Object();
private static ReflectPermission suppressAccessChecksPermission = new ReflectPermission("suppressAccessChecks");
private static volatile RuntimeDelegate cachedDelegate;
Allows custom implementations to extend the RuntimeDelegate
class. /**
* Allows custom implementations to extend the {@code RuntimeDelegate} class.
*/
protected RuntimeDelegate() {
}
Obtain a RuntimeDelegate
instance. If an instance had not already been created and set via setInstance(RuntimeDelegate)
, the first invocation will create an instance which will then be cached for future use.
The algorithm used to locate the RuntimeDelegate subclass to use consists
of the following steps:
- If a resource with the name of
META-INF/services/javax.ws.rs.ext.RuntimeDelegate
exists, then its first line, if present, is used as the UTF-8 encoded name of the implementation class.
- If the $java.home/lib/jaxrs.properties file exists and it is readable by the
java.util.Properties.load(InputStream)
method and it contains an entry whose key is javax.ws.rs.ext.RuntimeDelegate
, then the value of that entry is used as the name of the implementation class.
- If a system property with the name
javax.ws.rs.ext.RuntimeDelegate
is defined, then its value is used as the name of the implementation class.
-
Finally, a default implementation class name is used.
Returns: an instance of RuntimeDelegate
.
/**
* Obtain a {@code RuntimeDelegate} instance. If an instance had not already been
* created and set via {@link #setInstance(RuntimeDelegate)}, the first
* invocation will create an instance which will then be cached for future use.
*
* <p>
* The algorithm used to locate the RuntimeDelegate subclass to use consists
* of the following steps:
* </p>
* <ul>
* <li>
* If a resource with the name of {@code META-INF/services/javax.ws.rs.ext.RuntimeDelegate}
* exists, then its first line, if present, is used as the UTF-8 encoded
* name of the implementation class.
* </li>
* <li>
* If the $java.home/lib/jaxrs.properties file exists and it is readable by
* the {@code java.util.Properties.load(InputStream)} method and it contains
* an entry whose key is {@code javax.ws.rs.ext.RuntimeDelegate}, then the value of
* that entry is used as the name of the implementation class.
* </li>
* <li>
* If a system property with the name {@code javax.ws.rs.ext.RuntimeDelegate}
* is defined, then its value is used as the name of the implementation class.
* </li>
* <li>
* Finally, a default implementation class name is used.
* </li>
* </ul>
*
* @return an instance of {@code RuntimeDelegate}.
*/
public static RuntimeDelegate getInstance() {
// Double-check idiom for lazy initialization of fields.
// Local variable is used to limit the number of more expensive accesses to a volatile field.
RuntimeDelegate result = cachedDelegate;
if (result == null) { // First check (no locking)
synchronized (RD_LOCK) {
result = cachedDelegate;
if (result == null) { // Second check (with locking)
cachedDelegate = result = findDelegate();
}
}
}
return result;
}
Obtain a RuntimeDelegate
instance using the method described in getInstance
. Returns: an instance of RuntimeDelegate
.
/**
* Obtain a {@code RuntimeDelegate} instance using the method described in
* {@link #getInstance}.
*
* @return an instance of {@code RuntimeDelegate}.
*/
private static RuntimeDelegate findDelegate() {
try {
Object delegate = FactoryFinder.find(
JAXRS_RUNTIME_DELEGATE_PROPERTY,
JAXRS_DEFAULT_RUNTIME_DELEGATE,
RuntimeDelegate.class);
if (!(delegate instanceof RuntimeDelegate)) {
Class pClass = RuntimeDelegate.class;
String classnameAsResource = pClass.getName().replace('.', '/') + ".class";
ClassLoader loader = pClass.getClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
URL targetTypeURL = loader.getResource(classnameAsResource);
throw new LinkageError("ClassCastException: attempting to cast"
+ delegate.getClass().getClassLoader().getResource(classnameAsResource)
+ " to " + targetTypeURL);
}
return (RuntimeDelegate) delegate;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
Set the runtime delegate that will be used by classes. If this method is not called prior to getInstance
then an implementation will be sought as described in getInstance
. Params: - rd – the runtime delegate instance
Throws: - SecurityException – if there is a security manager and the permission
ReflectPermission("suppressAccessChecks") has not been granted.
/**
* Set the runtime delegate that will be used by classes. If this method
* is not called prior to {@link #getInstance} then an implementation will
* be sought as described in {@link #getInstance}.
*
* @param rd the runtime delegate instance
* @throws SecurityException if there is a security manager and the permission
* ReflectPermission("suppressAccessChecks") has not been granted.
*/
public static void setInstance(final RuntimeDelegate rd) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(suppressAccessChecksPermission);
}
synchronized (RD_LOCK) {
RuntimeDelegate.cachedDelegate = rd;
}
}
Create a new instance of a UriBuilder
. See Also: Returns: new UriBuilder
instance.
/**
* Create a new instance of a {@link javax.ws.rs.core.UriBuilder}.
*
* @return new {@code UriBuilder} instance.
* @see javax.ws.rs.core.UriBuilder
*/
public abstract UriBuilder createUriBuilder();
Create a new instance of a ResponseBuilder
. See Also: Returns: new ResponseBuilder
instance.
/**
* Create a new instance of a {@link javax.ws.rs.core.Response.ResponseBuilder}.
*
* @return new {@code ResponseBuilder} instance.
* @see javax.ws.rs.core.Response.ResponseBuilder
*/
public abstract ResponseBuilder createResponseBuilder();
Create a new instance of a VariantListBuilder
. See Also: Returns: new VariantListBuilder
instance.
/**
* Create a new instance of a {@link javax.ws.rs.core.Variant.VariantListBuilder}.
*
* @return new {@code VariantListBuilder} instance.
* @see javax.ws.rs.core.Variant.VariantListBuilder
*/
public abstract VariantListBuilder createVariantListBuilder();
Create a configured instance of the supplied endpoint type. How the
returned endpoint instance is published is dependent on the type of
endpoint.
Params: - application – the application configuration.
- endpointType – the type of endpoint instance to be created.
Type parameters: - <T> – endpoint type.
Throws: - IllegalArgumentException –
if application is null or the requested endpoint type is
not supported.
- UnsupportedOperationException –
if the implementation supports no endpoint types.
Returns: a configured instance of the requested type.
/**
* Create a configured instance of the supplied endpoint type. How the
* returned endpoint instance is published is dependent on the type of
* endpoint.
*
* @param <T> endpoint type.
* @param application the application configuration.
* @param endpointType the type of endpoint instance to be created.
* @return a configured instance of the requested type.
* @throws java.lang.IllegalArgumentException
* if application is null or the requested endpoint type is
* not supported.
* @throws java.lang.UnsupportedOperationException
* if the implementation supports no endpoint types.
*/
public abstract <T> T createEndpoint(Application application, Class<T> endpointType)
throws IllegalArgumentException, UnsupportedOperationException;
Obtain an instance of a HeaderDelegate
for the supplied class. An implementation is required to support the following values for type: CacheControl
, Cookie
, EntityTag
, Link
, NewCookie
, MediaType
and java.util.Date
. Params: - type – the class of the header.
Type parameters: - <T> – header type.
Throws: - IllegalArgumentException – if type is
null
.
See Also: Returns: an instance of HeaderDelegate
for the supplied type.
/**
* Obtain an instance of a {@link HeaderDelegate} for the supplied class. An
* implementation is required to support the following values for type:
* {@link javax.ws.rs.core.CacheControl}, {@link javax.ws.rs.core.Cookie},
* {@link javax.ws.rs.core.EntityTag}, {@link javax.ws.rs.core.Link},
* {@link javax.ws.rs.core.NewCookie}, {@link javax.ws.rs.core.MediaType}
* and {@code java.util.Date}.
*
* @param <T> header type.
* @param type the class of the header.
* @return an instance of {@code HeaderDelegate} for the supplied type.
* @throws java.lang.IllegalArgumentException
* if type is {@code null}.
* @see javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate
*/
public abstract <T> HeaderDelegate<T> createHeaderDelegate(Class<T> type)
throws IllegalArgumentException;
Defines the contract for a delegate that is responsible for converting between the String form of a HTTP header and the corresponding type T
. Type parameters: - <T> – an type that corresponds to the value of a HTTP header.
/**
* Defines the contract for a delegate that is responsible for
* converting between the String form of a HTTP header and
* the corresponding type {@code T}.
*
* @param <T> an type that corresponds to the value of a HTTP header.
*/
public static interface HeaderDelegate<T> {
Parse the supplied value and create an instance of T
. Params: - value – the string value.
Throws: - IllegalArgumentException – if the supplied string cannot be parsed or is
null
.
Returns: the newly created instance of T
.
/**
* Parse the supplied value and create an instance of {@code T}.
*
* @param value the string value.
* @return the newly created instance of {@code T}.
* @throws IllegalArgumentException if the supplied string cannot be
* parsed or is {@code null}.
*/
public T fromString(String value);
Convert the supplied value to a String.
Params: - value – the value of type
T
.
Throws: - IllegalArgumentException – if the supplied object cannot be serialized or is
null
.
Returns: a String representation of the value.
/**
* Convert the supplied value to a String.
*
* @param value the value of type {@code T}.
* @return a String representation of the value.
* @throws IllegalArgumentException if the supplied object cannot be
* serialized or is {@code null}.
*/
public String toString(T value);
}
Create a new instance of a Builder
. See Also: Returns: new Link.Builder
instance.
/**
* Create a new instance of a {@link javax.ws.rs.core.Link.Builder}.
*
* @return new {@code Link.Builder} instance.
* @see javax.ws.rs.core.Link.Builder
*/
public abstract Link.Builder createLinkBuilder();
}