/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.chemistry.opencmis.client.bindings.spi.webservices;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPException;

import org.apache.chemistry.opencmis.client.bindings.impl.ClientVersion;
import org.apache.chemistry.opencmis.client.bindings.impl.CmisBindingsHelper;
import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
import org.apache.chemistry.opencmis.client.bindings.spi.http.HttpInvoker;
import org.apache.chemistry.opencmis.client.bindings.spi.http.Response;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisProxyAuthenticationException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
import org.apache.chemistry.opencmis.commons.impl.IOUtils;
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
import org.apache.chemistry.opencmis.commons.impl.XMLUtils;
import org.apache.chemistry.opencmis.commons.impl.jaxb.ACLService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.ACLServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.DiscoveryService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.DiscoveryServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.MultiFilingService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.MultiFilingServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.NavigationService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.NavigationServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.ObjectService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.ObjectServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.PolicyService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.PolicyServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.RelationshipService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.RelationshipServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.RepositoryService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.RepositoryServicePort;
import org.apache.chemistry.opencmis.commons.impl.jaxb.VersioningService;
import org.apache.chemistry.opencmis.commons.impl.jaxb.VersioningServicePort;
import org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public abstract class AbstractPortProvider {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractPortProvider.class);

    private static final int PORT_CACHE_SIZE = 5;

    protected static final int CHUNK_SIZE = (64 * 1024) - 1;

    protected enum CmisWebSerivcesService {
        REPOSITORY_SERVICE("RepositoryService", false, RepositoryService.class, RepositoryServicePort.class,
                SessionParameter.WEBSERVICES_REPOSITORY_SERVICE,
                SessionParameter.WEBSERVICES_REPOSITORY_SERVICE_ENDPOINT),

        NAVIGATION_SERVICE("NavigationService", false, NavigationService.class, NavigationServicePort.class,
                SessionParameter.WEBSERVICES_NAVIGATION_SERVICE,
                SessionParameter.WEBSERVICES_NAVIGATION_SERVICE_ENDPOINT),

        OBJECT_SERVICE("ObjectService", true, ObjectService.class, ObjectServicePort.class,
                SessionParameter.WEBSERVICES_OBJECT_SERVICE, SessionParameter.WEBSERVICES_OBJECT_SERVICE_ENDPOINT),

        VERSIONING_SERVICE("VersioningService", true, VersioningService.class, VersioningServicePort.class,
                SessionParameter.WEBSERVICES_VERSIONING_SERVICE,
                SessionParameter.WEBSERVICES_VERSIONING_SERVICE_ENDPOINT),

        DISCOVERY_SERVICE("DiscoveryService", false, DiscoveryService.class, DiscoveryServicePort.class,
                SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, SessionParameter.WEBSERVICES_DISCOVERY_SERVICE_ENDPOINT),

        MULTIFILING_SERVICE("MultiFilingService", false, MultiFilingService.class, MultiFilingServicePort.class,
                SessionParameter.WEBSERVICES_MULTIFILING_SERVICE,
                SessionParameter.WEBSERVICES_MULTIFILING_SERVICE_ENDPOINT),

        RELATIONSHIP_SERVICE("RelationshipService", false, RelationshipService.class, RelationshipServicePort.class,
                SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE,
                SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE_ENDPOINT),

        POLICY_SERVICE("PolicyService", false, PolicyService.class, PolicyServicePort.class,
                SessionParameter.WEBSERVICES_POLICY_SERVICE, SessionParameter.WEBSERVICES_POLICY_SERVICE_ENDPOINT),

        ACL_SERVICE("ACLService", false, ACLService.class, ACLServicePort.class,
                SessionParameter.WEBSERVICES_ACL_SERVICE, SessionParameter.WEBSERVICES_ACL_SERVICE_ENDPOINT);

        private final String name;
        private final QName qname;
        private final boolean handlesContent;
        private final Class<? extends Service> serviceClass;
        private final Class<?> portClass;
        private final String wsdlKey;
        private final String endpointKey;

        CmisWebSerivcesService(String localname, boolean handlesContent, Class<? extends Service> serviceClass,
                Class<?> port11Class, String wsdlKey, String endpointKey) {
            this.name = localname;
            this.qname = new QName("http://docs.oasis-open.org/ns/cmis/ws/200908/", localname);
            this.handlesContent = handlesContent;
            this.serviceClass = serviceClass;
            this.portClass = port11Class;
            this.wsdlKey = wsdlKey;
            this.endpointKey = endpointKey;
        }

        public String getServiceName() {
            return name;
        }

        public QName getQName() {
            return qname;
        }

        public boolean handlesContent() {
            return handlesContent;
        }

        public Class<? extends Service> getServiceClass() {
            return serviceClass;
        }

        public Class<?> getPortClass() {
            return portClass;
        }

        public String getWsdlKey() {
            return wsdlKey;
        }

        public String getEndpointKey() {
            return endpointKey;
        }
    }

    class CmisServiceHolder {
        private final CmisWebSerivcesService service;
        private SoftReference<Service> serviceObject;
        private final URL endpointUrl;

        public CmisServiceHolder(final CmisWebSerivcesService service, final URL endpointUrl)
                throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
            this.service = service;
            this.endpointUrl = endpointUrl;
            this.serviceObject = new SoftReference<Service>(createServiceObject());
        }

        private Service createServiceObject() throws InstantiationException, IllegalAccessException,
                InvocationTargetException, NoSuchMethodException {
            final Constructor<? extends Service> serviceConstructor = service.getServiceClass().getConstructor(
                    new Class<?>[] { URL.class, QName.class });

            URL wsdlUrl = service.getPortClass().getResource("/wsdl/cmis11/CMISWS-Service.wsdl");
            if (LOG.isDebugEnabled()) {
                LOG.debug("Session {}: WSDL URL: {}", getSession().getSessionId(), wsdlUrl.toExternalForm());
            }

            Service newService = serviceConstructor.newInstance(new Object[] { wsdlUrl, service.getQName() });

            AuthenticationProvider authProvider = CmisBindingsHelper.getAuthenticationProvider(getSession());
            if (authProvider != null) {
                HandlerResolver handlerResolver = authProvider.getHandlerResolver();
                if (handlerResolver != null) {
                    newService.setHandlerResolver(handlerResolver);
                }
            }

            return newService;
        }

        public CmisWebSerivcesService getService() {
            return service;
        }

        public Service getServiceObject() throws InstantiationException, IllegalAccessException,
                InvocationTargetException, NoSuchMethodException {
            Service result = serviceObject.get();
            if (result == null) {
                result = createServiceObject();
                serviceObject = new SoftReference<Service>(result);
            }

            return result;
        }

        public URL getEndpointUrl() {
            return endpointUrl;
        }

        public String getServiceName() {
            return service.getServiceName();
        }
    }

    private BindingSession session;
    private boolean useCompression;
    private boolean useClientCompression;
    private String acceptLanguage;

    private final ReentrantLock portObjectLock = new ReentrantLock();
    private final EnumMap<CmisWebSerivcesService, ArrayDeque<SoftReference<BindingProvider>>> portObjectCache = new EnumMap<CmisWebSerivcesService, ArrayDeque<SoftReference<BindingProvider>>>(
            CmisWebSerivcesService.class);

    public BindingSession getSession() {
        return session;
    }

    public void setSession(BindingSession session) {
        this.session = session;

        final Object compression = session.get(SessionParameter.COMPRESSION);
        useCompression = (compression != null) && Boolean.parseBoolean(compression.toString());

        final Object clientCompression = session.get(SessionParameter.CLIENT_COMPRESSION);
        useClientCompression = (clientCompression != null) && Boolean.parseBoolean(clientCompression.toString());

        if (session.get(CmisBindingsHelper.ACCEPT_LANGUAGE) instanceof String) {
            acceptLanguage = session.get(CmisBindingsHelper.ACCEPT_LANGUAGE).toString();
        }
    }

    public boolean useCompression() {
        return useCompression;
    }

    public boolean useClientCompression() {
        return useClientCompression;
    }

    public String getAcceptLanguage() {
        return acceptLanguage;
    }

    /**
     * Return the Repository Service port object.
     */
    public RepositoryServicePort getRepositoryServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.REPOSITORY_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (RepositoryServicePort) portObject;
    }

    /**
     * Return the Navigation Service port object.
     */
    public NavigationServicePort getNavigationServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.NAVIGATION_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (NavigationServicePort) portObject;
    }

    /**
     * Return the Object Service port object.
     */
    public ObjectServicePort getObjectServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.OBJECT_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (ObjectServicePort) portObject;
    }

    /**
     * Return the Versioning Service port object.
     */
    public VersioningServicePort getVersioningServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.VERSIONING_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (VersioningServicePort) portObject;
    }

    /**
     * Return the Discovery Service port object.
     */
    public DiscoveryServicePort getDiscoveryServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.DISCOVERY_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (DiscoveryServicePort) portObject;
    }

    /**
     * Return the MultiFiling Service port object.
     */
    public MultiFilingServicePort getMultiFilingServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.MULTIFILING_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (MultiFilingServicePort) portObject;
    }

    /**
     * Return the Relationship Service port object.
     */
    public RelationshipServicePort getRelationshipServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.RELATIONSHIP_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (RelationshipServicePort) portObject;
    }

    /**
     * Return the Policy Service port object.
     */
    public PolicyServicePort getPolicyServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.POLICY_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (PolicyServicePort) portObject;
    }

    /**
     * Return the ACL Service port object.
     */
    public ACLServicePort getACLServicePort(CmisVersion cmisVersion, String soapAction) {
        BindingProvider portObject = getPortObject(CmisWebSerivcesService.ACL_SERVICE);
        setSoapAction(portObject, soapAction, cmisVersion);

        return (ACLServicePort) portObject;
    }

    public void endCall(Object portObject) {
        AuthenticationProvider authProvider = CmisBindingsHelper.getAuthenticationProvider(session);
        if (authProvider != null && portObject instanceof BindingProvider) {
            BindingProvider bp = (BindingProvider) portObject;
            String url = (String) bp.getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
            if (bp.getResponseContext() != null) {
                @SuppressWarnings("unchecked")
                Map<String, List<String>> headers = (Map<String, List<String>>) bp.getResponseContext().get(
                        MessageContext.HTTP_RESPONSE_HEADERS);
                Integer statusCode = (Integer) bp.getResponseContext().get(MessageContext.HTTP_RESPONSE_CODE);
                authProvider.putResponseHeaders(url, statusCode == null ? -1 : statusCode, headers);
            }

            CmisWebSerivcesService service = null;

            if (portObject instanceof RepositoryServicePort) {
                service = CmisWebSerivcesService.REPOSITORY_SERVICE;
            } else if (portObject instanceof NavigationServicePort) {
                service = CmisWebSerivcesService.NAVIGATION_SERVICE;
            } else if (portObject instanceof ObjectServicePort) {
                service = CmisWebSerivcesService.OBJECT_SERVICE;
            } else if (portObject instanceof VersioningServicePort) {
                service = CmisWebSerivcesService.VERSIONING_SERVICE;
            } else if (portObject instanceof DiscoveryServicePort) {
                service = CmisWebSerivcesService.DISCOVERY_SERVICE;
            } else if (portObject instanceof MultiFilingServicePort) {
                service = CmisWebSerivcesService.MULTIFILING_SERVICE;
            } else if (portObject instanceof RelationshipServicePort) {
                service = CmisWebSerivcesService.RELATIONSHIP_SERVICE;
            } else if (portObject instanceof PolicyServicePort) {
                service = CmisWebSerivcesService.POLICY_SERVICE;
            } else if (portObject instanceof ACLServicePort) {
                service = CmisWebSerivcesService.ACL_SERVICE;
            }

            if (service == null) {
                return;
            }

            portObjectLock.lock();
            try {
                ArrayDeque<SoftReference<BindingProvider>> queue = portObjectCache.get(service);
                if (queue == null) {
                    throw new CmisRuntimeException("This is a bug!");
                }

                if (queue.size() < PORT_CACHE_SIZE) {
                    queue.push(new SoftReference<BindingProvider>(bp));
                } else {
                    Iterator<SoftReference<BindingProvider>> iter = queue.iterator();
                    while (iter.hasNext()) {
                        SoftReference<BindingProvider> ref = iter.next();
                        if (ref.get() == null) {
                            iter.remove();
                            queue.push(new SoftReference<BindingProvider>(bp));
                            break;
                        }
                    }
                }
            } finally {
                portObjectLock.unlock();
            }
        }
    }

    // ---- internal ----

    @SuppressWarnings("unchecked")
    protected BindingProvider getPortObject(final CmisWebSerivcesService service) {
        Map<CmisWebSerivcesService, CmisServiceHolder> serviceMap = (Map<CmisWebSerivcesService, CmisServiceHolder>) session
                .get(SpiSessionParameter.SERVICES);

        // does the service map exist?
        if (serviceMap == null) {
            session.writeLock();
            try {
                // try again
                serviceMap = (Map<CmisWebSerivcesService, CmisServiceHolder>) session.get(SpiSessionParameter.SERVICES);
                if (serviceMap == null) {
                    serviceMap = new EnumMap<CmisWebSerivcesService, CmisServiceHolder>(CmisWebSerivcesService.class);
                    session.put(SpiSessionParameter.SERVICES, serviceMap, true);
                }

                if (serviceMap.containsKey(service)) {
                    return createPortObject(serviceMap.get(service));
                }

                // create service object
                CmisServiceHolder serviceholder = initServiceObject(service);
                serviceMap.put(service, serviceholder);

                // create port object
                return createPortObject(serviceholder);
            } finally {
                session.writeUnlock();
            }
        }

        // is the service in the service map?
        if (!serviceMap.containsKey(service)) {
            session.writeLock();
            try {
                // try again
                if (serviceMap.containsKey(service)) {
                    return createPortObject(serviceMap.get(service));
                }

                // create object
                CmisServiceHolder serviceholder = initServiceObject(service);
                serviceMap.put(service, serviceholder);

                return createPortObject(serviceholder);
            } finally {
                session.writeUnlock();
            }
        }

        return createPortObject(serviceMap.get(service));
    }

    /**
     * Creates a service object.
     */
    protected CmisServiceHolder initServiceObject(final CmisWebSerivcesService service) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Session {}: Initializing Web Service {} ...", getSession().getSessionId(),
                    service.getServiceName());
        }

        try {
            // get URLs
            URL endpointUrl = null;

            String wsdlUrlStr = (String) session.get(service.getWsdlKey());
            if (wsdlUrlStr != null) {
                endpointUrl = getEndpointUrlFromWsdl(wsdlUrlStr, service);
            } else {
                String endpointUrlStr = (String) session.get(service.getEndpointKey());
                if (endpointUrlStr != null) {
                    endpointUrl = new URL(endpointUrlStr);
                }
            }

            if (endpointUrl == null) {
                throw new CmisRuntimeException("Neither a WSDL URL nor an endpoint URL is specified for the service "
                        + service.getServiceName() + "!");
            }

            // build the requested service object
            return new CmisServiceHolder(service, endpointUrl);
        } catch (CmisBaseException ce) {
            throw ce;
        } catch (HTTPException he) {
            String message = "Cannot connect to Web Services [" + service.getServiceName() + "]: " + he.getMessage();
            if (he.getStatusCode() == 401) {
                throw new CmisUnauthorizedException(message, he);
            } else if (he.getStatusCode() == 404) {
                throw new CmisObjectNotFoundException(message, he);
            } else if (he.getStatusCode() == 407) {
                throw new CmisProxyAuthenticationException(message, he);
            } else if (he.getStatusCode() == 301 || he.getStatusCode() == 302 || he.getStatusCode() == 303
                    || he.getStatusCode() == 307) {
                throw new CmisConnectionException("Redirects are not supported (HTTP status code " + he.getStatusCode()
                        + "): " + message, he);
            } else {
                throw new CmisConnectionException(message, he);
            }
        } catch (InvocationTargetException ite) {
            String message = "Cannot initalize Web Services service object [" + service.getServiceName() + "]: "
                    + ite.getCause().getMessage();
            throw new CmisConnectionException(message, ite);
        } catch (Exception e) {
            String message = "Cannot initalize Web Services service object [" + service.getServiceName() + "]: "
                    + e.getMessage();
            throw new CmisConnectionException(message, e);
        }
    }

    /**
     * Reads the URL and extracts the endpoint URL of the given service.
     */
    private URL getEndpointUrlFromWsdl(final String wsdlUrl, final CmisWebSerivcesService service) {
        InputStream wsdlStream;
        URL url;

        // check the WSDL URL
        try {
            url = new URL(wsdlUrl);
        } catch (MalformedURLException e) {
            throw new CmisConnectionException("Invalid WSDL URL: " + wsdlUrl, e);
        }

        // check protocol
        if (url.getProtocol().equalsIgnoreCase("http") || url.getProtocol().equalsIgnoreCase("https")) {
            // HTTP URL -> use HttpInvoker to enable authentication
            HttpInvoker hi = CmisBindingsHelper.getHttpInvoker(session);
            Response wsdlResponse = hi.invokeGET(new UrlBuilder(wsdlUrl), session);

            if (wsdlResponse.getResponseCode() != 200) {
                throw new CmisConnectionException("Cannot access WSDL: " + wsdlUrl, BigInteger.ZERO,
                        wsdlResponse.getErrorContent());
            } else {
                wsdlStream = wsdlResponse.getStream();
            }
        } else {
            // non-HTTP URL -> just open the stream
            try {
                wsdlStream = url.openStream();
            } catch (IOException e) {
                throw new CmisConnectionException("Cannot access WSDL: " + wsdlUrl, e);
            }
        }

        // parse the WSDL
        try {
            final Document doc = XMLUtils.parseDomDocument(new BufferedInputStream(wsdlStream, 64 * 1024));

            NodeList serivceList = doc.getElementsByTagNameNS("http://schemas.xmlsoap.org/wsdl/", "service");
            for (int i = 0; i < serivceList.getLength(); i++) {
                Element serviceNode = (Element) serivceList.item(i);

                String name = serviceNode.getAttribute("name");
                if (name == null) {
                    continue;
                }

                if (!service.getQName().getLocalPart().equals(name)) {
                    continue;
                }

                NodeList portList = serviceNode.getElementsByTagNameNS("http://schemas.xmlsoap.org/wsdl/", "port");
                if (portList.getLength() < 1) {
                    throw new CmisRuntimeException("This service has no ports: " + service.getServiceName());
                }

                Element port = (Element) portList.item(0);

                NodeList addressList = port.getElementsByTagNameNS("http://schemas.xmlsoap.org/wsdl/soap/", "address");
                if (addressList.getLength() < 1) {
                    throw new CmisRuntimeException("This service has no endpoint address: " + service.getServiceName());
                }

                Element address = (Element) addressList.item(0);

                String location = address.getAttribute("location");
                if (location == null) {
                    throw new CmisRuntimeException("This service has no endpoint address: " + service.getServiceName());
                }

                try {
                    return new URL(location);
                } catch (MalformedURLException e) {
                    throw new CmisRuntimeException("This service provides an invalid endpoint address: "
                            + service.getServiceName(), e);
                }
            }

            throw new CmisRuntimeException("This service does not provide an endpoint address: "
                    + service.getServiceName());
        } catch (ParserConfigurationException pe) {
            throw new CmisRuntimeException("Cannot parse this WSDL: " + wsdlUrl, pe);
        } catch (SAXException se) {
            throw new CmisRuntimeException("Cannot parse this WSDL: " + wsdlUrl, se);
        } catch (IOException ioe) {
            throw new CmisRuntimeException("Cannot read this WSDL: " + wsdlUrl, ioe);
        } finally {
            IOUtils.closeQuietly(wsdlStream);
        }
    }

    /**
     * Sets the default HTTP headers on a {@link BindingProvider} object.
     */
    protected void setHTTPHeaders(BindingProvider portObject, Map<String, List<String>> httpHeaders) {
        if (httpHeaders == null) {
            httpHeaders = new HashMap<String, List<String>>();
        }

        // CMIS client header
        httpHeaders.put("X-CMIS-Client", Collections.singletonList(ClientVersion.OPENCMIS_CLIENT));

        // compression
        if (useCompression) {
            httpHeaders.put("Accept-Encoding", Collections.singletonList("gzip"));
        }

        // client compression
        if (useClientCompression) {
            httpHeaders.put("Content-Encoding", Collections.singletonList("gzip"));
        }

        // locale
        if (acceptLanguage != null) {
            httpHeaders.put("Accept-Language", Collections.singletonList(acceptLanguage));
        }

        portObject.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
    }

    /**
     * Sets the endpoint URL if the URL is not <code>null</code>.
     */
    protected void setEndpointUrl(BindingProvider portObject, URL endpointUrl) {
        if (endpointUrl == null) {
            return;
        }

        portObject.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointUrl.toString());
    }

    /**
     * Sets the SOAP Action header.
     */
    protected void setSoapAction(BindingProvider portObject, String soapAction, CmisVersion cmisVersion) {
        portObject.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);

        if (cmisVersion == CmisVersion.CMIS_1_0) {
            portObject.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, "");
        } else {
            portObject.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, soapAction);
        }
    }

    /**
     * Creates a simple port object from a CmisServiceHolder object.
     */
    protected BindingProvider createPortObjectFromServiceHolder(final CmisServiceHolder serviceHolder,
            WebServiceFeature... features) throws Exception {
        portObjectLock.lock();
        try {
            ArrayDeque<SoftReference<BindingProvider>> queue = portObjectCache.get(serviceHolder.getService());
            if (queue == null) {
                queue = new ArrayDeque<SoftReference<BindingProvider>>();
                portObjectCache.put(serviceHolder.getService(), queue);
            }

            while (!queue.isEmpty()) {
                BindingProvider bp = queue.pop().get();
                if (bp != null) {
                    return bp;
                }
            }
        } finally {
            portObjectLock.unlock();
        }

        return (BindingProvider) serviceHolder.getServiceObject().getPort(serviceHolder.getService().getPortClass(),
                features);
    }

    /**
     * Creates a port object.
     */
    protected abstract BindingProvider createPortObject(CmisServiceHolder serviceHolder);
}
