/* * #%L * Service Locator Client for CXF * %% * Copyright (C) 2011 - 2012 Talend Inc. * %% * Licensed 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. * #L% */ package org.talend.esb.servicelocator.cxf.internal; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.namespace.QName; import javax.xml.transform.Result; import org.w3c.dom.Node; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.endpoint.Server; import org.apache.cxf.service.model.BindingInfo; import org.apache.cxf.service.model.EndpointInfo; import org.apache.cxf.service.model.ServiceInfo; import org.apache.cxf.ws.addressing.EndpointReferenceType; import org.apache.cxf.ws.addressing.MetadataType; import org.apache.cxf.wsdl.WSAEndpointReferenceUtils; import org.talend.esb.servicelocator.client.BindingType; import org.talend.esb.servicelocator.client.SLProperties; import org.talend.esb.servicelocator.client.SLPropertiesImpl; import org.talend.esb.servicelocator.client.ServiceLocatorException; import org.talend.esb.servicelocator.client.SimpleEndpoint; import org.talend.esb.servicelocator.client.TransportType; import org.talend.esb.servicelocator.client.internal.SLPropertiesConverter; import org.talend.esb.servicelocator.client.internal.endpoint.ServiceLocatorPropertiesType; public class CXFEndpointProvider implements org.talend.esb.servicelocator.client.Endpoint { static final String SOAP11_BINDING_ID = "http://schemas.xmlsoap.org/wsdl/soap/"; static final String SOAP12_BINDING_ID = "http://schemas.xmlsoap.org/wsdl/soap12/"; static final String JAXRS_BINDING_ID = "http://apache.org/cxf/binding/jaxrs"; static final String CXF_HTTP_TRANSPORT_ID = "http://cxf.apache.org/transports/http"; static final String SOAP_HTTP_TRANSPORT_ID = "http://schemas.xmlsoap.org/soap/http"; private static final Logger LOG = Logger.getLogger(CXFEndpointProvider.class.getName()); private static final org.apache.cxf.ws.addressing.ObjectFactory WSA_OBJECT_FACTORY = new org.apache.cxf.ws.addressing.ObjectFactory(); private static final org.talend.esb.servicelocator.client.internal.endpoint.ObjectFactory SL_OBJECT_FACTORY = new org.talend.esb.servicelocator.client.internal.endpoint.ObjectFactory(); private static volatile JAXBContext jContext; private final QName sName; private final EndpointReferenceType epr; private final BindingType bindingType; private final TransportType transportType; private SLProperties props; /** * Creates a CXFEndpointProvider instance. * @param serviceName * @param endpointReference */ public CXFEndpointProvider(QName serviceName, EndpointReferenceType endpointReference) { this(serviceName, null, null, endpointReference); } /** * Creates a CXFEndpointProvider instance. * @param serviceName * @param bindingId * @param transportId * @param endpointReference */ public CXFEndpointProvider(QName serviceName, String bindingId, String transportId, EndpointReferenceType endpointReference) { sName = serviceName; epr = endpointReference; bindingType = map2BindingType(bindingId); transportType = map2TransportType(transportId); } /** * Creates a CXFEndpointProvider instance. * @param serviceName * @param address * @param properties */ public CXFEndpointProvider(QName serviceName, String address, SLProperties properties) { this(serviceName, createEPR(address, properties)); props = properties; } /** * Creates a CXFEndpointProvider instance. * @param server * @param address * @param properties */ public CXFEndpointProvider(Server server, String address, SLProperties properties) { this(getServiceName(server), getBindingId(server), getTransportId(server), createEPR(server, address, properties)); props = properties; } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#getServiceName() */ @Override public QName getServiceName() { return sName; } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#getAddress() */ @Override public String getAddress() { return epr.getAddress().getValue(); } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#getBinding() */ @Override public BindingType getBinding() { return bindingType; } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#getTransport() */ @Override public TransportType getTransport() { return transportType; } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#getProperties() */ @Override public SLProperties getProperties() { return props != null ? props : SLPropertiesImpl.EMPTY_PROPERTIES; } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#writeEndpointReferenceTo(javax.xml.transform.Result, org.talend.esb.servicelocator.client.Endpoint.PropertiesTransformer) */ @Override public void writeEndpointReferenceTo(Result result, PropertiesTransformer transformer) throws ServiceLocatorException { try { JAXBElement<EndpointReferenceType> ep = WSA_OBJECT_FACTORY.createEndpointReference(epr); createMarshaller().marshal(ep, result); } catch (JAXBException e) { if (LOG.isLoggable(Level.SEVERE)) { LOG.log(Level.SEVERE, "Failed to serialize endpoint data", e); } throw new ServiceLocatorException("Failed to serialize endpoint data", e); } } /* (non-Javadoc) * @see org.talend.esb.servicelocator.client.Endpoint#addEndpointReference(org.w3c.dom.Node) */ @Override public void addEndpointReference(Node parent) throws ServiceLocatorException { serializeEPR(epr, parent); } /** * Inserts a marshalled endpoint reference to a given DOM tree rooted by parent. * @param wsAddr * @param parent * @throws ServiceLocatorException */ private void serializeEPR(EndpointReferenceType wsAddr, Node parent) throws ServiceLocatorException { try { JAXBElement<EndpointReferenceType> ep = WSA_OBJECT_FACTORY.createEndpointReference(wsAddr); createMarshaller().marshal(ep, parent); } catch (JAXBException e) { if (LOG.isLoggable(Level.SEVERE)) { LOG.log(Level.SEVERE, "Failed to serialize endpoint data", e); } throw new ServiceLocatorException("Failed to serialize endpoint data", e); } } /** * Creates a JAXB marshaller. * @return * @throws JAXBException */ private Marshaller createMarshaller() throws JAXBException { JAXBContext jc = getContext(); return jc.createMarshaller(); } private static JAXBContext getContext() throws JAXBException{ if (jContext == null) { jContext = JAXBContext.newInstance( "org.apache.cxf.ws.addressing:" + "org.talend.esb.servicelocator.client.internal.endpoint", SimpleEndpoint.class.getClassLoader()); } return jContext; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object other) { if (other instanceof CXFEndpointProvider) { CXFEndpointProvider otherEndpoint = (CXFEndpointProvider) other; return getAddress().equals(otherEndpoint.getAddress()) && getServiceName().equals(otherEndpoint.getServiceName()); } return false; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int result = 13; int c = getAddress().hashCode(); result = 23 * result + c; c = getServiceName().hashCode(); result = 23 * result + c; return c; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "CXFEndpointProvider with address " + getAddress() + " for service " + getServiceName(); } /** * Creates an endpoint reference from a given adress. * @param address * @param props * @return */ private static EndpointReferenceType createEPR(String address, SLProperties props) { EndpointReferenceType epr = WSAEndpointReferenceUtils.getEndpointReference(address); if (props != null) { addProperties(epr, props); } return epr; } /** * Creates an endpoint reference by duplicating the endpoint reference of a given server. * @param server * @param address * @param props * @return */ private static EndpointReferenceType createEPR(Server server, String address, SLProperties props) { EndpointReferenceType sourceEPR = server.getEndpoint().getEndpointInfo().getTarget(); EndpointReferenceType targetEPR = WSAEndpointReferenceUtils.duplicate(sourceEPR); WSAEndpointReferenceUtils.setAddress(targetEPR, address); if (props != null) { addProperties(targetEPR, props); } return targetEPR; } /** * Adds service locator properties to an endpoint reference. * @param epr * @param props */ private static void addProperties(EndpointReferenceType epr, SLProperties props) { MetadataType metadata = WSAEndpointReferenceUtils.getSetMetadata(epr); ServiceLocatorPropertiesType jaxbProps = SLPropertiesConverter.toServiceLocatorPropertiesType(props); JAXBElement<ServiceLocatorPropertiesType> slp = SL_OBJECT_FACTORY.createServiceLocatorProperties(jaxbProps); metadata.getAny().add(slp); } /** * Extracts the service name from a Server. * @param server * @return */ private static QName getServiceName(Server server) { QName serviceName; String bindingId = getBindingId(server); EndpointInfo eInfo = server.getEndpoint().getEndpointInfo(); if (JAXRS_BINDING_ID.equals(bindingId)) { serviceName = eInfo.getName(); } else { ServiceInfo serviceInfo = eInfo.getService(); serviceName = serviceInfo.getName(); } return serviceName; } /** * Extracts the bindingId from a Server. * @param server * @return */ private static String getBindingId(Server server) { Endpoint ep = server.getEndpoint(); BindingInfo bi = ep.getBinding().getBindingInfo(); return bi.getBindingId(); } /** * Extracts the transportId from a Server. * @param server * @return */ private static String getTransportId(Server server) { return server.getEndpoint().getEndpointInfo().getTransportId(); } /** * Maps a bindingId to its corresponding BindingType. * @param bindingId * @return */ private static BindingType map2BindingType(String bindingId) { BindingType type; if (SOAP11_BINDING_ID.equals(bindingId)) { type = BindingType.SOAP11; } else if (SOAP12_BINDING_ID.equals(bindingId)) { type = BindingType.SOAP12; } else if (JAXRS_BINDING_ID.equals(bindingId)) { type = BindingType.JAXRS; } else { type = BindingType.OTHER; } return type; } /** * Maps a transportId to its corresponding TransportType. * @param transportId * @return */ private static TransportType map2TransportType(String transportId) { TransportType type; if (CXF_HTTP_TRANSPORT_ID.equals(transportId) || SOAP_HTTP_TRANSPORT_ID.equals(transportId)) { type = TransportType.HTTP; } else { type = TransportType.OTHER; } return type; } }