325N/A/*
325N/A * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
325N/A *
325N/A * This code is free software; you can redistribute it and/or modify it
325N/A * under the terms of the GNU General Public License version 2 only, as
325N/A * published by the Free Software Foundation. Oracle designates this
325N/A * particular file as subject to the "Classpath" exception as provided
325N/A * by Oracle in the LICENSE file that accompanied this code.
325N/A *
325N/A * This code is distributed in the hope that it will be useful, but WITHOUT
325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
325N/A * version 2 for more details (a copy is included in the LICENSE file that
325N/A * accompanied this code).
325N/A *
325N/A * You should have received a copy of the GNU General Public License version
325N/A * 2 along with this work; if not, write to the Free Software Foundation,
325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
325N/A *
325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
325N/A * or visit www.oracle.com if you need additional information or have any
325N/A * questions.
325N/A */
325N/A
325N/Apackage com.sun.xml.internal.ws.server;
325N/A
325N/Aimport com.sun.istack.internal.NotNull;
325N/Aimport com.sun.istack.internal.Nullable;
325N/Aimport com.sun.xml.internal.ws.api.BindingID;
325N/Aimport com.sun.xml.internal.ws.api.WSBinding;
325N/Aimport com.sun.xml.internal.ws.api.policy.PolicyResolverFactory;
325N/Aimport com.sun.xml.internal.ws.api.policy.PolicyResolver;
325N/Aimport com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
325N/Aimport com.sun.xml.internal.ws.api.server.*;
325N/Aimport com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
325N/Aimport com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver;
325N/Aimport com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver.Parser;
325N/Aimport com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension;
325N/Aimport com.sun.xml.internal.ws.binding.BindingImpl;
325N/Aimport com.sun.xml.internal.ws.binding.SOAPBindingImpl;
325N/Aimport com.sun.xml.internal.ws.binding.WebServiceFeatureList;
325N/Aimport com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
325N/Aimport com.sun.xml.internal.ws.model.RuntimeModeler;
325N/Aimport com.sun.xml.internal.ws.model.SOAPSEIModel;
325N/Aimport com.sun.xml.internal.ws.model.wsdl.WSDLModelImpl;
325N/Aimport com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl;
325N/Aimport com.sun.xml.internal.ws.model.wsdl.WSDLServiceImpl;
325N/Aimport com.sun.xml.internal.ws.resources.ServerMessages;
325N/Aimport com.sun.xml.internal.ws.server.provider.ProviderInvokerTube;
325N/Aimport com.sun.xml.internal.ws.server.sei.SEIInvokerTube;
325N/Aimport com.sun.xml.internal.ws.util.HandlerAnnotationInfo;
325N/Aimport com.sun.xml.internal.ws.util.HandlerAnnotationProcessor;
325N/Aimport com.sun.xml.internal.ws.util.ServiceConfigurationError;
325N/Aimport com.sun.xml.internal.ws.util.ServiceFinder;
325N/Aimport com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser;
325N/Aimport com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator;
325N/Aimport com.sun.xml.internal.ws.policy.PolicyMap;
325N/Aimport com.sun.xml.internal.ws.policy.jaxws.PolicyUtil;
325N/Aimport org.xml.sax.EntityResolver;
325N/Aimport org.xml.sax.SAXException;
325N/A
325N/Aimport javax.jws.WebService;
325N/Aimport javax.xml.namespace.QName;
325N/Aimport javax.xml.stream.XMLStreamException;
325N/Aimport javax.xml.ws.Provider;
325N/Aimport javax.xml.ws.WebServiceException;
325N/Aimport javax.xml.ws.WebServiceProvider;
325N/Aimport javax.xml.ws.WebServiceFeature;
325N/Aimport javax.xml.ws.soap.SOAPBinding;
325N/Aimport java.io.IOException;
325N/Aimport java.net.URL;
325N/Aimport java.util.ArrayList;
325N/Aimport java.util.Collection;
325N/Aimport java.util.HashMap;
325N/Aimport java.util.List;
325N/Aimport java.util.Map;
325N/Aimport java.util.logging.Logger;
325N/A
325N/A/**
325N/A * Entry point to the JAX-WS RI server-side runtime.
325N/A *
325N/A * @author Kohsuke Kawaguchi
325N/A * @author Jitendra Kotamraju
325N/A */
325N/Apublic class EndpointFactory {
325N/A
325N/A /**
325N/A * Implements {@link WSEndpoint#create}.
325N/A *
325N/A * No need to take WebServiceContext implementation. When InvokerPipe is
325N/A * instantiated, it calls InstanceResolver to set up a WebServiceContext.
325N/A * We shall only take delegate to getUserPrincipal and isUserInRole from adapter.
325N/A *
325N/A * <p>
325N/A * Nobody else should be calling this method.
325N/A */
325N/A public static <T> WSEndpoint<T> createEndpoint(
325N/A Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker,
325N/A @Nullable QName serviceName, @Nullable QName portName,
325N/A @Nullable Container container, @Nullable WSBinding binding,
325N/A @Nullable SDDocumentSource primaryWsdl,
325N/A @Nullable Collection<? extends SDDocumentSource> metadata,
325N/A EntityResolver resolver, boolean isTransportSynchronous) {
325N/A
325N/A if(implType ==null)
325N/A throw new IllegalArgumentException();
325N/A
325N/A verifyImplementorClass(implType);
325N/A
325N/A if (invoker == null) {
325N/A invoker = InstanceResolver.createDefault(implType).createInvoker();
325N/A }
325N/A
325N/A List<SDDocumentSource> md = new ArrayList<SDDocumentSource>();
325N/A if(metadata!=null)
325N/A md.addAll(metadata);
325N/A
325N/A if(primaryWsdl!=null && !md.contains(primaryWsdl))
325N/A md.add(primaryWsdl);
325N/A
325N/A if(container==null)
325N/A container = ContainerResolver.getInstance().getContainer();
325N/A
325N/A if(serviceName==null)
325N/A serviceName = getDefaultServiceName(implType);
325N/A
325N/A if(portName==null)
325N/A portName = getDefaultPortName(serviceName,implType);
325N/A
325N/A {// error check
325N/A String serviceNS = serviceName.getNamespaceURI();
325N/A String portNS = portName.getNamespaceURI();
325N/A if (!serviceNS.equals(portNS)) {
325N/A throw new ServerRtException("wrong.tns.for.port",portNS, serviceNS);
325N/A }
325N/A }
325N/A
325N/A // setting a default binding
325N/A if (binding == null)
325N/A binding = BindingImpl.create(BindingID.parse(implType));
325N/A
325N/A if (primaryWsdl != null) {
325N/A verifyPrimaryWSDL(primaryWsdl, serviceName);
325N/A }
325N/A
325N/A QName portTypeName = null;
325N/A if (implType.getAnnotation(WebServiceProvider.class)==null) {
325N/A portTypeName = RuntimeModeler.getPortTypeName(implType);
325N/A }
325N/A
325N/A // Categorises the documents as WSDL, Schema etc
325N/A List<SDDocumentImpl> docList = categoriseMetadata(md, serviceName, portTypeName);
325N/A // Finds the primary WSDL and makes sure that metadata doesn't have
325N/A // two concrete or abstract WSDLs
325N/A SDDocumentImpl primaryDoc = findPrimary(docList);
325N/A
325N/A InvokerTube terminal;
325N/A WSDLPortImpl wsdlPort = null;
325N/A AbstractSEIModelImpl seiModel = null;
325N/A // create WSDL model
325N/A if (primaryDoc != null) {
325N/A wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container);
325N/A }
325N/A
325N/A WebServiceFeatureList features=((BindingImpl)binding).getFeatures();
325N/A features.parseAnnotations(implType);
325N/A PolicyMap policyMap = null;
325N/A // create terminal pipe that invokes the application
325N/A if (implType.getAnnotation(WebServiceProvider.class)!=null) {
325N/A //TODO incase of Provider, provide a way to User for complete control of the message processing by giving
325N/A // ability to turn off the WSDL/Policy based features and its associated tubes.
325N/A
325N/A //Even in case of Provider, merge all features configured via WSDL/Policy or deployment configuration
325N/A Iterable<WebServiceFeature> configFtrs;
325N/A if(wsdlPort != null) {
325N/A policyMap = wsdlPort.getOwner().getParent().getPolicyMap();
325N/A //Merge features from WSDL and other policy configuration
325N/A configFtrs = wsdlPort.getFeatures();
325N/A } else {
325N/A //No WSDL, so try to merge features from Policy configuration
325N/A policyMap = PolicyResolverFactory.create().resolve(
325N/A new PolicyResolver.ServerContext(null, container, implType, false));
325N/A configFtrs = PolicyUtil.getPortScopedFeatures(policyMap,serviceName,portName);
325N/A }
325N/A features.mergeFeatures(configFtrs, true);
325N/A terminal = ProviderInvokerTube.create(implType,binding,invoker);
325N/A } else {
325N/A // Create runtime model for non Provider endpoints
325N/A seiModel = createSEIModel(wsdlPort, implType, serviceName, portName, binding);
325N/A if(binding instanceof SOAPBindingImpl){
325N/A //set portKnownHeaders on Binding, so that they can be used for MU processing
325N/A ((SOAPBindingImpl)binding).setPortKnownHeaders(
325N/A ((SOAPSEIModel)seiModel).getKnownHeaders());
325N/A }
325N/A // Generate WSDL for SEI endpoints(not for Provider endpoints)
325N/A if (primaryDoc == null) {
325N/A primaryDoc = generateWSDL(binding, seiModel, docList, container, implType);
325N/A // create WSDL model
325N/A wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container);
325N/A seiModel.freeze(wsdlPort);
325N/A }
325N/A policyMap = wsdlPort.getOwner().getParent().getPolicyMap();
325N/A // New Features might have been added in WSDL through Policy.
325N/A //Merge features from WSDL and other policy configuration
325N/A // This sets only the wsdl features that are not already set(enabled/disabled)
325N/A features.mergeFeatures(wsdlPort.getFeatures(), true);
325N/A terminal= new SEIInvokerTube(seiModel,invoker,binding);
325N/A }
325N/A
325N/A // Process @HandlerChain, if handler-chain is not set via Deployment Descriptor
325N/A if (processHandlerAnnotation) {
325N/A processHandlerAnnotation(binding, implType, serviceName, portName);
325N/A }
325N/A // Selects only required metadata for this endpoint from the passed-in metadata
325N/A if (primaryDoc != null) {
325N/A docList = findMetadataClosure(primaryDoc, docList);
325N/A }
325N/A ServiceDefinitionImpl serviceDefiniton = (primaryDoc != null) ? new ServiceDefinitionImpl(docList, primaryDoc) : null;
325N/A
325N/A return new WSEndpointImpl<T>(serviceName, portName, binding,container,seiModel,wsdlPort,implType, serviceDefiniton,terminal, isTransportSynchronous, policyMap);
325N/A }
325N/A
325N/A
325N/A /**
325N/A * Goes through the original metadata documents and collects the required ones.
325N/A * This done traversing from primary WSDL and its imports until it builds a
325N/A * complete set of documents(transitive closure) for the endpoint.
325N/A *
325N/A * @param primaryDoc primary WSDL doc
325N/A * @param docList complete metadata
325N/A * @return new metadata that doesn't contain extraneous documnets.
325N/A */
325N/A private static List<SDDocumentImpl> findMetadataClosure(SDDocumentImpl primaryDoc, List<SDDocumentImpl> docList) {
325N/A // create a map for old metadata
325N/A Map<String, SDDocumentImpl> oldMap = new HashMap<String, SDDocumentImpl>();
325N/A for(SDDocumentImpl doc : docList) {
325N/A oldMap.put(doc.getSystemId().toString(), doc);
325N/A }
325N/A // create a map for new metadata
325N/A Map<String, SDDocumentImpl> newMap = new HashMap<String, SDDocumentImpl>();
325N/A newMap.put(primaryDoc.getSystemId().toString(), primaryDoc);
325N/A
325N/A List<String> remaining = new ArrayList<String>();
325N/A remaining.addAll(primaryDoc.getImports());
325N/A while(!remaining.isEmpty()) {
325N/A String url = remaining.remove(0);
325N/A SDDocumentImpl doc = oldMap.get(url);
325N/A if (doc == null) {
325N/A // old metadata doesn't have this imported doc, may be external
325N/A continue;
325N/A }
325N/A // Check if new metadata already contains this doc
325N/A if (!newMap.containsKey(url)) {
325N/A newMap.put(url, doc);
325N/A remaining.addAll(doc.getImports());
325N/A }
325N/A }
325N/A List<SDDocumentImpl> newMetadata = new ArrayList<SDDocumentImpl>();
325N/A newMetadata.addAll(newMap.values());
325N/A return newMetadata;
325N/A }
325N/A
325N/A private static <T> void processHandlerAnnotation(WSBinding binding, Class<T> implType, QName serviceName, QName portName) {
325N/A HandlerAnnotationInfo chainInfo =
325N/A HandlerAnnotationProcessor.buildHandlerInfo(
325N/A implType, serviceName, portName, binding);
325N/A if (chainInfo != null) {
325N/A binding.setHandlerChain(chainInfo.getHandlers());
325N/A if (binding instanceof SOAPBinding) {
325N/A ((SOAPBinding) binding).setRoles(chainInfo.getRoles());
325N/A }
325N/A }
325N/A
325N/A }
325N/A
325N/A /**
325N/A * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider
325N/A * annotation
325N/A *
325N/A * @return
325N/A * true if it is a Provider or AsyncProvider endpoint
325N/A * false otherwise
325N/A * @throws java.lang.IllegalArgumentException
325N/A * If it doesn't have any one of @WebService or @WebServiceProvider
325N/A * If it has both @WebService and @WebServiceProvider annotations
325N/A */
325N/A public static boolean verifyImplementorClass(Class<?> clz) {
325N/A WebServiceProvider wsProvider = clz.getAnnotation(WebServiceProvider.class);
325N/A WebService ws = clz.getAnnotation(WebService.class);
325N/A if (wsProvider == null && ws == null) {
325N/A throw new IllegalArgumentException(clz +" has neither @WebService nor @WebServiceProvider annotation");
325N/A }
325N/A if (wsProvider != null && ws != null) {
325N/A throw new IllegalArgumentException(clz +" has both @WebService and @WebServiceProvider annotations");
325N/A }
325N/A if (wsProvider != null) {
325N/A if (Provider.class.isAssignableFrom(clz) || AsyncProvider.class.isAssignableFrom(clz)) {
325N/A return true;
325N/A }
325N/A throw new IllegalArgumentException(clz +" doesn't implement Provider or AsyncProvider interface");
325N/A }
325N/A return false;
325N/A }
325N/A
325N/A
325N/A private static AbstractSEIModelImpl createSEIModel(WSDLPort wsdlPort,
325N/A Class<?> implType, @NotNull QName serviceName, @NotNull QName portName, WSBinding binding) {
325N/A
325N/A RuntimeModeler rap;
325N/A // Create runtime model for non Provider endpoints
325N/A
325N/A // wsdlPort will be null, means we will generate WSDL. Hence no need to apply
325N/A // bindings or need to look in the WSDL
325N/A if(wsdlPort == null){
325N/A rap = new RuntimeModeler(implType,serviceName, binding.getBindingId(), binding.getFeatures().toArray());
325N/A } else {
325N/A /*
325N/A This not needed anymore as wsdlFeatures are merged later anyway
325N/A and so is the MTOMFeature.
325N/A applyEffectiveMtomSetting(wsdlPort.getBinding(), binding);
325N/A */
325N/A //now we got the Binding so lets build the model
325N/A rap = new RuntimeModeler(implType, serviceName, (WSDLPortImpl)wsdlPort, binding.getFeatures().toArray());
325N/A }
325N/A rap.setClassLoader(implType.getClassLoader());
325N/A rap.setPortName(portName);
325N/A return rap.buildRuntimeModel();
325N/A }
325N/A
325N/A /**
325N/A *Set the mtom enable setting from wsdl model (mtom policy assertion) on to @link WSBinding} if DD has
325N/A * not already set it on BindingID. Also check conflicts.
325N/A */
325N/A /*
325N/A private static void applyEffectiveMtomSetting(WSDLBoundPortType wsdlBinding, WSBinding binding){
325N/A if(wsdlBinding.isMTOMEnabled()){
325N/A BindingID bindingId = binding.getBindingId();
325N/A if(bindingId.isMTOMEnabled() == null){
325N/A binding.setMTOMEnabled(true);
325N/A }else if (bindingId.isMTOMEnabled() != null && bindingId.isMTOMEnabled() == Boolean.FALSE){
325N/A //TODO: i18N
325N/A throw new ServerRtException("Deployment failed! Mtom policy assertion in WSDL is enabled whereas the deplyment descriptor setting wants to disable it!");
325N/A }
325N/A }
325N/A }
325N/A */
325N/A /**
325N/A * If service name is not already set via DD or programmatically, it uses
325N/A * annotations {@link WebServiceProvider}, {@link WebService} on implementorClass to get PortName.
325N/A *
325N/A * @return non-null service name
325N/A */
325N/A public static @NotNull QName getDefaultServiceName(Class<?> implType) {
325N/A QName serviceName;
325N/A WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class);
325N/A if (wsProvider!=null) {
325N/A String tns = wsProvider.targetNamespace();
325N/A String local = wsProvider.serviceName();
325N/A serviceName = new QName(tns, local);
325N/A } else {
325N/A serviceName = RuntimeModeler.getServiceName(implType);
325N/A }
325N/A assert serviceName != null;
325N/A return serviceName;
325N/A }
325N/A
325N/A /**
325N/A * If portName is not already set via DD or programmatically, it uses
325N/A * annotations on implementorClass to get PortName.
325N/A *
325N/A * @return non-null port name
325N/A */
325N/A public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType) {
325N/A QName portName;
325N/A WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class);
325N/A if (wsProvider!=null) {
325N/A String tns = wsProvider.targetNamespace();
325N/A String local = wsProvider.portName();
325N/A portName = new QName(tns, local);
325N/A } else {
325N/A portName = RuntimeModeler.getPortName(implType, serviceName.getNamespaceURI());
325N/A }
325N/A assert portName != null;
325N/A return portName;
325N/A }
325N/A
325N/A /**
325N/A * Returns the wsdl from @WebService, or @WebServiceProvider annotation using
325N/A * wsdlLocation element.
325N/A *
325N/A * @param implType
325N/A * endpoint implementation class
325N/A * make sure that you called {@link #verifyImplementorClass} on it.
325N/A * @return wsdl if there is wsdlLocation, else null
325N/A */
325N/A public static @Nullable String getWsdlLocation(Class<?> implType) {
325N/A String wsdl;
325N/A WebService ws = implType.getAnnotation(WebService.class);
325N/A if (ws != null) {
325N/A wsdl = ws.wsdlLocation();
325N/A } else {
325N/A WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class);
325N/A assert wsProvider != null;
325N/A wsdl = wsProvider.wsdlLocation();
325N/A }
325N/A if (wsdl.length() < 1) {
325N/A wsdl = null;
325N/A }
325N/A return wsdl;
325N/A }
325N/A
325N/A /**
325N/A * Generates the WSDL and XML Schema for the endpoint if necessary
325N/A * It generates WSDL only for SOAP1.1, and for XSOAP1.2 bindings
325N/A */
325N/A private static SDDocumentImpl generateWSDL(WSBinding binding, AbstractSEIModelImpl seiModel, List<SDDocumentImpl> docs,
325N/A Container container, Class implType) {
325N/A BindingID bindingId = binding.getBindingId();
325N/A if (!bindingId.canGenerateWSDL()) {
325N/A throw new ServerRtException("can.not.generate.wsdl", bindingId);
325N/A }
325N/A
325N/A if (bindingId.toString().equals(SOAPBindingImpl.X_SOAP12HTTP_BINDING)) {
325N/A String msg = ServerMessages.GENERATE_NON_STANDARD_WSDL();
325N/A logger.warning(msg);
325N/A }
325N/A
325N/A // Generate WSDL and schema documents using runtime model
325N/A WSDLGenResolver wsdlResolver = new WSDLGenResolver(docs,seiModel.getServiceQName(),seiModel.getPortTypeName());
325N/A WSDLGenerator wsdlGen = new WSDLGenerator(seiModel, wsdlResolver, binding, container, implType, false,
325N/A ServiceFinder.find(WSDLGeneratorExtension.class).toArray());
325N/A wsdlGen.doGeneration();
325N/A return wsdlResolver.updateDocs();
325N/A }
325N/A
325N/A /**
325N/A * Builds {@link SDDocumentImpl} from {@link SDDocumentSource}.
325N/A */
325N/A private static List<SDDocumentImpl> categoriseMetadata(
325N/A List<SDDocumentSource> src, QName serviceName, QName portTypeName) {
325N/A
325N/A List<SDDocumentImpl> r = new ArrayList<SDDocumentImpl>(src.size());
325N/A for (SDDocumentSource doc : src) {
325N/A r.add(SDDocumentImpl.create(doc,serviceName,portTypeName));
325N/A }
325N/A return r;
325N/A }
325N/A
325N/A /**
325N/A * Verifies whether the given primaryWsdl contains the given serviceName.
325N/A * If the WSDL doesn't have the service, it throws an WebServiceException.
325N/A */
325N/A private static void verifyPrimaryWSDL(@NotNull SDDocumentSource primaryWsdl, @NotNull QName serviceName) {
325N/A SDDocumentImpl primaryDoc = SDDocumentImpl.create(primaryWsdl,serviceName,null);
325N/A if (!(primaryDoc instanceof SDDocument.WSDL)) {
325N/A throw new WebServiceException(primaryWsdl.getSystemId()+
325N/A " is not a WSDL. But it is passed as a primary WSDL");
325N/A }
325N/A SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)primaryDoc;
325N/A if (!wsdlDoc.hasService()) {
325N/A if(wsdlDoc.getAllServices().isEmpty())
325N/A throw new WebServiceException("Not a primary WSDL="+primaryWsdl.getSystemId()+
325N/A " since it doesn't have Service "+serviceName);
325N/A else
325N/A throw new WebServiceException("WSDL "+primaryDoc.getSystemId()
325N/A +" has the following services "+wsdlDoc.getAllServices()
325N/A +" but not "+serviceName+". Maybe you forgot to specify a serviceName and/or targetNamespace in @WebService/@WebServiceProvider?");
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Finds the primary WSDL document from the list of metadata documents. If
325N/A * there are two metadata documents that qualify for primary, it throws an
325N/A * exception. If there are two metadata documents that qualify for porttype,
325N/A * it throws an exception.
325N/A *
325N/A * @return primay wsdl document, null if is not there in the docList
325N/A *
325N/A */
325N/A private static @Nullable SDDocumentImpl findPrimary(@NotNull List<SDDocumentImpl> docList) {
325N/A SDDocumentImpl primaryDoc = null;
325N/A boolean foundConcrete = false;
325N/A boolean foundAbstract = false;
325N/A for(SDDocumentImpl doc : docList) {
325N/A if (doc instanceof SDDocument.WSDL) {
325N/A SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)doc;
325N/A if (wsdlDoc.hasService()) {
325N/A primaryDoc = doc;
325N/A if (foundConcrete) {
325N/A throw new ServerRtException("duplicate.primary.wsdl", doc.getSystemId() );
325N/A }
325N/A foundConcrete = true;
325N/A }
325N/A if (wsdlDoc.hasPortType()) {
325N/A if (foundAbstract) {
325N/A throw new ServerRtException("duplicate.abstract.wsdl", doc.getSystemId());
325N/A }
325N/A foundAbstract = true;
325N/A }
325N/A }
325N/A }
325N/A return primaryDoc;
325N/A }
325N/A
325N/A /**
325N/A * Parses the primary WSDL and returns the {@link WSDLPort} for the given service and port names
325N/A *
325N/A * @param primaryWsdl Primary WSDL
325N/A * @param metadata it may contain imported WSDL and schema documents
325N/A * @param serviceName service name in wsdl
325N/A * @param portName port name in WSDL
325N/A * @param container container in which this service is running
325N/A * @return non-null wsdl port object
325N/A */
325N/A private static @NotNull WSDLPortImpl getWSDLPort(SDDocumentSource primaryWsdl, List<? extends SDDocumentSource> metadata,
325N/A @NotNull QName serviceName, @NotNull QName portName, Container container) {
325N/A URL wsdlUrl = primaryWsdl.getSystemId();
325N/A try {
325N/A // TODO: delegate to another entity resolver
325N/A WSDLModelImpl wsdlDoc = RuntimeWSDLParser.parse(
325N/A new Parser(primaryWsdl), new EntityResolverImpl(metadata),
325N/A false, container, ServiceFinder.find(WSDLParserExtension.class).toArray());
325N/A if(wsdlDoc.getServices().size() == 0) {
325N/A throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_NOSERVICE_IN_WSDLMODEL(wsdlUrl));
325N/A }
325N/A WSDLServiceImpl wsdlService = wsdlDoc.getService(serviceName);
325N/A if (wsdlService == null) {
325N/A throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICE(serviceName,wsdlUrl));
325N/A }
325N/A WSDLPortImpl wsdlPort = wsdlService.get(portName);
325N/A if (wsdlPort == null) {
325N/A throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICEPORT(serviceName, portName, wsdlUrl));
325N/A }
325N/A return wsdlPort;
325N/A } catch (IOException e) {
325N/A throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e);
325N/A } catch (XMLStreamException e) {
325N/A throw new ServerRtException("runtime.saxparser.exception", e.getMessage(), e.getLocation(), e);
325N/A } catch (SAXException e) {
325N/A throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e);
325N/A } catch (ServiceConfigurationError e) {
325N/A throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e);
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * {@link XMLEntityResolver} that can resolve to {@link SDDocumentSource}s.
325N/A */
325N/A private static final class EntityResolverImpl implements XMLEntityResolver {
325N/A private Map<String,SDDocumentSource> metadata = new HashMap<String,SDDocumentSource>();
325N/A
325N/A public EntityResolverImpl(List<? extends SDDocumentSource> metadata) {
325N/A for (SDDocumentSource doc : metadata) {
325N/A this.metadata.put(doc.getSystemId().toExternalForm(),doc);
325N/A }
325N/A }
325N/A
325N/A public Parser resolveEntity (String publicId, String systemId) throws IOException, XMLStreamException {
325N/A if (systemId != null) {
325N/A SDDocumentSource doc = metadata.get(systemId);
325N/A if (doc != null)
325N/A return new Parser(doc);
325N/A }
325N/A return null;
325N/A }
325N/A
325N/A }
325N/A
325N/A private static final Logger logger = Logger.getLogger(
325N/A com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.endpoint");
325N/A}