| /* |
| * 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); |
| } |