/jboss-as-7.1.1.Final/webservices/server-integration/src/main/java/org/jboss/as/webservices/parser/WSDeploymentAspectParser.java
Java | 390 lines | 329 code | 20 blank | 41 comment | 78 complexity | 87e0aae7e5ba191a88983e6a8f18c6ff MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
1/*
2 * JBoss, Home of Professional Open Source.
3 * Copyright 2011, Red Hat Middleware LLC, and individual contributors
4 * as indicated by the @author tags. See the copyright.txt file in the
5 * distribution for a full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22package org.jboss.as.webservices.parser;
23
24import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
25import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
26import static org.jboss.as.webservices.WSMessages.MESSAGES;
27import static org.jboss.wsf.spi.util.StAXUtils.match;
28
29import java.io.InputStream;
30import java.lang.reflect.Method;
31import java.security.AccessController;
32import java.security.PrivilegedAction;
33import java.util.LinkedList;
34import java.util.List;
35import java.util.Map;
36
37import javax.xml.stream.XMLStreamConstants;
38import javax.xml.stream.XMLStreamException;
39import javax.xml.stream.XMLStreamReader;
40import javax.xml.ws.WebServiceException;
41
42import org.jboss.ws.common.JavaUtils;
43import org.jboss.wsf.spi.deployment.DeploymentAspect;
44import org.jboss.wsf.spi.util.StAXUtils;
45
46/**
47 * A parser for WS deployment aspects
48 *
49 * @author alessio.soldano@jboss.com
50 * @since 18-Jan-2011
51 *
52 */
53public class WSDeploymentAspectParser {
54
55 private static final String NS = "urn:jboss:ws:deployment:aspects:1.0";
56 private static final String DEPLOYMENT_ASPECTS = "deploymentAspects";
57 private static final String DEPLOYMENT_ASPECT = "deploymentAspect";
58 private static final String CLASS = "class";
59 private static final String PRIORITY = "priority";
60 private static final String PROPERTY = "property";
61 private static final String NAME = "name";
62 private static final String MAP = "map";
63 private static final String KEY_CLASS = "keyClass";
64 private static final String VALUE_CLASS = "valueClass";
65 private static final String ENTRY = "entry";
66 private static final String KEY = "key";
67 private static final String VALUE = "value";
68 private static final String LIST = "list";
69 private static final String ELEMENT_CLASS = "elementClass";
70
71 public static List<DeploymentAspect> parse(InputStream is, ClassLoader loader) {
72 try {
73 XMLStreamReader xmlr = StAXUtils.createXMLStreamReader(is);
74 return parse(xmlr, loader);
75 } catch (Exception e) {
76 throw new WebServiceException(e);
77 }
78 }
79
80 public static List<DeploymentAspect> parse(XMLStreamReader reader, ClassLoader loader) throws XMLStreamException {
81 int iterate;
82 try {
83 iterate = reader.nextTag();
84 } catch (XMLStreamException e) {
85 // skip non-tag elements
86 iterate = reader.nextTag();
87 }
88 List<DeploymentAspect> deploymentAspects = null;
89 switch (iterate) {
90 case END_ELEMENT: {
91 // we're done
92 break;
93 }
94 case START_ELEMENT: {
95
96 if (match(reader, NS, DEPLOYMENT_ASPECTS)) {
97 deploymentAspects = parseDeploymentAspects(reader, loader);
98 } else {
99 throw MESSAGES.unexpectedElement(reader.getLocalName());
100 }
101 }
102 }
103 return deploymentAspects;
104 }
105
106 private static List<DeploymentAspect> parseDeploymentAspects(XMLStreamReader reader, ClassLoader loader) throws XMLStreamException {
107 List<DeploymentAspect> deploymentAspects = new LinkedList<DeploymentAspect>();
108 while (reader.hasNext()) {
109 switch (reader.nextTag()) {
110 case XMLStreamConstants.END_ELEMENT: {
111 if (match(reader, NS, DEPLOYMENT_ASPECTS)) {
112 return deploymentAspects;
113 } else {
114 throw MESSAGES.unexpectedEndTag(reader.getLocalName());
115 }
116 }
117 case XMLStreamConstants.START_ELEMENT: {
118 if (match(reader, NS, DEPLOYMENT_ASPECT)) {
119 deploymentAspects.add(parseDeploymentAspect(reader, loader));
120 } else {
121 throw MESSAGES.unexpectedElement(reader.getLocalName());
122 }
123 }
124 }
125 }
126 throw MESSAGES.unexpectedEndOfDocument();
127 }
128
129 private static DeploymentAspect parseDeploymentAspect(XMLStreamReader reader, ClassLoader loader) throws XMLStreamException {
130 String deploymentAspectClass = reader.getAttributeValue(null, CLASS);
131 if (deploymentAspectClass == null) {
132 throw MESSAGES.missingDeploymentAspectClassAttribute();
133 }
134 DeploymentAspect deploymentAspect = null;
135 try {
136 @SuppressWarnings("unchecked")
137 Class<? extends DeploymentAspect> clazz = (Class<? extends DeploymentAspect>) Class.forName(deploymentAspectClass, true, loader);
138 ClassLoader orig = getContextClassLoader();
139 try {
140 setContextClassLoader(loader);
141 deploymentAspect = clazz.newInstance();
142 } finally {
143 setContextClassLoader(orig);
144 }
145 } catch (Exception e) {
146 throw MESSAGES.cannotInstantiateDeploymentAspect(e, deploymentAspectClass);
147 }
148 String priority = reader.getAttributeValue(null, PRIORITY);
149 if (priority != null) {
150 deploymentAspect.setRelativeOrder(Integer.parseInt(priority.trim()));
151 }
152 while (reader.hasNext()) {
153 switch (reader.nextTag()) {
154 case XMLStreamConstants.END_ELEMENT: {
155 if (match(reader, NS, DEPLOYMENT_ASPECT)) {
156 return deploymentAspect;
157 } else {
158 throw MESSAGES.unexpectedEndTag(reader.getLocalName());
159 }
160 }
161 case XMLStreamConstants.START_ELEMENT: {
162 if (match(reader, NS, PROPERTY)) {
163 parseProperty(reader, deploymentAspect, loader);
164 } else {
165 throw MESSAGES.unexpectedElement(reader.getLocalName());
166 }
167 }
168 }
169 }
170 throw MESSAGES.unexpectedEndOfDocument();
171 }
172
173 @SuppressWarnings("rawtypes")
174 private static void parseProperty(XMLStreamReader reader, DeploymentAspect deploymentAspect, ClassLoader loader) throws XMLStreamException {
175 Class<? extends DeploymentAspect> deploymentAspectClass = deploymentAspect.getClass();
176 String propName = reader.getAttributeValue(null, NAME);
177 if (propName == null) {
178 throw MESSAGES.missingPropertyNameAttribute(deploymentAspect);
179 }
180 String propClass = reader.getAttributeValue(null, CLASS);
181 if (propClass == null) {
182 throw MESSAGES.missingPropertyClassAttribute(deploymentAspect);
183 } else {
184 try {
185 if (isSupportedPropertyClass(propClass)) {
186 Method m = selectMethod(deploymentAspectClass, propName, propClass);
187 m.invoke(deploymentAspect, parseSimpleValue(reader, propClass));
188 return;
189 }
190 } catch (Exception e) {
191 throw new IllegalStateException(e);
192 }
193 }
194 while (reader.hasNext()) {
195 switch (reader.nextTag()) {
196 case XMLStreamConstants.END_ELEMENT: {
197 if (match(reader, NS, PROPERTY)) {
198 return;
199 } else {
200 throw MESSAGES.unexpectedEndTag(reader.getLocalName());
201 }
202 }
203 case XMLStreamConstants.START_ELEMENT: {
204 if (match(reader, NS, MAP)) {
205 try {
206 Method m = selectMethod(deploymentAspectClass, propName, propClass);
207 Map map = parseMapProperty(reader, propClass, reader.getAttributeValue(null, KEY_CLASS),
208 reader.getAttributeValue(null, VALUE_CLASS), loader);
209 m.invoke(deploymentAspect, map);
210 } catch (Exception e) {
211 throw new IllegalStateException(e);
212 }
213 } else if (match(reader, NS, LIST)) {
214 try {
215 Method m = selectMethod(deploymentAspectClass, propName, propClass);
216 List list = parseListProperty(reader, propClass, reader.getAttributeValue(null, ELEMENT_CLASS));
217 m.invoke(deploymentAspect, list);
218 } catch (Exception e) {
219 throw new IllegalStateException(e);
220 }
221 } else {
222 throw MESSAGES.unexpectedElement(reader.getLocalName());
223 }
224 }
225 }
226 }
227 throw MESSAGES.unexpectedEndOfDocument();
228 }
229
230 private static Method selectMethod(Class<?> deploymentAspectClass, String propName, String propClass) throws ClassNotFoundException {
231 //TODO improve this (better support for primitives, edge cases, etc.)
232 Method[] methods = deploymentAspectClass.getMethods();
233 for (Method m : methods) {
234 if (m.getName().equals("set" + JavaUtils.capitalize(propName))) {
235 Class<?>[] pars = m.getParameterTypes();
236 if (pars.length == 1 && (propClass.equals(pars[0].getName()) || (pars[0].isAssignableFrom(Class.forName(propClass))))) {
237 return m;
238 }
239 }
240 }
241 return null;
242 }
243
244 private static boolean isSupportedPropertyClass(String propClass) {
245 return (String.class.getName().equals(propClass) || Boolean.class.getName().equals(propClass) || Integer.class
246 .getName().equals(propClass) || JavaUtils.isPrimitive(propClass));
247 }
248
249 private static Object parseSimpleValue(XMLStreamReader reader, String propClass) throws XMLStreamException {
250 if (String.class.getName().equals(propClass)) {
251 return StAXUtils.elementAsString(reader);
252 } else if (Boolean.class.getName().equals(propClass)) {
253 return StAXUtils.elementAsBoolean(reader);
254 } else if (Integer.class.getName().equals(propClass)) {
255 return StAXUtils.elementAsInt(reader);
256 } else if (boolean.class.getName().equals(propClass)) {
257 return StAXUtils.elementAsBoolean(reader);
258 } else {
259 throw MESSAGES.unsupportedPropertyClass(propClass);
260 }
261 }
262
263 @SuppressWarnings({ "rawtypes", "unchecked" })
264 private static List parseListProperty(XMLStreamReader reader, String propClass, String elementClass)
265 throws XMLStreamException {
266 List list = null;
267 try {
268 list = (List) Class.forName(propClass).newInstance();
269 } catch (Exception e) {
270 throw MESSAGES.cannotInstantiateList(e, propClass);
271 }
272 while (reader.hasNext()) {
273 switch (reader.nextTag()) {
274 case XMLStreamConstants.END_ELEMENT: {
275 if (match(reader, NS, LIST)) {
276 return list;
277 } else {
278 throw MESSAGES.unexpectedEndTag(reader.getLocalName());
279 }
280 }
281 case XMLStreamConstants.START_ELEMENT: {
282 if (match(reader, NS, VALUE)) {
283 list.add(parseSimpleValue(reader, elementClass));
284 } else {
285 throw MESSAGES.unexpectedElement(reader.getLocalName());
286 }
287 }
288 }
289 }
290 throw MESSAGES.unexpectedEndOfDocument();
291 }
292
293 @SuppressWarnings("rawtypes")
294 private static Map parseMapProperty(XMLStreamReader reader, String propClass, String keyClass, String valueClass, ClassLoader loader)
295 throws XMLStreamException {
296 Map map = null;
297 try {
298 map = (Map) Class.forName(propClass, true, loader).newInstance();
299 } catch (Exception e) {
300 throw MESSAGES.cannotInstantiateMap(e, propClass);
301 }
302 while (reader.hasNext()) {
303 switch (reader.nextTag()) {
304 case XMLStreamConstants.END_ELEMENT: {
305 if (match(reader, NS, MAP)) {
306 return map;
307 } else {
308 throw MESSAGES.unexpectedEndTag(reader.getLocalName());
309 }
310 }
311 case XMLStreamConstants.START_ELEMENT: {
312 if (match(reader, NS, ENTRY)) {
313 parseMapEntry(reader, map, keyClass, valueClass);
314 } else {
315 throw MESSAGES.unexpectedElement(reader.getLocalName());
316 }
317 }
318 }
319 }
320 throw MESSAGES.unexpectedEndOfDocument();
321 }
322
323 @SuppressWarnings({ "rawtypes", "unchecked" })
324 private static void parseMapEntry(XMLStreamReader reader, Map map, String keyClass, String valueClass)
325 throws XMLStreamException {
326 boolean keyStartDone = false, valueStartDone = false;
327 Object key = null;
328 Object value = null;
329 while (reader.hasNext()) {
330 switch (reader.nextTag()) {
331 case XMLStreamConstants.END_ELEMENT: {
332 if (match(reader, NS, ENTRY) && keyStartDone && valueStartDone) {
333 map.put(key, value);
334 return;
335 } else {
336 throw MESSAGES.unexpectedEndTag(reader.getLocalName());
337 }
338 }
339 case XMLStreamConstants.START_ELEMENT: {
340 if (match(reader, NS, KEY)) {
341 keyStartDone = true;
342 key = parseSimpleValue(reader, keyClass);
343 } else if (match(reader, NS, VALUE)) {
344 valueStartDone = true;
345 value = parseSimpleValue(reader, valueClass);
346 } else {
347 throw MESSAGES.unexpectedElement(reader.getLocalName());
348 }
349 }
350 }
351 }
352 throw MESSAGES.unexpectedEndOfDocument();
353 }
354
355 /**
356 * Get context classloader.
357 *
358 * @return the current context classloader
359 */
360 private static ClassLoader getContextClassLoader() {
361 SecurityManager sm = System.getSecurityManager();
362 if (sm == null) {
363 return Thread.currentThread().getContextClassLoader();
364 } else {
365 return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
366 public ClassLoader run() {
367 return Thread.currentThread().getContextClassLoader();
368 }
369 });
370 }
371 }
372
373 /**
374 * Set context classloader.
375 *
376 * @param classLoader the classloader
377 */
378 private static void setContextClassLoader(final ClassLoader classLoader) {
379 if (System.getSecurityManager() == null) {
380 Thread.currentThread().setContextClassLoader(classLoader);
381 } else {
382 AccessController.doPrivileged(new PrivilegedAction<Object>() {
383 public Object run() {
384 Thread.currentThread().setContextClassLoader(classLoader);
385 return null;
386 }
387 });
388 }
389 }
390}