File: RuntimeDelegate.java

package info (click to toggle)
libjsr311-api-java 1.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 420 kB
  • sloc: java: 1,547; xml: 166; makefile: 9
file content (218 lines) | stat: -rw-r--r-- 8,690 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
 * 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);
    }
}