1 /*******************************************************************************
2  * Copyright (c) 2015, 2019 Raymond Augé and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Raymond Augé - bug fixes and enhancements
13  ******************************************************************************/
14 
15 package org.eclipse.equinox.http.servlet.internal.util;
16 
17 import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.*;
18 
19 import java.lang.reflect.Array;
20 import java.util.*;
21 import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO;
22 import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO.ErrorCodeType;
23 import org.eclipse.equinox.http.servlet.internal.error.HttpWhiteboardFailureException;
24 import org.osgi.dto.DTO;
25 import org.osgi.framework.Constants;
26 import org.osgi.framework.ServiceReference;
27 import org.osgi.service.http.runtime.dto.*;
28 
29 /**
30  * @author Raymond Augé
31  */
32 public class DTOUtil {
33 
assembleErrorPageDTO(ServiceReference<?> serviceReference, long contextId, boolean validated)34 	public static ExtendedErrorPageDTO assembleErrorPageDTO(ServiceReference<?> serviceReference, long contextId, boolean validated) {
35 		Object errorPageObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_ERROR_PAGE);
36 
37 		if (errorPageObj == null) {
38 			return null;
39 		}
40 
41 		ExtendedErrorPageDTO errorPageDTO = new ExtendedErrorPageDTO();
42 
43 		errorPageDTO.asyncSupported = false;
44 		Object asyncSupportedObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED);
45 		if (asyncSupportedObj == null) {
46 			// ignored
47 		}
48 		else if (Boolean.class.isInstance(asyncSupportedObj)) {
49 			errorPageDTO.asyncSupported = ((Boolean)asyncSupportedObj).booleanValue();
50 		}
51 		else if (String.class.isInstance(asyncSupportedObj)) {
52 			errorPageDTO.asyncSupported = Boolean.valueOf((String)asyncSupportedObj);
53 		}
54 		// There is no validation for this scenario, truthiness of any other input is false
55 
56 		List<String> errorPages = StringPlus.from(errorPageObj);
57 		if (errorPages.isEmpty()) {
58 			throw new HttpWhiteboardFailureException("'errorPage' expects String, String[] or Collection<String>", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
59 		}
60 
61 		List<String> exceptions = new ArrayList<String>();
62 		Set<Long> errorCodeSet = new LinkedHashSet<Long>();
63 
64 		for(String errorPage : errorPages) {
65 			try {
66 				if ("4xx".equals(errorPage)) { //$NON-NLS-1$
67 					errorPageDTO.errorCodeType = ErrorCodeType.RANGE_4XX;
68 					for (long code = 400; code < 500; code++) {
69 						errorCodeSet.add(code);
70 					}
71 				} else if ("5xx".equals(errorPage)) { //$NON-NLS-1$
72 					errorPageDTO.errorCodeType = ErrorCodeType.RANGE_5XX;
73 					for (long code = 500; code < 600; code++) {
74 						errorCodeSet.add(code);
75 					}
76 				} else if (errorPage.matches("\\d{3}")) { //$NON-NLS-1$
77 					errorPageDTO.errorCodeType = ErrorCodeType.SPECIFIC;
78 					long code = Long.parseLong(errorPage);
79 					errorCodeSet.add(code);
80 				} else {
81 					exceptions.add(errorPage);
82 				}
83 			}
84 			catch (NumberFormatException nfe) {
85 				exceptions.add(errorPage);
86 			}
87 		}
88 
89 		errorPageDTO.errorCodes = new long[errorCodeSet.size()];
90 		int i = 0;
91 		for(Long code : errorCodeSet) {
92 			errorPageDTO.errorCodes[i] = code;
93 			i++;
94 		}
95 
96 		errorPageDTO.exceptions = exceptions.toArray(new String[0]);
97 
98 		errorPageDTO.initParams = ServiceProperties.parseInitParams(
99 			serviceReference, HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX);
100 
101 		Object servletNameObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_NAME);
102 		if (servletNameObj == null) {
103 			// ignore
104 		}
105 		else if (String.class.isInstance(servletNameObj)) {
106 			errorPageDTO.name = (String)servletNameObj;
107 		}
108 		else if (validated) {
109 			throw new HttpWhiteboardFailureException("'name' expects String", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
110 		}
111 
112 		errorPageDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID);
113 		errorPageDTO.servletContextId = contextId;
114 
115 		return errorPageDTO;
116 	}
117 
118 	@SuppressWarnings("deprecation")
assembleServletDTO(ServiceReference<?> serviceReference, long contextId, boolean validated)119 	public static org.eclipse.equinox.http.servlet.dto.ExtendedServletDTO assembleServletDTO(ServiceReference<?> serviceReference, long contextId, boolean validated) {
120 		org.eclipse.equinox.http.servlet.dto.ExtendedServletDTO servletDTO = new org.eclipse.equinox.http.servlet.dto.ExtendedServletDTO();
121 
122 		servletDTO.asyncSupported = false;
123 		Object asyncSupportedObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED);
124 		if (asyncSupportedObj == null) {
125 			// ignored
126 		}
127 		else if (Boolean.class.isInstance(asyncSupportedObj)) {
128 			servletDTO.asyncSupported = ((Boolean)asyncSupportedObj).booleanValue();
129 		}
130 		else if (String.class.isInstance(asyncSupportedObj)) {
131 			servletDTO.asyncSupported = Boolean.valueOf((String)asyncSupportedObj);
132 		}
133 		// There is no validation for this scenario, truthiness of any other input is false
134 
135 		servletDTO.initParams = ServiceProperties.parseInitParams(
136 			serviceReference, HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX);
137 
138 		servletDTO.multipartEnabled = false;
139 		Object multipartEnabledObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_MULTIPART_ENABLED);
140 		if (multipartEnabledObj == null) {
141 			multipartEnabledObj = serviceReference.getProperty(Const.EQUINOX_HTTP_MULTIPART_ENABLED);
142 		}
143 		if (multipartEnabledObj == null) {
144 			// ignore
145 		}
146 		else if (Boolean.class.isInstance(multipartEnabledObj)) {
147 			servletDTO.multipartEnabled = ((Boolean)multipartEnabledObj).booleanValue();
148 		}
149 		else if (String.class.isInstance(multipartEnabledObj)) {
150 			servletDTO.multipartEnabled = Boolean.valueOf((String)multipartEnabledObj);
151 		}
152 		// There is no validation for this scenario, truthiness of any other input is false
153 
154 		servletDTO.multipartFileSizeThreshold = 0;
155 		servletDTO.multipartLocation = Const.BLANK;
156 		servletDTO.multipartMaxFileSize = -1L;
157 		servletDTO.multipartMaxRequestSize = -1L;
158 
159 		if (servletDTO.multipartEnabled) {
160 			Object multipartFileSizeThresholdObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_MULTIPART_FILESIZETHRESHOLD);
161 			if (multipartFileSizeThresholdObj == null) {
162 				multipartFileSizeThresholdObj = serviceReference.getProperty(Const.EQUINOX_HTTP_MULTIPART_FILESIZETHRESHOLD);
163 			}
164 			if (multipartFileSizeThresholdObj == null) {
165 				// ignore
166 			}
167 			else if (Integer.class.isInstance(multipartFileSizeThresholdObj)) {
168 				servletDTO.multipartFileSizeThreshold = ((Integer)multipartFileSizeThresholdObj).intValue();
169 			}
170 			else if (validated) {
171 				throw new HttpWhiteboardFailureException("'multipartFileSizeThreshold' expects int or Integer", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
172 			}
173 
174 			Object multipartLocationObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_MULTIPART_LOCATION);
175 			if (multipartLocationObj == null) {
176 				multipartLocationObj = serviceReference.getProperty(Const.EQUINOX_HTTP_MULTIPART_LOCATION);
177 			}
178 			if (multipartLocationObj == null) {
179 				// ignore
180 			}
181 			else if (String.class.isInstance(multipartLocationObj)) {
182 				servletDTO.multipartLocation = (String)multipartLocationObj;
183 			}
184 			else if (validated) {
185 				throw new HttpWhiteboardFailureException("'multipartLocation' expects String", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
186 			}
187 
188 			Object multipartMaxFileSizeObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_MULTIPART_MAXFILESIZE);
189 			if (multipartMaxFileSizeObj == null) {
190 				multipartMaxFileSizeObj = serviceReference.getProperty(Const.EQUINOX_HTTP_MULTIPART_MAXFILESIZE);
191 			}
192 			if (multipartMaxFileSizeObj == null) {
193 				// ignore
194 			}
195 			else if (Long.class.isInstance(multipartMaxFileSizeObj)) {
196 				servletDTO.multipartMaxFileSize = ((Long)multipartMaxFileSizeObj).longValue();
197 			}
198 			else if (validated) {
199 				throw new HttpWhiteboardFailureException("'multipartMaxFileSize' expects [L|l]ong", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
200 			}
201 
202 			Object multipartMaxRequestSizeObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_MULTIPART_MAXREQUESTSIZE);
203 			if (multipartMaxRequestSizeObj == null) {
204 				multipartMaxRequestSizeObj = serviceReference.getProperty(Const.EQUINOX_HTTP_MULTIPART_MAXREQUESTSIZE);
205 			}
206 			if (multipartMaxRequestSizeObj == null) {
207 				// ignore
208 			}
209 			else if (Long.class.isInstance(multipartMaxRequestSizeObj)) {
210 				servletDTO.multipartMaxRequestSize = ((Long)multipartMaxRequestSizeObj).longValue();
211 			}
212 			else if (validated) {
213 				throw new HttpWhiteboardFailureException("'multipartMaxRequestSize' expects [L|l]ong", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
214 			}
215 		}
216 
217 		Object servletNameObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_NAME);
218 		if (servletNameObj == null) {
219 			// ignore
220 		}
221 		else if (String.class.isInstance(servletNameObj)) {
222 			servletDTO.name = (String)servletNameObj;
223 		}
224 		else if (validated) {
225 			throw new HttpWhiteboardFailureException("'name' expects String", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
226 		}
227 
228 		Object patternObj = serviceReference.getProperty(HTTP_WHITEBOARD_SERVLET_PATTERN);
229 		if (patternObj == null) {
230 			servletDTO.patterns = new String[0];
231 		}
232 		else {
233 			servletDTO.patterns = sort(StringPlus.from(patternObj).toArray(new String[0]));
234 
235 			if (validated && (servletDTO.patterns.length > 0)) {
236 				for (String pattern : servletDTO.patterns) {
237 					checkPattern(pattern);
238 				}
239 			}
240 		}
241 
242 		servletDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID);
243 		servletDTO.servletContextId = contextId;
244 
245 		return servletDTO;
246 	}
247 
clone(ErrorPageDTO original)248 	public static ErrorPageDTO clone(ErrorPageDTO original) {
249 		ErrorPageDTO clone = new ErrorPageDTO();
250 
251 		clone.asyncSupported = copy(original.asyncSupported);
252 		clone.errorCodes = copy(original.errorCodes);
253 		clone.exceptions = copy(original.exceptions);
254 		clone.initParams = copyStringMap(original.initParams);
255 		clone.name = copy(original.name);
256 		clone.serviceId = copy(original.serviceId);
257 		clone.servletContextId = copy(original.servletContextId);
258 		clone.servletInfo = copy(original.servletInfo);
259 
260 		return clone;
261 	}
262 
clone(FailedErrorPageDTO original)263 	public static FailedErrorPageDTO clone(FailedErrorPageDTO original) {
264 		FailedErrorPageDTO clone = new FailedErrorPageDTO();
265 
266 		clone.asyncSupported = copy(original.asyncSupported);
267 		clone.errorCodes = copy(original.errorCodes);
268 		clone.exceptions = copy(original.exceptions);
269 		clone.failureReason = copy(original.failureReason);
270 		clone.initParams = copyStringMap(original.initParams);
271 		clone.name = copy(original.name);
272 		clone.serviceId = copy(original.serviceId);
273 		clone.servletContextId = copy(original.servletContextId);
274 		clone.servletInfo = copy(original.servletInfo);
275 
276 		return clone;
277 	}
278 
clone(FailedFilterDTO original)279 	public static FailedFilterDTO clone(FailedFilterDTO original) {
280 		FailedFilterDTO clone = new FailedFilterDTO();
281 
282 		clone.asyncSupported = copy(original.asyncSupported);
283 		clone.dispatcher = copy(original.dispatcher);
284 		clone.failureReason = copy(original.failureReason);
285 		clone.initParams = copyStringMap(original.initParams);
286 		clone.name = copy(original.name);
287 		clone.patterns = copy(original.patterns);
288 		clone.regexs = copy(original.regexs);
289 		clone.serviceId = copy(original.serviceId);
290 		clone.servletContextId = copy(original.servletContextId);
291 		clone.servletNames = copy(original.servletNames);
292 
293 		return clone;
294 	}
295 
clone(FailedListenerDTO original)296 	public static FailedListenerDTO clone(FailedListenerDTO original) {
297 		FailedListenerDTO clone = new FailedListenerDTO();
298 
299 		clone.failureReason = copy(original.failureReason);
300 		clone.serviceId = copy(original.serviceId);
301 		clone.servletContextId = copy(original.servletContextId);
302 		clone.types = copy(original.types);
303 
304 		return clone;
305 	}
306 
clone(FailedPreprocessorDTO original)307 	public static FailedPreprocessorDTO clone(FailedPreprocessorDTO original) {
308 		FailedPreprocessorDTO clone = new FailedPreprocessorDTO();
309 
310 		clone.failureReason = copy(original.failureReason);
311 		clone.initParams = copyStringMap(original.initParams);
312 		clone.serviceId = copy(original.serviceId);
313 
314 		return clone;
315 	}
316 
clone(FailedResourceDTO original)317 	public static FailedResourceDTO clone(FailedResourceDTO original) {
318 		FailedResourceDTO clone = new FailedResourceDTO();
319 
320 		clone.failureReason = copy(original.failureReason);
321 		clone.patterns = copy(original.patterns);
322 		clone.prefix = copy(original.prefix);
323 		clone.serviceId = copy(original.serviceId);
324 		clone.servletContextId = copy(original.servletContextId);
325 
326 		return clone;
327 	}
328 
clone(FailedServletContextDTO original)329 	public static FailedServletContextDTO clone(FailedServletContextDTO original) {
330 		FailedServletContextDTO clone = new FailedServletContextDTO();
331 
332 		clone.attributes = copyGenericMap(original.attributes);
333 		clone.contextPath = copy(original.contextPath);
334 		clone.errorPageDTOs = copy(original.errorPageDTOs);
335 		clone.failureReason = copy(original.failureReason);
336 		clone.filterDTOs = copy(original.filterDTOs);
337 		clone.initParams = copyStringMap(original.initParams);
338 		clone.listenerDTOs = copy(original.listenerDTOs);
339 		clone.name = copy(original.name);
340 		clone.resourceDTOs = copy(original.resourceDTOs);
341 		clone.serviceId = copy(original.serviceId);
342 		clone.servletDTOs = copy(original.servletDTOs);
343 
344 		return clone;
345 	}
346 
clone(FailedServletDTO original)347 	public static FailedServletDTO clone(FailedServletDTO original) {
348 		FailedServletDTO clone = new FailedServletDTO();
349 
350 		clone.asyncSupported = copy(original.asyncSupported);
351 		clone.failureReason = copy(original.failureReason);
352 		clone.initParams = copyStringMap(clone.initParams);
353 		clone.multipartEnabled = copy(original.multipartEnabled);
354 		clone.multipartFileSizeThreshold = copy(original.multipartFileSizeThreshold);
355 		clone.multipartLocation = copy(original.multipartLocation);
356 		clone.multipartMaxFileSize = copy(original.multipartMaxFileSize);
357 		clone.multipartMaxRequestSize = copy(original.multipartMaxRequestSize);
358 		clone.name = copy(original.name);
359 		clone.patterns = copy(original.patterns);
360 		clone.serviceId = copy(original.serviceId);
361 		clone.servletContextId = copy(original.servletContextId);
362 		clone.servletInfo = copy(original.servletInfo);
363 
364 		return clone;
365 	}
366 
clone(FilterDTO original)367 	public static FilterDTO clone(FilterDTO original) {
368 		FilterDTO clone = new FilterDTO();
369 
370 		clone.asyncSupported = copy(original.asyncSupported);
371 		clone.dispatcher = copy(original.dispatcher);
372 		clone.initParams = copyStringMap(original.initParams);
373 		clone.name = copy(original.name);
374 		clone.patterns = copy(original.patterns);
375 		clone.regexs = copy(original.regexs);
376 		clone.serviceId = copy(original.serviceId);
377 		clone.servletContextId = copy(original.servletContextId);
378 		clone.servletNames = copy(original.servletNames);
379 
380 		return clone;
381 	}
382 
clone(ListenerDTO original)383 	public static ListenerDTO clone(ListenerDTO original) {
384 		ListenerDTO clone = new ListenerDTO();
385 
386 		clone.serviceId = copy(original.serviceId);
387 		clone.servletContextId = copy(original.servletContextId);
388 		clone.types = copy(original.types);
389 
390 		return clone;
391 	}
392 
clone(ResourceDTO original)393 	public static ResourceDTO clone(ResourceDTO original) {
394 		ResourceDTO clone = new ResourceDTO();
395 
396 		clone.patterns = copy(original.patterns);
397 		clone.prefix = copy(original.prefix);
398 		clone.serviceId = copy(original.serviceId);
399 		clone.servletContextId = copy(original.servletContextId);
400 
401 		return clone;
402 	}
403 
clone(ServletDTO original)404 	public static ServletDTO clone(ServletDTO original) {
405 		ServletDTO clone = new ServletDTO();
406 
407 		clone.asyncSupported = copy(original.asyncSupported);
408 		clone.initParams = copyStringMap(original.initParams);
409 		clone.multipartEnabled = copy(original.multipartEnabled);
410 		clone.multipartFileSizeThreshold = copy(original.multipartFileSizeThreshold);
411 		clone.multipartLocation = copy(original.multipartLocation);
412 		clone.multipartMaxFileSize = copy(original.multipartMaxFileSize);
413 		clone.multipartMaxRequestSize = copy(original.multipartMaxRequestSize);
414 		clone.name = copy(original.name);
415 		clone.patterns = copy(original.patterns);
416 		clone.serviceId = copy(original.serviceId);
417 		clone.servletContextId = copy(original.servletContextId);
418 		clone.servletInfo = copy(original.servletInfo);
419 
420 		return clone;
421 	}
422 
copy(long[] array)423 	private static long[] copy(long[] array) {
424 		if (array == null) {
425 			return new long[0];
426 		}
427 		if (array.length == 0) {
428 			return array;
429 		}
430 		return Arrays.copyOf(array, array.length);
431 	}
432 
433 
copy(String[] array)434 	private static String[] copy(String[] array) {
435 		if (array == null) {
436 			return new String[0];
437 		}
438 		if (array.length == 0) {
439 			return array;
440 		}
441 		return Arrays.copyOf(array, array.length);
442 	}
443 
copy(T[] array)444 	private static <T> T[] copy(T[] array) {
445 		if (array == null) {
446 			return null;
447 		}
448 		if (array.length == 0) {
449 			return array;
450 		}
451 		return Arrays.copyOf(array, array.length);
452 	}
453 
copy(int value)454 	private static int copy(int value) {
455 		return value;
456 	}
457 
copy(long value)458 	private static long copy(long value) {
459 		return value;
460 	}
461 
copy(boolean value)462 	private static boolean copy(boolean value) {
463 		return value;
464 	}
465 
copy(String value)466 	private static String copy(String value) {
467 		return value;
468 	}
469 
copyStringMap(Map<String, String> initParams)470 	private static Map<String, String> copyStringMap(Map<String, String> initParams) {
471 		if (initParams == null) {
472 			return Collections.emptyMap();
473 		}
474 		return new HashMap<String, String>(initParams);
475 	}
476 
copyGenericMap(Map<String, V> value)477 	public static <V> Map<String, Object> copyGenericMap(Map<String, V> value) {
478 		if ((value == null) || value.isEmpty()) {
479 			return Collections.emptyMap();
480 		}
481 		HashMap<String, Object> result = new HashMap<String, Object>();
482 		for (Map.Entry<String, V> entry : value.entrySet()) {
483 			result.put(entry.getKey(), mapValue(entry.getValue()));
484 		}
485 		return result;
486 	}
487 
mapValue(Object v)488 	public static Object mapValue(Object v) {
489 		if ((v == null)
490 				|| v instanceof Number
491 				|| v instanceof Boolean
492 				|| v instanceof Character
493 				|| v instanceof String
494 				|| v instanceof DTO) {
495 			return v;
496 		}
497 		if (v instanceof Map) {
498 			Map<?, ?> m = (Map<?, ?>) v;
499 			Map<Object, Object> map = newMap(m.size());
500 			for (Map.Entry<?, ?> e : m.entrySet()) {
501 				map.put(mapValue(e.getKey()), mapValue(e.getValue()));
502 			}
503 			return map;
504 		}
505 		if (v instanceof List) {
506 			List<?> c = (List<?>) v;
507 			List<Object> list = newList(c.size());
508 			for (Object o : c) {
509 				list.add(mapValue(o));
510 			}
511 			return list;
512 		}
513 		if (v instanceof Set) {
514 			Set<?> c = (Set<?>) v;
515 			Set<Object> set = newSet(c.size());
516 			for (Object o : c) {
517 				set.add(mapValue(o));
518 			}
519 			return set;
520 		}
521 		if (v.getClass().isArray()) {
522 			final int length = Array.getLength(v);
523 			final Class<?> componentType = mapComponentType(v.getClass().getComponentType());
524 			Object array = Array.newInstance(componentType, length);
525 			for (int i = 0; i < length; i++) {
526 				Array.set(array, i, mapValue(Array.get(v, i)));
527 			}
528 			return array;
529 		}
530 		return String.valueOf(v);
531 	}
532 
checkPattern(String pattern)533 	private static void checkPattern(String pattern) {
534 		if (pattern == null) {
535 			throw new HttpWhiteboardFailureException("Pattern cannot be null", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$
536 		}
537 
538 		if (pattern.indexOf("*.") == 0) { //$NON-NLS-1$
539 			return;
540 		}
541 
542 		if (Const.BLANK.equals(pattern)) {
543 			return;
544 		}
545 
546 		if (Const.SLASH.equals(pattern)) {
547 			return;
548 		}
549 
550 		if (!pattern.startsWith(Const.SLASH) ||
551 			(pattern.endsWith(Const.SLASH) && !pattern.equals(Const.SLASH)) ||
552 			pattern.contains("**")) { //$NON-NLS-1$
553 
554 			throw new HttpWhiteboardFailureException(
555 				"Invalid pattern '" + pattern + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$
556 		}
557 	}
558 
mapComponentType(Class<?> componentType)559 	private static Class<?> mapComponentType(Class<?> componentType) {
560 		if (componentType.isPrimitive()
561 				|| componentType.isArray()
562 				|| Object.class.equals(componentType)
563 				|| Number.class.isAssignableFrom(componentType)
564 				|| Boolean.class.isAssignableFrom(componentType)
565 				|| Character.class.isAssignableFrom(componentType)
566 				|| String.class.isAssignableFrom(componentType)
567 				|| DTO.class.isAssignableFrom(componentType)) {
568 			return componentType;
569 		}
570 		if (Map.class.isAssignableFrom(componentType)) {
571 			return Map.class;
572 		}
573 		if (List.class.isAssignableFrom(componentType)) {
574 			return List.class;
575 		}
576 		if (Set.class.isAssignableFrom(componentType)) {
577 			return Set.class;
578 		}
579 		return String.class;
580 	}
581 
newList(int size)582 	private static <E> List<E> newList(int size) {
583 		return new ArrayList<E>(size);
584 	}
585 
newSet(int size)586 	private static <E> Set<E> newSet(int size) {
587 		return new HashSet<E>(size);
588 	}
589 
newMap(int size)590 	private static <K, V> Map<K, V> newMap(int size) {
591 		return new HashMap<K, V>(size);
592 	}
593 
sort(String[] values)594 	private static String[] sort(String[] values) {
595 		if (values == null) {
596 			return null;
597 		}
598 
599 		Arrays.sort(values);
600 
601 		return values;
602 	}
603 
604 }
605