| /* |
| * The contents of this file are subject to the terms |
| * of the Common Development and Distribution License |
| * (the "License"). You may not use this file except |
| * in compliance with the License. |
| * |
| * You can obtain a copy of the license at |
| * http://www.opensource.org/licenses/cddl1.php |
| * See the License for the specific language governing |
| * permissions and limitations under the License. |
| */ |
| |
| /* |
| * RuntimeDelegate.java |
| * |
| * Created on November 15, 2007, 4:00 PM |
| * |
| */ |
| |
| package javax.ws.rs.ext; |
| |
| import java.lang.reflect.ReflectPermission; |
| import java.net.URL; |
| import javax.ws.rs.core.Application; |
| import javax.ws.rs.core.Response.ResponseBuilder; |
| import javax.ws.rs.core.Variant.VariantListBuilder; |
| import javax.ws.rs.core.UriBuilder; |
| |
| /** |
| * Implementations of JAX-RS provide a concrete subclass of RuntimeDelegate and |
| * various JAX-RS API methods defer to methods of RuntimeDelegate for their |
| * functionality. Regular users of JAX-RS are not expected to use this class |
| * directly and overriding an implementation of this class with a user supplied |
| * subclass may cause unexpected behavior. |
| * |
| */ |
| public abstract class RuntimeDelegate { |
| |
| public static final String JAXRS_RUNTIME_DELEGATE_PROPERTY |
| = "javax.ws.rs.ext.RuntimeDelegate"; |
| private static final String JAXRS_DEFAULT_RUNTIME_DELEGATE |
| = "com.sun.ws.rs.ext.RuntimeDelegateImpl"; |
| |
| private static ReflectPermission rp = new ReflectPermission("suppressAccessChecks"); |
| |
| protected RuntimeDelegate() { |
| } |
| |
| private static volatile RuntimeDelegate rd; |
| |
| /** |
| * Obtain a RuntimeDelegate instance. If an instance had not already been |
| * created and set via {@link #setInstance}, 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</code> |
| * 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)</code> method and it contains |
| * an entry whose key is <code>javax.ws.rs.ext.RuntimeDelegate</code>, 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</code> |
| * 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 RuntimeDelegate |
| */ |
| public static RuntimeDelegate getInstance() { |
| // Double-check idiom for lazy initialization of fields. |
| RuntimeDelegate result = rd; |
| if (result == null) { // First check (no locking) |
| synchronized(RuntimeDelegate.class) { |
| result = rd; |
| if (result == null) { // Second check (with locking) |
| rd = result = findDelegate(); |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Obtain a RuntimeDelegate instance using the method described in |
| * {@link #getInstance}. |
| * @return an instance of RuntimeDelegate |
| */ |
| private static RuntimeDelegate findDelegate() { |
| try { |
| Object delegate = |
| FactoryFinder.find(JAXRS_RUNTIME_DELEGATE_PROPERTY, |
| JAXRS_DEFAULT_RUNTIME_DELEGATE); |
| 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.toString() ); |
| } |
| return (RuntimeDelegate) delegate; |
| } catch (Exception ex) { |
| throw new RuntimeException(ex); |
| } |
| } |
| |
| /** |
| * Set the runtime delegate that will be used by JAX-RS 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(RuntimeDelegate rd) throws SecurityException { |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| security.checkPermission(rp); |
| } |
| synchronized(RuntimeDelegate.class) { |
| RuntimeDelegate.rd = rd; |
| } |
| } |
| |
| /** |
| * Create a new instance of a {@link javax.ws.rs.core.UriBuilder}. |
| * @return new UriBuilder instance |
| * @see javax.ws.rs.core.UriBuilder |
| */ |
| public abstract UriBuilder createUriBuilder(); |
| |
| /** |
| * Create a new instance of a {@link javax.ws.rs.core.Response.ResponseBuilder}. |
| * @return new ResponseBuilder instance |
| * @see javax.ws.rs.core.Response.ResponseBuilder |
| */ |
| public abstract ResponseBuilder createResponseBuilder(); |
| |
| /** |
| * Create a new instance of a {@link javax.ws.rs.core.Variant.VariantListBuilder}. |
| * |
| * @return new 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. |
| * @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: |
| * {@link javax.ws.rs.core.Cookie}, {@link javax.ws.rs.core.CacheControl}, |
| * {@link javax.ws.rs.core.EntityTag}, {@link javax.ws.rs.core.NewCookie}, |
| * {@link javax.ws.rs.core.MediaType} and {@code java.util.Date}. |
| * @param type the class of the header |
| * @return an instance of HeaderDelegate for the supplied type |
| * @throws java.lang.IllegalArgumentException if type is null |
| */ |
| public abstract <T> HeaderDelegate<T> createHeaderDelegate(Class<T> type); |
| |
| /** |
| * Defines the contract for a delegate that is responsible for |
| * converting between the String form of a HTTP header and |
| * the corresponding JAX-RS type <code>T</code>. |
| * @param T a JAX-RS type that corresponds to the value of a HTTP header |
| */ |
| public static interface HeaderDelegate<T> { |
| /** |
| * Parse the supplied value and create an instance of <code>T</code>. |
| * @param value the string value |
| * @return the newly created instance of <code>T</code> |
| * @throws IllegalArgumentException if the supplied string cannot be |
| * parsed or is null |
| */ |
| public T fromString(String value) throws IllegalArgumentException; |
| |
| /** |
| * Convert the supplied value to a String. |
| * @param value the value of type <code>T</code> |
| * @return a String representation of the value |
| * @throws IllegalArgumentException if the supplied object cannot be |
| * serialized or is null |
| */ |
| public String toString(T value); |
| } |
| } |