001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.server;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.BindingID;
042: import com.sun.xml.ws.api.WSBinding;
043: import com.sun.xml.ws.api.model.wsdl.WSDLPort;
044: import com.sun.xml.ws.api.server.AsyncProvider;
045: import com.sun.xml.ws.api.server.Container;
046: import com.sun.xml.ws.api.server.ContainerResolver;
047: import com.sun.xml.ws.api.server.InstanceResolver;
048: import com.sun.xml.ws.api.server.Invoker;
049: import com.sun.xml.ws.api.server.SDDocument;
050: import com.sun.xml.ws.api.server.SDDocumentSource;
051: import com.sun.xml.ws.api.server.WSEndpoint;
052: import com.sun.xml.ws.api.wsdl.parser.WSDLParserExtension;
053: import com.sun.xml.ws.api.wsdl.parser.XMLEntityResolver;
054: import com.sun.xml.ws.api.wsdl.parser.XMLEntityResolver.Parser;
055: import com.sun.xml.ws.api.wsdl.writer.WSDLGeneratorExtension;
056: import com.sun.xml.ws.binding.BindingImpl;
057: import com.sun.xml.ws.binding.SOAPBindingImpl;
058: import com.sun.xml.ws.binding.WebServiceFeatureList;
059: import com.sun.xml.ws.model.AbstractSEIModelImpl;
060: import com.sun.xml.ws.model.RuntimeModeler;
061: import com.sun.xml.ws.model.SOAPSEIModel;
062: import com.sun.xml.ws.model.wsdl.WSDLModelImpl;
063: import com.sun.xml.ws.model.wsdl.WSDLPortImpl;
064: import com.sun.xml.ws.resources.ServerMessages;
065: import com.sun.xml.ws.server.provider.ProviderInvokerTube;
066: import com.sun.xml.ws.server.sei.SEIInvokerTube;
067: import com.sun.xml.ws.util.HandlerAnnotationInfo;
068: import com.sun.xml.ws.util.HandlerAnnotationProcessor;
069: import com.sun.xml.ws.util.ServiceConfigurationError;
070: import com.sun.xml.ws.util.ServiceFinder;
071: import com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser;
072: import com.sun.xml.ws.wsdl.writer.WSDLGenerator;
073: import org.xml.sax.EntityResolver;
074: import org.xml.sax.SAXException;
075:
076: import javax.jws.WebService;
077: import javax.xml.namespace.QName;
078: import javax.xml.stream.XMLStreamException;
079: import javax.xml.ws.Provider;
080: import javax.xml.ws.WebServiceException;
081: import javax.xml.ws.WebServiceProvider;
082: import javax.xml.ws.soap.SOAPBinding;
083: import java.io.IOException;
084: import java.net.URL;
085: import java.util.ArrayList;
086: import java.util.Collection;
087: import java.util.HashMap;
088: import java.util.List;
089: import java.util.Map;
090: import java.util.logging.Logger;
091:
092: /**
093: * Entry point to the JAX-WS RI server-side runtime.
094: *
095: * @author Kohsuke Kawaguchi
096: * @author Jitendra Kotamraju
097: */
098: public class EndpointFactory {
099:
100: /**
101: * Implements {@link WSEndpoint#create}.
102: *
103: * No need to take WebServiceContext implementation. When InvokerPipe is
104: * instantiated, it calls InstanceResolver to set up a WebServiceContext.
105: * We shall only take delegate to getUserPrincipal and isUserInRole from adapter.
106: *
107: * <p>
108: * Nobody else should be calling this method.
109: */
110: public static <T> WSEndpoint<T> createEndpoint(Class<T> implType,
111: boolean processHandlerAnnotation, @Nullable
112: Invoker invoker, @Nullable
113: QName serviceName, @Nullable
114: QName portName, @Nullable
115: Container container, @Nullable
116: WSBinding binding, @Nullable
117: SDDocumentSource primaryWsdl, @Nullable
118: Collection<? extends SDDocumentSource> metadata,
119: EntityResolver resolver, boolean isTransportSynchronous) {
120:
121: if (implType == null)
122: throw new IllegalArgumentException();
123:
124: verifyImplementorClass(implType);
125:
126: if (invoker == null) {
127: invoker = InstanceResolver.createDefault(implType)
128: .createInvoker();
129: }
130:
131: List<SDDocumentSource> md = new ArrayList<SDDocumentSource>();
132: if (metadata != null)
133: md.addAll(metadata);
134:
135: if (primaryWsdl != null && !md.contains(primaryWsdl))
136: md.add(primaryWsdl);
137:
138: if (container == null)
139: container = ContainerResolver.getInstance().getContainer();
140:
141: if (serviceName == null)
142: serviceName = getDefaultServiceName(implType);
143:
144: if (portName == null)
145: portName = getDefaultPortName(serviceName, implType);
146:
147: {// error check
148: String serviceNS = serviceName.getNamespaceURI();
149: String portNS = portName.getNamespaceURI();
150: if (!serviceNS.equals(portNS)) {
151: throw new ServerRtException("wrong.tns.for.port",
152: portNS, serviceNS);
153: }
154: }
155:
156: // setting a default binding
157: if (binding == null)
158: binding = BindingImpl.create(BindingID.parse(implType));
159:
160: if (primaryWsdl != null) {
161: verifyPrimaryWSDL(primaryWsdl, serviceName);
162: }
163:
164: QName portTypeName = null;
165: if (implType.getAnnotation(WebServiceProvider.class) == null) {
166: portTypeName = RuntimeModeler.getPortTypeName(implType);
167: }
168:
169: // Categorises the documents as WSDL, Schema etc
170: List<SDDocumentImpl> docList = categoriseMetadata(md,
171: serviceName, portTypeName);
172: // Finds the primary WSDL and makes sure that metadata doesn't have
173: // two concrete or abstract WSDLs
174: SDDocumentImpl primaryDoc = findPrimary(docList);
175:
176: InvokerTube terminal;
177: WSDLPortImpl wsdlPort = null;
178: AbstractSEIModelImpl seiModel = null;
179: // create WSDL model
180: if (primaryDoc != null) {
181: wsdlPort = getWSDLPort(primaryDoc, docList, serviceName,
182: portName);
183: }
184:
185: WebServiceFeatureList features = ((BindingImpl) binding)
186: .getFeatures();
187: features.parseAnnotations(implType);
188:
189: // create terminal pipe that invokes the application
190: if (implType.getAnnotation(WebServiceProvider.class) != null) {
191: //Provider case: Enable Addressing from WSDL only if it has RespectBindingFeature enabled
192: if (wsdlPort != null)
193: features.mergeFeatures(wsdlPort, true, true);
194: terminal = ProviderInvokerTube.create(implType, binding,
195: invoker);
196: } else {
197: // Create runtime model for non Provider endpoints
198: seiModel = createSEIModel(wsdlPort, implType, serviceName,
199: portName, binding);
200: if (binding instanceof SOAPBindingImpl) {
201: //set portKnownHeaders on Binding, so that they can be used for MU processing
202: ((SOAPBindingImpl) binding)
203: .setPortKnownHeaders(((SOAPSEIModel) seiModel)
204: .getKnownHeaders());
205: }
206: // Generate WSDL for SEI endpoints(not for Provider endpoints)
207: if (primaryDoc == null) {
208: primaryDoc = generateWSDL(binding, seiModel, docList,
209: container, implType);
210: // create WSDL model
211: wsdlPort = getWSDLPort(primaryDoc, docList,
212: serviceName, portName);
213: seiModel.freeze(wsdlPort);
214: }
215: // New Features might have been added in WSDL through Policy.
216: // This sets only the wsdl features that are not already set(enabled/disabled)
217: features.mergeFeatures(wsdlPort, false, true);
218: terminal = new SEIInvokerTube(seiModel, invoker, binding);
219: }
220:
221: // Process @HandlerChain, if handler-chain is not set via Deployment Descriptor
222: if (processHandlerAnnotation) {
223: processHandlerAnnotation(binding, implType, serviceName,
224: portName);
225: }
226: // Selects only required metadata for this endpoint from the passed-in metadata
227: if (primaryDoc != null) {
228: docList = findMetadataClosure(primaryDoc, docList);
229: }
230: ServiceDefinitionImpl serviceDefiniton = (primaryDoc != null) ? new ServiceDefinitionImpl(
231: docList, primaryDoc)
232: : null;
233:
234: return new WSEndpointImpl<T>(serviceName, portName, binding,
235: container, seiModel, wsdlPort, implType,
236: serviceDefiniton, terminal, isTransportSynchronous);
237: }
238:
239: /**
240: * Goes through the original metadata documents and collects the required ones.
241: * This done traversing from primary WSDL and its imports until it builds a
242: * complete set of documents(transitive closure) for the endpoint.
243: *
244: * @param primaryDoc primary WSDL doc
245: * @param docList complete metadata
246: * @return new metadata that doesn't contain extraneous documnets.
247: */
248: private static List<SDDocumentImpl> findMetadataClosure(
249: SDDocumentImpl primaryDoc, List<SDDocumentImpl> docList) {
250: // create a map for old metadata
251: Map<String, SDDocumentImpl> oldMap = new HashMap<String, SDDocumentImpl>();
252: for (SDDocumentImpl doc : docList) {
253: oldMap.put(doc.getSystemId().toString(), doc);
254: }
255: // create a map for new metadata
256: Map<String, SDDocumentImpl> newMap = new HashMap<String, SDDocumentImpl>();
257: newMap.put(primaryDoc.getSystemId().toString(), primaryDoc);
258:
259: List<String> remaining = new ArrayList<String>();
260: remaining.addAll(primaryDoc.getImports());
261: while (!remaining.isEmpty()) {
262: String url = remaining.remove(0);
263: SDDocumentImpl doc = oldMap.get(url);
264: if (doc == null) {
265: // old metadata doesn't have this imported doc, may be external
266: continue;
267: }
268: // Check if new metadata already contains this doc
269: if (!newMap.containsKey(url)) {
270: newMap.put(url, doc);
271: remaining.addAll(doc.getImports());
272: }
273: }
274: List<SDDocumentImpl> newMetadata = new ArrayList<SDDocumentImpl>();
275: newMetadata.addAll(newMap.values());
276: return newMetadata;
277: }
278:
279: private static <T> void processHandlerAnnotation(WSBinding binding,
280: Class<T> implType, QName serviceName, QName portName) {
281: HandlerAnnotationInfo chainInfo = HandlerAnnotationProcessor
282: .buildHandlerInfo(implType, serviceName, portName,
283: binding);
284: if (chainInfo != null) {
285: binding.setHandlerChain(chainInfo.getHandlers());
286: if (binding instanceof SOAPBinding) {
287: ((SOAPBinding) binding).setRoles(chainInfo.getRoles());
288: }
289: }
290:
291: }
292:
293: /**
294: * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider
295: * annotation
296: *
297: * @return
298: * true if it is a Provider or AsyncProvider endpoint
299: * false otherwise
300: * @throws java.lang.IllegalArgumentException
301: * If it doesn't have any one of @WebService or @WebServiceProvider
302: * If it has both @WebService and @WebServiceProvider annotations
303: */
304: public static boolean verifyImplementorClass(Class<?> clz) {
305: WebServiceProvider wsProvider = clz
306: .getAnnotation(WebServiceProvider.class);
307: WebService ws = clz.getAnnotation(WebService.class);
308: if (wsProvider == null && ws == null) {
309: throw new IllegalArgumentException(
310: clz
311: + " has neither @WebSerivce nor @WebServiceProvider annotation");
312: }
313: if (wsProvider != null && ws != null) {
314: throw new IllegalArgumentException(
315: clz
316: + " has both @WebSerivce and @WebServiceProvider annotations");
317: }
318: if (wsProvider != null) {
319: if (Provider.class.isAssignableFrom(clz)
320: || AsyncProvider.class.isAssignableFrom(clz)) {
321: return true;
322: }
323: throw new IllegalArgumentException(
324: clz
325: + " doesn't implement Provider or AsyncProvider interface");
326: }
327: return false;
328: }
329:
330: private static AbstractSEIModelImpl createSEIModel(
331: WSDLPort wsdlPort, Class<?> implType, @NotNull
332: QName serviceName, @NotNull
333: QName portName, WSBinding binding) {
334:
335: RuntimeModeler rap;
336: // Create runtime model for non Provider endpoints
337:
338: // wsdlPort will be null, means we will generate WSDL. Hence no need to apply
339: // bindings or need to look in the WSDL
340: if (wsdlPort == null) {
341: rap = new RuntimeModeler(implType, serviceName, binding
342: .getBindingId());
343: } else {
344: /*
345: This not needed anymore as wsdlFeatures are merged later anyway
346: and so is the MTOMFeature.
347: applyEffectiveMtomSetting(wsdlPort.getBinding(), binding);
348: */
349: //now we got the Binding so lets build the model
350: rap = new RuntimeModeler(implType, serviceName,
351: (WSDLPortImpl) wsdlPort);
352: }
353: rap.setPortName(portName);
354: return rap.buildRuntimeModel();
355: }
356:
357: /**
358: *Set the mtom enable setting from wsdl model (mtom policy assertion) on to @link WSBinding} if DD has
359: * not already set it on BindingID. Also check conflicts.
360: */
361: /*
362: private static void applyEffectiveMtomSetting(WSDLBoundPortType wsdlBinding, WSBinding binding){
363: if(wsdlBinding.isMTOMEnabled()){
364: BindingID bindingId = binding.getBindingId();
365: if(bindingId.isMTOMEnabled() == null){
366: binding.setMTOMEnabled(true);
367: }else if (bindingId.isMTOMEnabled() != null && bindingId.isMTOMEnabled() == Boolean.FALSE){
368: //TODO: i18N
369: throw new ServerRtException("Deployment failed! Mtom policy assertion in WSDL is enabled whereas the deplyment descriptor setting wants to disable it!");
370: }
371: }
372: }
373: */
374: /**
375: * If service name is not already set via DD or programmatically, it uses
376: * annotations {@link WebServiceProvider}, {@link WebService} on implementorClass to get PortName.
377: *
378: * @return non-null service name
379: */
380: public static @NotNull
381: QName getDefaultServiceName(Class<?> implType) {
382: QName serviceName;
383: WebServiceProvider wsProvider = implType
384: .getAnnotation(WebServiceProvider.class);
385: if (wsProvider != null) {
386: String tns = wsProvider.targetNamespace();
387: String local = wsProvider.serviceName();
388: serviceName = new QName(tns, local);
389: } else {
390: serviceName = RuntimeModeler.getServiceName(implType);
391: }
392: assert serviceName != null;
393: return serviceName;
394: }
395:
396: /**
397: * If portName is not already set via DD or programmatically, it uses
398: * annotations on implementorClass to get PortName.
399: *
400: * @return non-null port name
401: */
402: public static @NotNull
403: QName getDefaultPortName(QName serviceName, Class<?> implType) {
404: QName portName;
405: WebServiceProvider wsProvider = implType
406: .getAnnotation(WebServiceProvider.class);
407: if (wsProvider != null) {
408: String tns = wsProvider.targetNamespace();
409: String local = wsProvider.portName();
410: portName = new QName(tns, local);
411: } else {
412: portName = RuntimeModeler.getPortName(implType, serviceName
413: .getNamespaceURI());
414: }
415: assert portName != null;
416: return portName;
417: }
418:
419: /**
420: * Returns the wsdl from @WebService, or @WebServiceProvider annotation using
421: * wsdlLocation element.
422: *
423: * @param implType
424: * endpoint implementation class
425: * make sure that you called {@link #verifyImplementorClass} on it.
426: * @return wsdl if there is wsdlLocation, else null
427: */
428: public static @Nullable
429: String getWsdlLocation(Class<?> implType) {
430: String wsdl;
431: WebService ws = implType.getAnnotation(WebService.class);
432: if (ws != null) {
433: wsdl = ws.wsdlLocation();
434: } else {
435: WebServiceProvider wsProvider = implType
436: .getAnnotation(WebServiceProvider.class);
437: assert wsProvider != null;
438: wsdl = wsProvider.wsdlLocation();
439: }
440: if (wsdl.length() < 1) {
441: wsdl = null;
442: }
443: return wsdl;
444: }
445:
446: /**
447: * Generates the WSDL and XML Schema for the endpoint if necessary
448: * It generates WSDL only for SOAP1.1, and for XSOAP1.2 bindings
449: */
450: private static SDDocumentImpl generateWSDL(WSBinding binding,
451: AbstractSEIModelImpl seiModel, List<SDDocumentImpl> docs,
452: Container container, Class implType) {
453: BindingID bindingId = binding.getBindingId();
454: if (!bindingId.canGenerateWSDL()) {
455: throw new ServerRtException("can.not.generate.wsdl",
456: bindingId);
457: }
458:
459: if (bindingId.toString().equals(
460: SOAPBindingImpl.X_SOAP12HTTP_BINDING)) {
461: String msg = ServerMessages.GENERATE_NON_STANDARD_WSDL();
462: logger.warning(msg);
463: }
464:
465: // Generate WSDL and schema documents using runtime model
466: WSDLGenResolver wsdlResolver = new WSDLGenResolver(docs,
467: seiModel.getServiceQName(), seiModel.getPortTypeName());
468: WSDLGenerator wsdlGen = new WSDLGenerator(seiModel,
469: wsdlResolver, binding, container, implType,
470: ServiceFinder.find(WSDLGeneratorExtension.class)
471: .toArray());
472: wsdlGen.doGeneration();
473: return wsdlResolver.updateDocs();
474: }
475:
476: /**
477: * Builds {@link SDDocumentImpl} from {@link SDDocumentSource}.
478: */
479: private static List<SDDocumentImpl> categoriseMetadata(
480: List<SDDocumentSource> src, QName serviceName,
481: QName portTypeName) {
482:
483: List<SDDocumentImpl> r = new ArrayList<SDDocumentImpl>(src
484: .size());
485: for (SDDocumentSource doc : src) {
486: r
487: .add(SDDocumentImpl.create(doc, serviceName,
488: portTypeName));
489: }
490: return r;
491: }
492:
493: /**
494: * Verifies whether the given primaryWsdl contains the given serviceName.
495: * If the WSDL doesn't have the service, it throws an WebServiceException.
496: */
497: private static void verifyPrimaryWSDL(@NotNull
498: SDDocumentSource primaryWsdl, @NotNull
499: QName serviceName) {
500: SDDocumentImpl primaryDoc = SDDocumentImpl.create(primaryWsdl,
501: serviceName, null);
502: if (!(primaryDoc instanceof SDDocument.WSDL)) {
503: throw new WebServiceException("Not a primary WSDL="
504: + primaryWsdl.getSystemId());
505: }
506: SDDocument.WSDL wsdlDoc = (SDDocument.WSDL) primaryDoc;
507: if (!wsdlDoc.hasService()) {
508: throw new WebServiceException("Not a primary WSDL="
509: + primaryWsdl.getSystemId()
510: + " since it doesn't have Service " + serviceName);
511: }
512: }
513:
514: /**
515: * Finds the primary WSDL document from the list of metadata documents. If
516: * there are two metadata documents that qualify for primary, it throws an
517: * exception. If there are two metadata documents that qualify for porttype,
518: * it throws an exception.
519: *
520: * @return primay wsdl document, null if is not there in the docList
521: *
522: */
523: private static @Nullable
524: SDDocumentImpl findPrimary(@NotNull
525: List<SDDocumentImpl> docList) {
526: SDDocumentImpl primaryDoc = null;
527: boolean foundConcrete = false;
528: boolean foundAbstract = false;
529: for (SDDocumentImpl doc : docList) {
530: if (doc instanceof SDDocument.WSDL) {
531: SDDocument.WSDL wsdlDoc = (SDDocument.WSDL) doc;
532: if (wsdlDoc.hasService()) {
533: primaryDoc = doc;
534: if (foundConcrete) {
535: throw new ServerRtException(
536: "duplicate.primary.wsdl", doc
537: .getSystemId());
538: }
539: foundConcrete = true;
540: }
541: if (wsdlDoc.hasPortType()) {
542: if (foundAbstract) {
543: throw new ServerRtException(
544: "duplicate.abstract.wsdl", doc
545: .getSystemId());
546: }
547: foundAbstract = true;
548: }
549: }
550: }
551: return primaryDoc;
552: }
553:
554: /**
555: * Parses the primary WSDL and returns the {@link WSDLPort} for the given service and port names
556: *
557: * @param primaryWsdl Primary WSDL
558: * @param metadata it may contain imported WSDL and schema documents
559: * @param serviceName service name in wsdl
560: * @param portName port name in WSDL
561: * @return non-null wsdl port object
562: */
563: private static @NotNull
564: WSDLPortImpl getWSDLPort(SDDocumentSource primaryWsdl,
565: List<? extends SDDocumentSource> metadata, @NotNull
566: QName serviceName, @NotNull
567: QName portName) {
568: URL wsdlUrl = primaryWsdl.getSystemId();
569: try {
570: // TODO: delegate to another entity resolver
571: WSDLModelImpl wsdlDoc = RuntimeWSDLParser.parse(new Parser(
572: primaryWsdl), new EntityResolverImpl(metadata),
573: false, ServiceFinder
574: .find(WSDLParserExtension.class).toArray());
575: WSDLPortImpl wsdlPort = wsdlDoc.getService(serviceName)
576: .get(portName);
577: if (wsdlPort == null) {
578: throw new ServerRtException(
579: ServerMessages
580: .localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICEPORT(
581: serviceName, portName, wsdlUrl));
582: }
583: return wsdlPort;
584: } catch (IOException e) {
585: throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,
586: e);
587: } catch (XMLStreamException e) {
588: throw new ServerRtException("runtime.saxparser.exception",
589: e.getMessage(), e.getLocation(), e);
590: } catch (SAXException e) {
591: throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,
592: e);
593: } catch (ServiceConfigurationError e) {
594: throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,
595: e);
596: }
597: }
598:
599: /**
600: * {@link XMLEntityResolver} that can resolve to {@link SDDocumentSource}s.
601: */
602: private static final class EntityResolverImpl implements
603: XMLEntityResolver {
604: private Map<String, SDDocumentSource> metadata = new HashMap<String, SDDocumentSource>();
605:
606: public EntityResolverImpl(
607: List<? extends SDDocumentSource> metadata) {
608: for (SDDocumentSource doc : metadata) {
609: this .metadata.put(doc.getSystemId().toExternalForm(),
610: doc);
611: }
612: }
613:
614: public Parser resolveEntity(String publicId, String systemId)
615: throws IOException, XMLStreamException {
616: if (systemId != null) {
617: SDDocumentSource doc = metadata.get(systemId);
618: if (doc != null)
619: return new Parser(doc);
620: }
621: return null;
622: }
623:
624: }
625:
626: private static final Logger logger = Logger
627: .getLogger(com.sun.xml.ws.util.Constants.LoggingDomain
628: + ".server.endpoint");
629: }
|