Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit 1840c67

Browse files
committed
JERSEY-2707: char cannot be used as the type of a @*Param
Added ValueExtractor and ParamConverter for char and Character types. Change-Id: If066ee537103a521874aacade320c5371d023969
1 parent be48eeb commit 1840c67

File tree

9 files changed

+503
-9
lines changed

9 files changed

+503
-9
lines changed

core-server/src/main/java/org/glassfish/jersey/server/internal/inject/MultivaluedParameterExtractorFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ private MultivaluedParameterExtractor<?> process(
153153

154154
if (rawType == String.class) {
155155
return new SingleStringValueExtractor(parameterName, defaultValue);
156+
} else if(rawType == Character.class) {
157+
Object defaultDefaultValue = PrimitiveMapper.primitiveToDefaultValueMap.get(rawType);
158+
return new PrimitiveCharacterExtractor(parameterName, defaultValue, defaultDefaultValue);
156159
} else if (rawType.isPrimitive()) {
157160
// Convert primitive to wrapper class
158161
rawType = PrimitiveMapper.primitiveToClassMap.get(rawType);
@@ -161,6 +164,11 @@ private MultivaluedParameterExtractor<?> process(
161164
return null;
162165
}
163166

167+
if(rawType == Character.class) {
168+
Object defaultDefaultValue = PrimitiveMapper.primitiveToDefaultValueMap.get(rawType);
169+
return new PrimitiveCharacterExtractor(parameterName, defaultValue, defaultDefaultValue);
170+
}
171+
164172
// Check for static valueOf(String )
165173
Method valueOf = AccessController.doPrivileged(ReflectionHelper.getValueOfStringMethodPA(rawType));
166174
if (valueOf != null) {

core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ParamConverters.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.glassfish.jersey.internal.inject.ExtractorException;
6060
import org.glassfish.jersey.internal.util.ReflectionHelper;
6161
import org.glassfish.jersey.message.internal.HttpDateFormat;
62+
import org.glassfish.jersey.server.internal.LocalizationMessages;
6263

6364
import org.glassfish.hk2.api.ServiceLocator;
6465

@@ -78,7 +79,7 @@ private static abstract class AbstractStringReader<T> implements ParamConverter<
7879
@Override
7980
public T fromString(final String value) {
8081
if (value == null) {
81-
throw new IllegalArgumentException("Supplied value is null");
82+
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
8283
}
8384
try {
8485
return _fromString(value);
@@ -102,6 +103,9 @@ public T fromString(final String value) {
102103

103104
@Override
104105
public String toString(final T value) throws IllegalArgumentException {
106+
if(value == null) {
107+
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
108+
}
105109
return value.toString();
106110
}
107111

@@ -187,6 +191,40 @@ public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type gen
187191
}
188192
}
189193

194+
@Singleton
195+
public static class CharacterProvider implements ParamConverterProvider {
196+
@Override
197+
public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType, final Annotation[] annotations) {
198+
if(rawType.equals(Character.class)) {
199+
return new ParamConverter<T>() {
200+
@Override
201+
public T fromString(String value) {
202+
if(value == null || value.isEmpty()) {
203+
return null;
204+
// throw new IllegalStateException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
205+
}
206+
207+
if(value.length() == 1) {
208+
return rawType.cast(value.charAt(0));
209+
}
210+
211+
throw new ExtractorException(LocalizationMessages.ERROR_PARAMETER_INVALID_CHAR_VALUE(value));
212+
}
213+
214+
@Override
215+
public String toString(T value) {
216+
if(value == null) {
217+
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
218+
}
219+
return value.toString();
220+
}
221+
};
222+
}
223+
224+
return null;
225+
}
226+
}
227+
190228
/**
191229
* Provider of {@link ParamConverter param converter} that convert the supplied string into a Java
192230
* {@link Date} instance using conversion method from the
@@ -202,7 +240,7 @@ public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type gen
202240
@Override
203241
public T fromString(final String value) {
204242
if (value == null) {
205-
throw new IllegalArgumentException("Supplied value is null");
243+
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
206244
}
207245
try {
208246
return rawType.cast(HttpDateFormat.readDate(value));
@@ -213,6 +251,9 @@ public T fromString(final String value) {
213251

214252
@Override
215253
public String toString(final T value) throws IllegalArgumentException {
254+
if(value == null) {
255+
throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
256+
}
216257
return value.toString();
217258
}
218259
};
@@ -239,6 +280,7 @@ public AggregatedProvider(@Context final ServiceLocator locator) {
239280
locator.createAndInitialize(DateProvider.class),
240281
locator.createAndInitialize(TypeFromStringEnum.class),
241282
locator.createAndInitialize(TypeValueOf.class),
283+
locator.createAndInitialize(CharacterProvider.class),
242284
locator.createAndInitialize(TypeFromString.class),
243285
locator.createAndInitialize(StringConstructor.class),
244286
};
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* The contents of this file are subject to the terms of either the GNU
7+
* General Public License Version 2 only ("GPL") or the Common Development
8+
* and Distribution License("CDDL") (collectively, the "License"). You
9+
* may not use this file except in compliance with the License. You can
10+
* obtain a copy of the License at
11+
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
12+
* or packager/legal/LICENSE.txt. See the License for the specific
13+
* language governing permissions and limitations under the License.
14+
*
15+
* When distributing the software, include this License Header Notice in each
16+
* file and include the License file at packager/legal/LICENSE.txt.
17+
*
18+
* GPL Classpath Exception:
19+
* Oracle designates this particular file as subject to the "Classpath"
20+
* exception as provided by Oracle in the GPL Version 2 section of the License
21+
* file that accompanied this code.
22+
*
23+
* Modifications:
24+
* If applicable, add the following below the License Header, with the fields
25+
* enclosed by brackets [] replaced by your own identifying information:
26+
* "Portions Copyright [year] [name of copyright owner]"
27+
*
28+
* Contributor(s):
29+
* If you wish your version of this file to be governed by only the CDDL or
30+
* only the GPL Version 2, indicate your decision by adding "[Contributor]
31+
* elects to include this software in this distribution under the [CDDL or GPL
32+
* Version 2] license." If you don't indicate a single choice of license, a
33+
* recipient has the option to distribute your version of this file under
34+
* either the CDDL, the GPL Version 2 or to extend the choice of license to
35+
* its licensees as provided above. However, if you add GPL Version 2 code
36+
* and therefore, elected the GPL Version 2 license, then the option applies
37+
* only if the new code is made subject to such option by the copyright
38+
* holder.
39+
*/
40+
41+
package org.glassfish.jersey.server.internal.inject;
42+
43+
import javax.ws.rs.core.MultivaluedMap;
44+
45+
import org.glassfish.jersey.internal.inject.ExtractorException;
46+
import org.glassfish.jersey.server.internal.LocalizationMessages;
47+
48+
/**
49+
* Value extractor for {@link java.lang.Character} and {@code char} parameters.
50+
*
51+
* @author Pavel Bucek (pavel.bucek at oracle.com)
52+
*/
53+
class PrimitiveCharacterExtractor implements MultivaluedParameterExtractor<Object> {
54+
55+
final String parameter;
56+
final String defaultStringValue;
57+
final Object defaultPrimitiveTypeValue;
58+
59+
public PrimitiveCharacterExtractor(String parameter, String defaultStringValue, Object defaultPrimitiveTypeValue) {
60+
this.parameter = parameter;
61+
this.defaultStringValue = defaultStringValue;
62+
this.defaultPrimitiveTypeValue = defaultPrimitiveTypeValue;
63+
}
64+
65+
@Override
66+
public String getName() {
67+
return parameter;
68+
}
69+
70+
@Override
71+
public String getDefaultValueString() {
72+
return defaultStringValue;
73+
}
74+
75+
@Override
76+
public Object extract(MultivaluedMap<String, String> parameters) {
77+
String v = parameters.getFirst(parameter);
78+
if (v != null && !v.trim().isEmpty()) {
79+
if(v.length() == 1) {
80+
return v.charAt(0);
81+
} else {
82+
throw new ExtractorException(LocalizationMessages.ERROR_PARAMETER_INVALID_CHAR_VALUE(v));
83+
}
84+
} else if (defaultStringValue != null && !defaultStringValue.trim().isEmpty()) {
85+
if(defaultStringValue.length() == 1) {
86+
return defaultStringValue.charAt(0);
87+
} else {
88+
throw new ExtractorException(LocalizationMessages.ERROR_PARAMETER_INVALID_CHAR_VALUE(defaultStringValue));
89+
}
90+
}
91+
92+
return defaultPrimitiveTypeValue;
93+
}
94+
}

core-server/src/main/java/org/glassfish/jersey/server/internal/inject/PrimitiveMapper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2010-2012 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2010-2015 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -63,6 +63,7 @@ private static Map<Class, Class> getPrimitiveToClassMap() {
6363
// that for Character
6464
m.put(Boolean.TYPE, Boolean.class);
6565
m.put(Byte.TYPE, Byte.class);
66+
m.put(Character.TYPE, Character.class);
6667
m.put(Short.TYPE, Short.class);
6768
m.put(Integer.TYPE, Integer.class);
6869
m.put(Long.TYPE, Long.class);
@@ -76,6 +77,7 @@ private static Map<Class, Object> getPrimitiveToDefaultValueMap() {
7677
Map<Class, Object> m = new WeakHashMap<Class, Object>();
7778
m.put(Boolean.class, Boolean.valueOf(false));
7879
m.put(Byte.class, Byte.valueOf((byte) 0));
80+
m.put(Character.class, Character.valueOf((char)0x00));
7981
m.put(Short.class, Short.valueOf((short) 0));
8082
m.put(Integer.class, Integer.valueOf(0));
8183
m.put(Long.class, Long.valueOf(0l));

core-server/src/main/resources/org/glassfish/jersey/server/internal/localization.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ error.monitoring.queue.response=Failed to add the monitoring event into the Resp
8181
registered MonitoringStatisticsListeners might be blocking the event processing.
8282
error.monitoring.queue.mapper=Failed to add the monitoring event into the Exception Mapper Events Queue - queue is full. One of \
8383
the registered MonitoringStatisticsListeners might be blocking the event processing.
84+
error.parameter.invalid.char.value=Value "{0}" is not a character.
8485
error.parameter.missing.value.provider=No injection source found for a parameter of type {1} at index {0}.
8586
error.primitive.type.null=The request entity cannot be empty.
8687
error.processing.method=Error processing resource method, {0}, for ResourceMethodDispatchProvider, {1}.

0 commit comments

Comments
 (0)