1 /*
2 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package com.sun.xml.internal.ws.server;
27
28 import com.sun.istack.internal.NotNull;
29 import com.sun.istack.internal.Nullable;
30 import com.sun.xml.internal.ws.api.BindingID;
31 import com.sun.xml.internal.ws.api.WSBinding;
32 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
33 import com.sun.xml.internal.ws.api.server.AsyncProvider;
34 import com.sun.xml.internal.ws.api.server.Container;
35 import com.sun.xml.internal.ws.api.server.ContainerResolver;
36 import com.sun.xml.internal.ws.api.server.InstanceResolver;
37 import com.sun.xml.internal.ws.api.server.Invoker;
38 import com.sun.xml.internal.ws.api.server.SDDocument;
39 import com.sun.xml.internal.ws.api.server.SDDocumentSource;
40 import com.sun.xml.internal.ws.api.server.WSEndpoint;
41 import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
42 import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver;
43 import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver.Parser;
44 import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension;
45 import com.sun.xml.internal.ws.binding.BindingImpl;
46 import com.sun.xml.internal.ws.binding.SOAPBindingImpl;
47 import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
48 import com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
49 import com.sun.xml.internal.ws.model.RuntimeModeler;
50 import com.sun.xml.internal.ws.model.SOAPSEIModel;
51 import com.sun.xml.internal.ws.model.wsdl.WSDLModelImpl;
52 import com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl;
53 import com.sun.xml.internal.ws.model.wsdl.WSDLServiceImpl;
54 import com.sun.xml.internal.ws.resources.ServerMessages;
55 import com.sun.xml.internal.ws.server.provider.ProviderInvokerTube;
56 import com.sun.xml.internal.ws.server.sei.SEIInvokerTube;
57 import com.sun.xml.internal.ws.util.HandlerAnnotationInfo;
58 import com.sun.xml.internal.ws.util.HandlerAnnotationProcessor;
59 import com.sun.xml.internal.ws.util.ServiceConfigurationError;
60 import com.sun.xml.internal.ws.util.ServiceFinder;
61 import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser;
62 import com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator;
63 import org.xml.sax.EntityResolver;
64 import org.xml.sax.SAXException;
65
66 import javax.jws.WebService;
67 import javax.xml.namespace.QName;
68 import javax.xml.stream.XMLStreamException;
69 import javax.xml.ws.Provider;
70 import javax.xml.ws.WebServiceException;
71 import javax.xml.ws.WebServiceProvider;
72 import javax.xml.ws.soap.SOAPBinding;
73 import java.io.IOException;
74 import java.net.URL;
75 import java.util.ArrayList;
76 import java.util.Collection;
77 import java.util.HashMap;
78 import java.util.List;
79 import java.util.Map;
80 import java.util.logging.Logger;
81
82 /**
83 * Entry point to the JAX-WS RI server-side runtime.
84 *
85 * @author Kohsuke Kawaguchi
86 * @author Jitendra Kotamraju
87 */
88 public class EndpointFactory {
89
90 /**
91 * Implements {@link WSEndpoint#create}.
92 *
93 * No need to take WebServiceContext implementation. When InvokerPipe is
94 * instantiated, it calls InstanceResolver to set up a WebServiceContext.
95 * We shall only take delegate to getUserPrincipal and isUserInRole from adapter.
96 *
97 * <p>
98 * Nobody else should be calling this method.
99 */
100 public static <T> WSEndpoint<T> createEndpoint(
101 Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker,
102 @Nullable QName serviceName, @Nullable QName portName,
103 @Nullable Container container, @Nullable WSBinding binding,
104 @Nullable SDDocumentSource primaryWsdl,
105 @Nullable Collection<? extends SDDocumentSource> metadata, EntityResolver resolver, boolean isTransportSynchronous) {
106
107 if(implType ==null)
108 throw new IllegalArgumentException();
109
110 verifyImplementorClass(implType);
111
112 if (invoker == null) {
113 invoker = InstanceResolver.createDefault(implType).createInvoker();
114 }
115
116 List<SDDocumentSource> md = new ArrayList<SDDocumentSource>();
117 if(metadata!=null)
118 md.addAll(metadata);
119
120 if(primaryWsdl!=null && !md.contains(primaryWsdl))
121 md.add(primaryWsdl);
122
123 if(container==null)
124 container = ContainerResolver.getInstance().getContainer();
125
126 if(serviceName==null)
127 serviceName = getDefaultServiceName(implType);
128
129 if(portName==null)
130 portName = getDefaultPortName(serviceName,implType);
131
132 {// error check
133 String serviceNS = serviceName.getNamespaceURI();
134 String portNS = portName.getNamespaceURI();
135 if (!serviceNS.equals(portNS)) {
136 throw new ServerRtException("wrong.tns.for.port",portNS, serviceNS);
137 }
138 }
139
140 // setting a default binding
141 if (binding == null)
142 binding = BindingImpl.create(BindingID.parse(implType));
143
144 if (primaryWsdl != null) {
145 verifyPrimaryWSDL(primaryWsdl, serviceName);
146 }
147
148 QName portTypeName = null;
149 if (implType.getAnnotation(WebServiceProvider.class)==null) {
150 portTypeName = RuntimeModeler.getPortTypeName(implType);
151 }
152
153 // Categorises the documents as WSDL, Schema etc
154 List<SDDocumentImpl> docList = categoriseMetadata(md, serviceName, portTypeName);
155 // Finds the primary WSDL and makes sure that metadata doesn't have
156 // two concrete or abstract WSDLs
157 SDDocumentImpl primaryDoc = findPrimary(docList);
158
159 InvokerTube terminal;
160 WSDLPortImpl wsdlPort = null;
161 AbstractSEIModelImpl seiModel = null;
162 // create WSDL model
163 if (primaryDoc != null) {
164 wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container);
165 }
166
167 WebServiceFeatureList features=((BindingImpl)binding).getFeatures();
168 features.parseAnnotations(implType);
169
170 // create terminal pipe that invokes the application
171 if (implType.getAnnotation(WebServiceProvider.class)!=null) {
172 //Provider case: Enable Addressing from WSDL only if it has RespectBindingFeature enabled
173 if (wsdlPort != null)
174 features.mergeFeatures(wsdlPort,true,true);
175 terminal = ProviderInvokerTube.create(implType,binding,invoker);
176 } else {
177 // Create runtime model for non Provider endpoints
178 seiModel = createSEIModel(wsdlPort, implType, serviceName, portName, binding);
179 if(binding instanceof SOAPBindingImpl){
180 //set portKnownHeaders on Binding, so that they can be used for MU processing
181 ((SOAPBindingImpl)binding).setPortKnownHeaders(
182 ((SOAPSEIModel)seiModel).getKnownHeaders());
183 }
184 // Generate WSDL for SEI endpoints(not for Provider endpoints)
185 if (primaryDoc == null) {
186 primaryDoc = generateWSDL(binding, seiModel, docList, container, implType);
187 // create WSDL model
188 wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container);
189 seiModel.freeze(wsdlPort);
190 }
191 // New Features might have been added in WSDL through Policy.
192 // This sets only the wsdl features that are not already set(enabled/disabled)
193 features.mergeFeatures(wsdlPort, false, true);
194 terminal= new SEIInvokerTube(seiModel,invoker,binding);
195 }
196
197 // Process @HandlerChain, if handler-chain is not set via Deployment Descriptor
198 if (processHandlerAnnotation) {
199 processHandlerAnnotation(binding, implType, serviceName, portName);
200 }
201 // Selects only required metadata for this endpoint from the passed-in metadata
202 if (primaryDoc != null) {
203 docList = findMetadataClosure(primaryDoc, docList);
204 }
205 ServiceDefinitionImpl serviceDefiniton = (primaryDoc != null) ? new ServiceDefinitionImpl(docList, primaryDoc) : null;
206
207 return new WSEndpointImpl<T>(serviceName, portName, binding,container,seiModel,wsdlPort,implType, serviceDefiniton,terminal, isTransportSynchronous);
208 }
209
210 /**
211 * Goes through the original metadata documents and collects the required ones.
212 * This done traversing from primary WSDL and its imports until it builds a
213 * complete set of documents(transitive closure) for the endpoint.
214 *
215 * @param primaryDoc primary WSDL doc
216 * @param docList complete metadata
217 * @return new metadata that doesn't contain extraneous documnets.
218 */
219 private static List<SDDocumentImpl> findMetadataClosure(SDDocumentImpl primaryDoc, List<SDDocumentImpl> docList) {
220 // create a map for old metadata
221 Map<String, SDDocumentImpl> oldMap = new HashMap<String, SDDocumentImpl>();
222 for(SDDocumentImpl doc : docList) {
223 oldMap.put(doc.getSystemId().toString(), doc);
224 }
225 // create a map for new metadata
226 Map<String, SDDocumentImpl> newMap = new HashMap<String, SDDocumentImpl>();
227 newMap.put(primaryDoc.getSystemId().toString(), primaryDoc);
228
229 List<String> remaining = new ArrayList<String>();
230 remaining.addAll(primaryDoc.getImports());
231 while(!remaining.isEmpty()) {
232 String url = remaining.remove(0);
233 SDDocumentImpl doc = oldMap.get(url);
234 if (doc == null) {
235 // old metadata doesn't have this imported doc, may be external
236 continue;
237 }
238 // Check if new metadata already contains this doc
239 if (!newMap.containsKey(url)) {
240 newMap.put(url, doc);
241 remaining.addAll(doc.getImports());
242 }
243 }
244 List<SDDocumentImpl> newMetadata = new ArrayList<SDDocumentImpl>();
245 newMetadata.addAll(newMap.values());
246 return newMetadata;
247 }
248
249 private static <T> void processHandlerAnnotation(WSBinding binding, Class<T> implType, QName serviceName, QName portName) {
250 HandlerAnnotationInfo chainInfo =
251 HandlerAnnotationProcessor.buildHandlerInfo(
252 implType, serviceName, portName, binding);
253 if (chainInfo != null) {
254 binding.setHandlerChain(chainInfo.getHandlers());
255 if (binding instanceof SOAPBinding) {
256 ((SOAPBinding) binding).setRoles(chainInfo.getRoles());
257 }
258 }
259
260 }
261
262 /**
263 * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider
264 * annotation
265 *
266 * @return
267 * true if it is a Provider or AsyncProvider endpoint
268 * false otherwise
269 * @throws java.lang.IllegalArgumentException
270 * If it doesn't have any one of @WebService or @WebServiceProvider
271 * If it has both @WebService and @WebServiceProvider annotations
272 */
273 public static boolean verifyImplementorClass(Class<?> clz) {
274 WebServiceProvider wsProvider = clz.getAnnotation(WebServiceProvider.class);
275 WebService ws = clz.getAnnotation(WebService.class);
276 if (wsProvider == null && ws == null) {
277 throw new IllegalArgumentException(clz +" has neither @WebSerivce nor @WebServiceProvider annotation");
278 }
279 if (wsProvider != null && ws != null) {
280 throw new IllegalArgumentException(clz +" has both @WebSerivce and @WebServiceProvider annotations");
281 }
282 if (wsProvider != null) {
283 if (Provider.class.isAssignableFrom(clz) || AsyncProvider.class.isAssignableFrom(clz)) {
284 return true;
285 }
286 throw new IllegalArgumentException(clz +" doesn't implement Provider or AsyncProvider interface");
287 }
288 return false;
289 }
290
291
292 private static AbstractSEIModelImpl createSEIModel(WSDLPort wsdlPort,
293 Class<?> implType, @NotNull QName serviceName, @NotNull QName portName, WSBinding binding) {
294
295 RuntimeModeler rap;
296 // Create runtime model for non Provider endpoints
297
298 // wsdlPort will be null, means we will generate WSDL. Hence no need to apply
299 // bindings or need to look in the WSDL
300 if(wsdlPort == null){
301 rap = new RuntimeModeler(implType,serviceName, binding.getBindingId(), binding.getFeatures().toArray());
302 } else {
303 /*
304 This not needed anymore as wsdlFeatures are merged later anyway
305 and so is the MTOMFeature.
306 applyEffectiveMtomSetting(wsdlPort.getBinding(), binding);
307 */
308 //now we got the Binding so lets build the model
309 rap = new RuntimeModeler(implType, serviceName, (WSDLPortImpl)wsdlPort, binding.getFeatures().toArray());
310 }
311 rap.setPortName(portName);
312 return rap.buildRuntimeModel();
313 }
314
315 /**
316 *Set the mtom enable setting from wsdl model (mtom policy assertion) on to @link WSBinding} if DD has
317 * not already set it on BindingID. Also check conflicts.
318 */
319 /*
320 private static void applyEffectiveMtomSetting(WSDLBoundPortType wsdlBinding, WSBinding binding){
321 if(wsdlBinding.isMTOMEnabled()){
322 BindingID bindingId = binding.getBindingId();
323 if(bindingId.isMTOMEnabled() == null){
324 binding.setMTOMEnabled(true);
325 }else if (bindingId.isMTOMEnabled() != null && bindingId.isMTOMEnabled() == Boolean.FALSE){
326 //TODO: i18N
327 throw new ServerRtException("Deployment failed! Mtom policy assertion in WSDL is enabled whereas the deplyment descriptor setting wants to disable it!");
328 }
329 }
330 }
331 */
332 /**
333 * If service name is not already set via DD or programmatically, it uses
334 * annotations {@link WebServiceProvider}, {@link WebService} on implementorClass to get PortName.
335 *
336 * @return non-null service name
337 */
338 public static @NotNull QName getDefaultServiceName(Class<?> implType) {
339 QName serviceName;
340 WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class);
341 if (wsProvider!=null) {
342 String tns = wsProvider.targetNamespace();
343 String local = wsProvider.serviceName();
344 serviceName = new QName(tns, local);
345 } else {
346 serviceName = RuntimeModeler.getServiceName(implType);
347 }
348 assert serviceName != null;
349 return serviceName;
350 }
351
352 /**
353 * If portName is not already set via DD or programmatically, it uses
354 * annotations on implementorClass to get PortName.
355 *
356 * @return non-null port name
357 */
358 public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType) {
359 QName portName;
360 WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class);
361 if (wsProvider!=null) {
362 String tns = wsProvider.targetNamespace();
363 String local = wsProvider.portName();
364 portName = new QName(tns, local);
365 } else {
366 portName = RuntimeModeler.getPortName(implType, serviceName.getNamespaceURI());
367 }
368 assert portName != null;
369 return portName;
370 }
371
372 /**
373 * Returns the wsdl from @WebService, or @WebServiceProvider annotation using
374 * wsdlLocation element.
375 *
376 * @param implType
377 * endpoint implementation class
378 * make sure that you called {@link #verifyImplementorClass} on it.
379 * @return wsdl if there is wsdlLocation, else null
380 */
381 public static @Nullable String getWsdlLocation(Class<?> implType) {
382 String wsdl;
383 WebService ws = implType.getAnnotation(WebService.class);
384 if (ws != null) {
385 wsdl = ws.wsdlLocation();
386 } else {
387 WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class);
388 assert wsProvider != null;
389 wsdl = wsProvider.wsdlLocation();
390 }
391 if (wsdl.length() < 1) {
392 wsdl = null;
393 }
394 return wsdl;
395 }
396
397 /**
398 * Generates the WSDL and XML Schema for the endpoint if necessary
399 * It generates WSDL only for SOAP1.1, and for XSOAP1.2 bindings
400 */
401 private static SDDocumentImpl generateWSDL(WSBinding binding, AbstractSEIModelImpl seiModel, List<SDDocumentImpl> docs,
402 Container container, Class implType) {
403 BindingID bindingId = binding.getBindingId();
404 if (!bindingId.canGenerateWSDL()) {
405 throw new ServerRtException("can.not.generate.wsdl", bindingId);
406 }
407
408 if (bindingId.toString().equals(SOAPBindingImpl.X_SOAP12HTTP_BINDING)) {
409 String msg = ServerMessages.GENERATE_NON_STANDARD_WSDL();
410 logger.warning(msg);
411 }
412
413 // Generate WSDL and schema documents using runtime model
414 WSDLGenResolver wsdlResolver = new WSDLGenResolver(docs,seiModel.getServiceQName(),seiModel.getPortTypeName());
415 WSDLGenerator wsdlGen = new WSDLGenerator(seiModel, wsdlResolver, binding, container, implType,
416 ServiceFinder.find(WSDLGeneratorExtension.class).toArray());
417 wsdlGen.doGeneration();
418 return wsdlResolver.updateDocs();
419 }
420
421 /**
422 * Builds {@link SDDocumentImpl} from {@link SDDocumentSource}.
423 */
424 private static List<SDDocumentImpl> categoriseMetadata(
425 List<SDDocumentSource> src, QName serviceName, QName portTypeName) {
426
427 List<SDDocumentImpl> r = new ArrayList<SDDocumentImpl>(src.size());
428 for (SDDocumentSource doc : src) {
429 r.add(SDDocumentImpl.create(doc,serviceName,portTypeName));
430 }
431 return r;
432 }
433
434 /**
435 * Verifies whether the given primaryWsdl contains the given serviceName.
436 * If the WSDL doesn't have the service, it throws an WebServiceException.
437 */
438 private static void verifyPrimaryWSDL(@NotNull SDDocumentSource primaryWsdl, @NotNull QName serviceName) {
439 SDDocumentImpl primaryDoc = SDDocumentImpl.create(primaryWsdl,serviceName,null);
440 if (!(primaryDoc instanceof SDDocument.WSDL)) {
441 throw new WebServiceException("Not a primary WSDL="+primaryWsdl.getSystemId());
442 }
443 SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)primaryDoc;
444 if (!wsdlDoc.hasService()) {
445 if(wsdlDoc.getAllServices().isEmpty())
446 throw new WebServiceException("Not a primary WSDL="+primaryWsdl.getSystemId()+
447 " since it doesn't have Service "+serviceName);
448 else
449 throw new WebServiceException("WSDL "+primaryDoc.getSystemId()+" has the following services "+wsdlDoc.getAllServices()+" but not "+serviceName+". Maybe you forgot to specify a service name in @WebService/@WebServiceProvider?");
450 }
451 }
452
453 /**
454 * Finds the primary WSDL document from the list of metadata documents. If
455 * there are two metadata documents that qualify for primary, it throws an
456 * exception. If there are two metadata documents that qualify for porttype,
457 * it throws an exception.
458 *
459 * @return primay wsdl document, null if is not there in the docList
460 *
461 */
462 private static @Nullable SDDocumentImpl findPrimary(@NotNull List<SDDocumentImpl> docList) {
463 SDDocumentImpl primaryDoc = null;
464 boolean foundConcrete = false;
465 boolean foundAbstract = false;
466 for(SDDocumentImpl doc : docList) {
467 if (doc instanceof SDDocument.WSDL) {
468 SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)doc;
469 if (wsdlDoc.hasService()) {
470 primaryDoc = doc;
471 if (foundConcrete) {
472 throw new ServerRtException("duplicate.primary.wsdl", doc.getSystemId() );
473 }
474 foundConcrete = true;
475 }
476 if (wsdlDoc.hasPortType()) {
477 if (foundAbstract) {
478 throw new ServerRtException("duplicate.abstract.wsdl", doc.getSystemId());
479 }
480 foundAbstract = true;
481 }
482 }
483 }
484 return primaryDoc;
485 }
486
487 /**
488 * Parses the primary WSDL and returns the {@link WSDLPort} for the given service and port names
489 *
490 * @param primaryWsdl Primary WSDL
491 * @param metadata it may contain imported WSDL and schema documents
492 * @param serviceName service name in wsdl
493 * @param portName port name in WSDL
494 * @param container container in which this service is running
495 * @return non-null wsdl port object
496 */
497 private static @NotNull WSDLPortImpl getWSDLPort(SDDocumentSource primaryWsdl, List<? extends SDDocumentSource> metadata,
498 @NotNull QName serviceName, @NotNull QName portName, Container container) {
499 URL wsdlUrl = primaryWsdl.getSystemId();
500 try {
501 // TODO: delegate to another entity resolver
502 WSDLModelImpl wsdlDoc = RuntimeWSDLParser.parse(
503 new Parser(primaryWsdl), new EntityResolverImpl(metadata),
504 false, container, ServiceFinder.find(WSDLParserExtension.class).toArray());
505 if(wsdlDoc.getServices().size() == 0) {
506 throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_NOSERVICE_IN_WSDLMODEL(wsdlUrl));
507 }
508 WSDLServiceImpl wsdlService = wsdlDoc.getService(serviceName);
509 if (wsdlService == null) {
510 throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICE(serviceName,wsdlUrl));
511 }
512 WSDLPortImpl wsdlPort = wsdlService.get(portName);
513 if (wsdlPort == null) {
514 throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICEPORT(serviceName, portName, wsdlUrl));
515 }
516 return wsdlPort;
517 } catch (IOException e) {
518 throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e);
519 } catch (XMLStreamException e) {
520 throw new ServerRtException("runtime.saxparser.exception", e.getMessage(), e.getLocation(), e);
521 } catch (SAXException e) {
522 throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e);
523 } catch (ServiceConfigurationError e) {
524 throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e);
525 }
526 }
527
528 /**
529 * {@link XMLEntityResolver} that can resolve to {@link SDDocumentSource}s.
530 */
531 private static final class EntityResolverImpl implements XMLEntityResolver {
532 private Map<String,SDDocumentSource> metadata = new HashMap<String,SDDocumentSource>();
533
534 public EntityResolverImpl(List<? extends SDDocumentSource> metadata) {
535 for (SDDocumentSource doc : metadata) {
536 this.metadata.put(doc.getSystemId().toExternalForm(),doc);
537 }
538 }
539
540 public Parser resolveEntity (String publicId, String systemId) throws IOException, XMLStreamException {
541 if (systemId != null) {
542 SDDocumentSource doc = metadata.get(systemId);
543 if (doc != null)
544 return new Parser(doc);
545 }
546 return null;
547 }
548
549 }
550
551 private static final Logger logger = Logger.getLogger(
552 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.endpoint");
553 }