001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.webservices.builder;
018    
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.lang.reflect.Method;
022    import java.math.BigDecimal;
023    import java.math.BigInteger;
024    import java.net.URI;
025    import java.net.URL;
026    import java.util.ArrayList;
027    import java.util.Calendar;
028    import java.util.HashMap;
029    import java.util.List;
030    import java.util.Map;
031    import java.util.jar.JarFile;
032    import java.util.zip.ZipEntry;
033    
034    import javax.wsdl.Definition;
035    import javax.wsdl.Operation;
036    import javax.xml.namespace.QName;
037    import javax.xml.rpc.handler.HandlerInfo;
038    import javax.xml.rpc.holders.BigDecimalHolder;
039    import javax.xml.rpc.holders.BigIntegerHolder;
040    import javax.xml.rpc.holders.BooleanHolder;
041    import javax.xml.rpc.holders.BooleanWrapperHolder;
042    import javax.xml.rpc.holders.ByteArrayHolder;
043    import javax.xml.rpc.holders.ByteHolder;
044    import javax.xml.rpc.holders.ByteWrapperHolder;
045    import javax.xml.rpc.holders.CalendarHolder;
046    import javax.xml.rpc.holders.DoubleHolder;
047    import javax.xml.rpc.holders.DoubleWrapperHolder;
048    import javax.xml.rpc.holders.FloatHolder;
049    import javax.xml.rpc.holders.FloatWrapperHolder;
050    import javax.xml.rpc.holders.IntHolder;
051    import javax.xml.rpc.holders.IntegerWrapperHolder;
052    import javax.xml.rpc.holders.LongHolder;
053    import javax.xml.rpc.holders.LongWrapperHolder;
054    import javax.xml.rpc.holders.ObjectHolder;
055    import javax.xml.rpc.holders.QNameHolder;
056    import javax.xml.rpc.holders.ShortHolder;
057    import javax.xml.rpc.holders.ShortWrapperHolder;
058    import javax.xml.rpc.holders.StringHolder;
059    
060    import org.apache.geronimo.common.DeploymentException;
061    import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
062    import org.apache.geronimo.kernel.ClassLoading;
063    import org.apache.geronimo.xbeans.j2ee.ExceptionMappingType;
064    import org.apache.geronimo.xbeans.j2ee.JavaWsdlMappingDocument;
065    import org.apache.geronimo.xbeans.j2ee.JavaWsdlMappingType;
066    import org.apache.geronimo.xbeans.j2ee.PackageMappingType;
067    import org.apache.geronimo.xbeans.j2ee.ParamValueType;
068    import org.apache.geronimo.xbeans.j2ee.PortComponentHandlerType;
069    import org.apache.geronimo.xbeans.j2ee.PortComponentType;
070    import org.apache.geronimo.xbeans.j2ee.ServiceEndpointInterfaceMappingType;
071    import org.apache.geronimo.xbeans.j2ee.ServiceEndpointMethodMappingType;
072    import org.apache.geronimo.xbeans.j2ee.ServiceImplBeanType;
073    import org.apache.geronimo.xbeans.j2ee.WebserviceDescriptionType;
074    import org.apache.geronimo.xbeans.j2ee.WebservicesDocument;
075    import org.apache.geronimo.xbeans.j2ee.WebservicesType;
076    import org.apache.geronimo.xbeans.j2ee.XsdQNameType;
077    import org.apache.xmlbeans.XmlCursor;
078    import org.apache.xmlbeans.XmlException;
079    import org.apache.xmlbeans.XmlObject;
080    
081    /**
082     * @version $Rev: 561959 $ $Date: 2007-08-01 17:21:43 -0400 (Wed, 01 Aug 2007) $
083     */
084    public class WSDescriptorParser {
085    
086    
087        public static JavaWsdlMappingType readJaxrpcMapping(JarFile moduleFile, URI jaxrpcMappingURI) throws DeploymentException {
088            String jaxrpcMappingPath = jaxrpcMappingURI.toString();
089            return readJaxrpcMapping(moduleFile, jaxrpcMappingPath);
090        }
091    
092        public static JavaWsdlMappingType readJaxrpcMapping(JarFile moduleFile, String jaxrpcMappingPath) throws DeploymentException {
093            JavaWsdlMappingType mapping;
094            InputStream jaxrpcInputStream;
095            try {
096                ZipEntry zipEntry = moduleFile.getEntry(jaxrpcMappingPath);
097                if (zipEntry == null) {
098                    throw new DeploymentException("The JAX-RPC mapping file " + jaxrpcMappingPath + " specified in webservices.xml could not be found.");
099                }
100                jaxrpcInputStream = moduleFile.getInputStream(zipEntry);
101            } catch (IOException e) {
102                throw new DeploymentException("Could not open stream to jaxrpc mapping document", e);
103            }
104            JavaWsdlMappingDocument mappingDocument;
105            try {
106                mappingDocument = JavaWsdlMappingDocument.Factory.parse(jaxrpcInputStream);
107            } catch (XmlException e) {
108                throw new DeploymentException("Could not parse jaxrpc mapping document", e);
109            } catch (IOException e) {
110                throw new DeploymentException("Could not read jaxrpc mapping document", e);
111            }
112            mapping = mappingDocument.getJavaWsdlMapping();
113            return mapping;
114        }
115    
116    
117        public static Map<QName,ExceptionMappingType> getExceptionMap(JavaWsdlMappingType mapping) {
118            Map<QName,ExceptionMappingType> exceptionMap = new HashMap<QName, ExceptionMappingType>();
119            if (mapping != null) {
120                ExceptionMappingType[] exceptionMappings = mapping.getExceptionMappingArray();
121                for (ExceptionMappingType exceptionMapping : exceptionMappings) {
122                    QName exceptionMessageQName = exceptionMapping.getWsdlMessage().getQNameValue();
123                    exceptionMap.put(exceptionMessageQName, exceptionMapping);
124                }
125            }
126            return exceptionMap;
127        }
128    
129        public static String getPackageFromNamespace(String namespace, JavaWsdlMappingType mapping) throws DeploymentException {
130            PackageMappingType[] packageMappings = mapping.getPackageMappingArray();
131            for (PackageMappingType packageMapping : packageMappings) {
132                if (namespace.equals(packageMapping.getNamespaceURI().getStringValue().trim())) {
133                    return packageMapping.getPackageType().getStringValue().trim();
134                }
135            }
136            throw new DeploymentException("Namespace " + namespace + " was not mapped in jaxrpc mapping file");
137        }
138    
139        private static final Map<Class,Class> rpcHolderClasses = new HashMap<Class, Class>();
140    
141        static {
142            rpcHolderClasses.put(BigDecimal.class, BigDecimalHolder.class);
143            rpcHolderClasses.put(BigInteger.class, BigIntegerHolder.class);
144            rpcHolderClasses.put(boolean.class, BooleanHolder.class);
145            rpcHolderClasses.put(Boolean.class, BooleanWrapperHolder.class);
146            rpcHolderClasses.put(byte[].class, ByteArrayHolder.class);
147            rpcHolderClasses.put(byte.class, ByteHolder.class);
148            rpcHolderClasses.put(Byte.class, ByteWrapperHolder.class);
149            rpcHolderClasses.put(Calendar.class, CalendarHolder.class);
150            rpcHolderClasses.put(double.class, DoubleHolder.class);
151            rpcHolderClasses.put(Double.class, DoubleWrapperHolder.class);
152            rpcHolderClasses.put(float.class, FloatHolder.class);
153            rpcHolderClasses.put(Float.class, FloatWrapperHolder.class);
154            rpcHolderClasses.put(int.class, IntHolder.class);
155            rpcHolderClasses.put(Integer.class, IntegerWrapperHolder.class);
156            rpcHolderClasses.put(long.class, LongHolder.class);
157            rpcHolderClasses.put(Long.class, LongWrapperHolder.class);
158            rpcHolderClasses.put(Object.class, ObjectHolder.class);
159            rpcHolderClasses.put(QName.class, QNameHolder.class);
160            rpcHolderClasses.put(short.class, ShortHolder.class);
161            rpcHolderClasses.put(Short.class, ShortWrapperHolder.class);
162            rpcHolderClasses.put(String.class, StringHolder.class);
163        }
164    
165        public static Class getHolderType(String paramJavaTypeName, boolean isInOnly, QName typeQName, boolean isComplexType, JavaWsdlMappingType mapping, ClassLoader classLoader) throws DeploymentException {
166            Class paramJavaType;
167            if (isInOnly) {
168                //IN parameters just use their own type
169                try {
170                    paramJavaType = ClassLoading.loadClass(paramJavaTypeName, classLoader);
171                } catch (ClassNotFoundException e) {
172                    throw new DeploymentException("could not load parameter type", e);
173                }
174                return paramJavaType;
175            } else {
176                //INOUT and OUT parameters use holders.  See jaxrpc spec 4.3.5
177                String holderName;
178                if (isComplexType) {
179                    //complex types get mapped:
180                    //package is determined from the namespace to package map + ".holders"
181                    //class name is the complex type QNMAne local part + "Holder", with the initial character uppercased.
182                    String namespace = typeQName.getNamespaceURI();
183                    String packageName = WSDescriptorParser.getPackageFromNamespace(namespace, mapping);
184                    StringBuffer buf = new StringBuffer(packageName.length() + typeQName.getLocalPart().length() + 14);
185                    buf.append(packageName).append(".holders.").append(typeQName.getLocalPart()).append("Holder");
186                    buf.setCharAt(packageName.length() + 9, Character.toUpperCase(typeQName.getLocalPart().charAt(0)));
187                    holderName = buf.toString();
188                } else {
189                    //see if it is in the primitive type and simple type mapping
190                    try {
191                        paramJavaType = ClassLoading.loadClass(paramJavaTypeName, classLoader);
192                    } catch (ClassNotFoundException e) {
193                        throw new DeploymentException("could not load parameter type", e);
194                    }
195                    Class holder = rpcHolderClasses.get(paramJavaType);
196                    if (holder != null) {
197                        try {
198                            //TODO use class names in map or make sure we are in the correct classloader to start with.
199                            holder = ClassLoading.loadClass(holder.getName(), classLoader);
200                        } catch (ClassNotFoundException e) {
201                            throw new DeploymentException("could not load holder type in correct classloader", e);
202                        }
203                        return holder;
204                    }
205                    //Otherwise, the holder must be in:
206                    //package same as type's package + ".holders"
207                    //class name same as type name + "Holder"
208                    String paramTypeName = paramJavaType.getName();
209                    StringBuffer buf = new StringBuffer(paramTypeName.length() + 14);
210                    int dot = paramTypeName.lastIndexOf(".");
211                    //foo.Bar >>> foo.holders.BarHolder
212                    buf.append(paramTypeName.substring(0, dot)).append(".holders").append(paramTypeName.substring(dot)).append("Holder");
213                    holderName = buf.toString();
214                }
215                try {
216                    return ClassLoading.loadClass(holderName, classLoader);
217                } catch (ClassNotFoundException e) {
218                    throw new DeploymentException("Could not load holder class", e);
219                }
220            }
221        }
222    
223        public static ServiceEndpointMethodMappingType getMethodMappingForOperation(String operationName, ServiceEndpointMethodMappingType[] methodMappings) throws DeploymentException {
224            for (ServiceEndpointMethodMappingType methodMapping : methodMappings) {
225                if (operationName.equals(methodMapping.getWsdlOperation().getStringValue())) {
226                    return methodMapping;
227                }
228            }
229            // Build list of available operations for exception
230            StringBuffer availOps = new StringBuffer(128);
231            for (int i = 0; i < methodMappings.length; i++) {
232                if (i != 0) availOps.append(",");
233                availOps.append(methodMappings[i].getWsdlOperation().getStringValue());
234            }
235            throw new DeploymentException("No method found for operation named '" + operationName + "'. Available operations: " + availOps);
236        }
237    
238        public static ServiceEndpointInterfaceMappingType getServiceEndpointInterfaceMapping(ServiceEndpointInterfaceMappingType[] endpointMappings, QName portTypeQName) throws DeploymentException {
239            for (ServiceEndpointInterfaceMappingType endpointMapping : endpointMappings) {
240                QName testPortQName = endpointMapping.getWsdlPortType().getQNameValue();
241                if (portTypeQName.equals(testPortQName)) {
242                    return endpointMapping;
243                }
244            }
245            throw new DeploymentException("Could not find service endpoint interface for port named " + portTypeQName);
246        }
247    
248        public static javax.wsdl.Service getService(QName serviceQName, Definition definition) throws DeploymentException {
249            javax.wsdl.Service service;
250            if (serviceQName != null) {
251                service = definition.getService(serviceQName);
252            } else {
253                Map services = definition.getServices();
254                if (services.size() != 1) {
255                    throw new DeploymentException("no serviceQName supplied, and there are " + services.size() + " services");
256                }
257                service = (javax.wsdl.Service) services.values().iterator().next();
258            }
259            if (service == null) {
260                throw new DeploymentException("No service wsdl for supplied service qname " + serviceQName);
261            }
262            return service;
263        }
264    
265        public static Method getMethodForOperation(Class serviceEndpointInterface, Operation operation) throws DeploymentException {
266            Method[] methods = serviceEndpointInterface.getMethods();
267            String opName = operation.getName();
268            Method found = null;
269            for (Method method : methods) {
270                if (method.getName().equals(opName)) {
271                    if (found != null) {
272                        throw new DeploymentException("Overloaded methods are not allowed in lightweight mappings");
273                    }
274                    found = method;
275                }
276            }
277            if (found == null) {
278                throw new DeploymentException("No method found for operation named " + opName);
279            }
280            return found;
281        }
282    
283        /**
284         * Parses a webservice.xml file and returns a map PortInfo instances indexed by the
285         * corresponding ejb-link or servlet-link element .
286         *
287         * @param webservicesType
288         * @param moduleFile
289         * @param isEJB
290         * @param servletLocations
291         * @return
292         * @throws org.apache.geronimo.common.DeploymentException
293         *
294         */
295        public static Map<String,PortInfo> parseWebServiceDescriptor(WebservicesType webservicesType, JarFile moduleFile, boolean isEJB, Map servletLocations) throws DeploymentException {
296            Map<String,PortInfo> portMap = new HashMap<String, PortInfo>();
297            WebserviceDescriptionType[] webserviceDescriptions = webservicesType.getWebserviceDescriptionArray();
298            SharedPortInfo sharedPortInfo;
299            for (WebserviceDescriptionType webserviceDescription : webserviceDescriptions) {            
300                String wsdlLocation = webserviceDescription.getWsdlFile().getStringValue().trim();
301                String jaxrpcMappingFile = webserviceDescription.getJaxrpcMappingFile().getStringValue().trim();
302                
303                sharedPortInfo = new SharedPortInfo(wsdlLocation, 
304                                                    jaxrpcMappingFile,
305                                                    DescriptorVersion.J2EE);
306                
307                PortComponentType[] portComponents = webserviceDescription.getPortComponentArray();
308                for (PortComponentType portComponent : portComponents) {
309                    String portComponentName = portComponent.getPortComponentName().getStringValue().trim();
310                    QName portQName = portComponent.getWsdlPort().getQNameValue();
311                    String seiInterfaceName = portComponent.getServiceEndpointInterface().getStringValue().trim();
312                    ServiceImplBeanType serviceImplBeanType = portComponent.getServiceImplBean();
313                    if (isEJB == serviceImplBeanType.isSetServletLink()) {
314                        throw new DeploymentException("Wrong kind of web service described in web service descriptor: expected " + (isEJB ? "EJB" : "POJO(Servlet)"));
315                    }
316                    String linkName;
317                    String servletLocation;
318                    if (serviceImplBeanType.isSetServletLink()) {
319                        linkName = serviceImplBeanType.getServletLink().getStringValue().trim();
320                        servletLocation = (String) servletLocations.get(linkName);
321                        if (servletLocation == null) {
322                            throw new DeploymentException("No servlet mapping for port " + portComponentName);
323                        }
324                    } else {
325                        linkName = serviceImplBeanType.getEjbLink().getStringValue().trim();
326                        servletLocation = (String) servletLocations.get(linkName);
327                    }
328                    PortComponentHandlerType[] handlers = portComponent.getHandlerArray();
329                    
330                    PortInfo portInfo = new PortInfo(sharedPortInfo, portComponentName, portQName, seiInterfaceName, handlers, servletLocation);
331    
332                    if (portMap.put(linkName, portInfo) != null) {
333                        throw new DeploymentException("Ambiguous description of port associated with j2ee component " + linkName);
334                    }
335                }
336            }
337            return portMap;
338        }
339    
340        public static Map<String,PortInfo> parseWebServiceDescriptor(org.apache.geronimo.xbeans.javaee.WebservicesType webservicesType, JarFile moduleFile, boolean isEJB, Map servletLocations) throws DeploymentException {
341            Map<String,PortInfo> portMap = new HashMap<String, PortInfo>();
342            org.apache.geronimo.xbeans.javaee.WebserviceDescriptionType[] webserviceDescriptions = webservicesType.getWebserviceDescriptionArray();
343            SharedPortInfo sharedPortInfo;
344            for (org.apache.geronimo.xbeans.javaee.WebserviceDescriptionType webserviceDescription : webserviceDescriptions) {
345                String wsdlLocation = null;
346                if (webserviceDescription.isSetWsdlFile()) {
347                    wsdlLocation = webserviceDescription.getWsdlFile().getStringValue().trim();
348                }
349                String jaxrpcMappingFile = null;
350                if (webserviceDescription.isSetJaxrpcMappingFile()) {
351                    jaxrpcMappingFile = webserviceDescription.getJaxrpcMappingFile().getStringValue().trim();
352                }
353                
354                sharedPortInfo = new SharedPortInfo(wsdlLocation, 
355                                                    jaxrpcMappingFile, 
356                                                    DescriptorVersion.JAVAEE);
357                
358                org.apache.geronimo.xbeans.javaee.PortComponentType[] portComponents = webserviceDescription.getPortComponentArray();
359                for (org.apache.geronimo.xbeans.javaee.PortComponentType portComponent : portComponents) {
360                    String portComponentName = portComponent.getPortComponentName().getStringValue().trim();
361                    QName portQName = null;
362                    if (portComponent.isSetWsdlPort()) {
363                        portQName = portComponent.getWsdlPort().getQNameValue();
364                    }
365                    String seiInterfaceName = null;
366                    if (portComponent.isSetServiceEndpointInterface()) {
367                        seiInterfaceName = portComponent.getServiceEndpointInterface().getStringValue().trim();
368                    }
369                    org.apache.geronimo.xbeans.javaee.ServiceImplBeanType serviceImplBeanType = portComponent.getServiceImplBean();
370                    if (isEJB == serviceImplBeanType.isSetServletLink()) {
371                        throw new DeploymentException("Wrong kind of web service described in web service descriptor: expected " + (isEJB ? "EJB" : "POJO(Servlet)"));
372                    }
373                    String linkName;
374                    String servletLocation;
375                    if (serviceImplBeanType.isSetServletLink()) {
376                        linkName = serviceImplBeanType.getServletLink().getStringValue().trim();
377                        servletLocation = (String) servletLocations.get(linkName);
378                        if (servletLocation == null) {
379                            throw new DeploymentException("No servlet mapping for port " + portComponentName);
380                        }
381                    } else {
382                        linkName = serviceImplBeanType.getEjbLink().getStringValue().trim();
383                        servletLocation = (String) servletLocations.get(linkName);
384                    }
385                    PortComponentHandlerType[] handlers = null;
386                    if (portComponent.getHandlerArray() != null) {
387                        handlers = new PortComponentHandlerType[portComponent.getHandlerArray().length];
388                        for (int i=0; i<portComponent.getHandlerArray().length; i++) {
389                            handlers[i] = (PortComponentHandlerType)portComponent.getHandlerArray()[i].changeType(PortComponentHandlerType.type);
390                        }
391                    }
392                    
393                    PortInfo portInfo = new PortInfo(sharedPortInfo, portComponentName, portQName, seiInterfaceName, handlers, servletLocation);
394    
395                    if (portMap.put(linkName, portInfo) != null) {
396                        throw new DeploymentException("Ambiguous description of port associated with j2ee component " + linkName);
397                    }
398                }
399            }
400            return portMap;
401        }
402        
403        public static Map<String,PortInfo> parseWebServiceDescriptor(URL wsDDUrl, JarFile moduleFile, boolean isEJB, Map servletLocations) throws DeploymentException {
404            XmlObject webservicesType = getWebservicesType(wsDDUrl);
405            if (webservicesType instanceof WebservicesType) {
406                WebservicesType webServices = (WebservicesType)webservicesType;
407                return parseWebServiceDescriptor(webServices, moduleFile, isEJB, servletLocations);
408            } else if (webservicesType instanceof org.apache.geronimo.xbeans.javaee.WebservicesType) {
409                org.apache.geronimo.xbeans.javaee.WebservicesType webServices = (org.apache.geronimo.xbeans.javaee.WebservicesType)webservicesType;
410                return parseWebServiceDescriptor(webServices, moduleFile, isEJB, servletLocations);
411            } else {
412                return null;
413            }
414        }
415        
416        static XmlObject getWebservicesType(URL wsDDUrl) throws DeploymentException {
417            try {
418                XmlObject webservicesDocumentUntyped = XmlObject.Factory.parse(wsDDUrl);
419                XmlCursor cursor = webservicesDocumentUntyped.newCursor();
420                try {
421                    if (cursor.currentTokenType() != XmlCursor.TokenType.START) {
422                        while(cursor.toNextToken()  != XmlCursor.TokenType.START) {}
423                    }
424                    QName qname = cursor.getName();
425                    if (WebservicesDocument.type.getDocumentElementName().equals(qname)) {
426                        return getJ2EEWebServices(webservicesDocumentUntyped);
427                    } else if (org.apache.geronimo.xbeans.javaee.WebservicesDocument.type.getDocumentElementName().equals(qname)) {
428                        return getJavaEEWebServices(webservicesDocumentUntyped);
429                    } else {
430                        return null;
431                    }
432                } finally {
433                    cursor.dispose();
434                }
435            } catch (XmlException e) {
436                throw new DeploymentException("Could not read descriptor document", e);
437            } catch (IOException e) {
438                return null;
439            }
440        }
441    
442        private static XmlObject getJ2EEWebServices(XmlObject webservicesDocumentUntyped) throws XmlException {
443            WebservicesDocument webservicesDocument;
444            if (webservicesDocumentUntyped instanceof WebservicesDocument) {
445                webservicesDocument = (WebservicesDocument) webservicesDocumentUntyped;
446            } else {
447                webservicesDocument = (WebservicesDocument) webservicesDocumentUntyped.changeType(WebservicesDocument.type);
448            }
449            XmlBeansUtil.validateDD(webservicesDocument);
450            return webservicesDocument.getWebservices();
451        }
452        
453        private static XmlObject getJavaEEWebServices(XmlObject webservicesDocumentUntyped) throws XmlException {
454            org.apache.geronimo.xbeans.javaee.WebservicesDocument webservicesDocument;
455            if (webservicesDocumentUntyped instanceof org.apache.geronimo.xbeans.javaee.WebservicesDocument) {
456                webservicesDocument = (org.apache.geronimo.xbeans.javaee.WebservicesDocument) webservicesDocumentUntyped;
457            } else {
458                webservicesDocument = (org.apache.geronimo.xbeans.javaee.WebservicesDocument) webservicesDocumentUntyped.changeType(org.apache.geronimo.xbeans.javaee.WebservicesDocument.type);
459            }
460            XmlBeansUtil.validateDD(webservicesDocument);
461            return webservicesDocument.getWebservices();        
462        }
463        
464        public static List<HandlerInfo> createHandlerInfoList(PortComponentHandlerType[] handlers, ClassLoader classLoader) throws DeploymentException {
465            List<HandlerInfo> list = new ArrayList<HandlerInfo>();
466            for (PortComponentHandlerType handler : handlers) {
467                // Get handler class
468                Class handlerClass;
469                String className = handler.getHandlerClass().getStringValue().trim();
470                try {
471                    handlerClass = classLoader.loadClass(className);
472                } catch (ClassNotFoundException e) {
473                    throw new DeploymentException("Unable to load handler class: " + className, e);
474                }
475    
476                // config data for the handler
477                Map<String, String> config = new HashMap<String, String>();
478                ParamValueType[] paramValues = handler.getInitParamArray();
479                for (ParamValueType paramValue : paramValues) {
480                    String paramName = paramValue.getParamName().getStringValue().trim();
481                    String paramStringValue = paramValue.getParamValue().getStringValue().trim();
482                    config.put(paramName, paramStringValue);
483                }
484    
485                // QName array of headers it processes
486                XsdQNameType[] soapHeaderQNames = handler.getSoapHeaderArray();
487                QName[] headers = new QName[soapHeaderQNames.length];
488                for (int j = 0; j < soapHeaderQNames.length; j++) {
489                    XsdQNameType soapHeaderQName = soapHeaderQNames[j];
490                    headers[j] = soapHeaderQName.getQNameValue();
491                }
492    
493                list.add(new HandlerInfo(handlerClass, config, headers));
494            }
495            return list;
496        }
497    }