/* * #%L * Locator Service :: SOAP * %% * 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.locator.service; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.transform.dom.DOMResult; import javax.xml.ws.wsaddressing.W3CEndpointReference; import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder; import org.talend.esb.servicelocator.client.BindingType; import org.talend.esb.servicelocator.client.ExpiredEndpointCollector; import org.talend.esb.servicelocator.client.SLEndpoint; import org.talend.esb.servicelocator.client.SLProperties; import org.talend.esb.servicelocator.client.SLPropertiesImpl; import org.talend.esb.servicelocator.client.SLPropertiesMatcher; import org.talend.esb.servicelocator.client.ServiceLocator; 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.EndpointTransformerImpl; import org.talend.esb.servicelocator.client.internal.ServiceLocatorImpl; import org.talend.schemas.esb.locator._2011._11.AssertionType; import org.talend.schemas.esb.locator._2011._11.EntryType; import org.talend.schemas.esb.locator._2011._11.InterruptionFaultDetail; import org.talend.schemas.esb.locator._2011._11.LookupEndpointResponse; import org.talend.schemas.esb.locator._2011._11.LookupEndpointsResponse; import org.talend.schemas.esb.locator._2011._11.LookupRequestType; import org.talend.schemas.esb.locator._2011._11.MatcherDataType; import org.talend.schemas.esb.locator._2011._11.SLPropertiesType; import org.talend.schemas.esb.locator._2011._11.ServiceLocatorFaultDetail; import org.talend.services.esb.locator.v1.InterruptedExceptionFault; import org.talend.services.esb.locator.v1.LocatorService; import org.talend.services.esb.locator.v1.ServiceLocatorFault; import org.w3c.dom.Document; public class LocatorSoapServiceImpl implements LocatorService { private static final Logger LOG = Logger .getLogger(LocatorSoapServiceImpl.class.getPackage().getName()); private static final Random RANDOM = new Random(); private ServiceLocator locatorClient; private ExpiredEndpointCollector endpointCollector; private String locatorEndpoints = "localhost:2181"; private int sessionTimeout = 5000; private int connectionTimeout = 5000; private String authenticationName; private String authenticationPassword; public void setLocatorClient(ServiceLocator locatorClient) { this.locatorClient = locatorClient; if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Locator client was set for Soap service."); } } public void setEndpointCollector(ExpiredEndpointCollector endpointCollector) { this.endpointCollector = endpointCollector; } public void setLocatorEndpoints(String locatorEndpoints) { this.locatorEndpoints = locatorEndpoints; } public void setSessionTimeout(int sessionTimeout) { this.sessionTimeout = sessionTimeout; } public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; } public void start() { if (endpointCollector != null) { endpointCollector.startScheduledCollection(); } } /** * Instantiate Service Locator client. After successful instantiation * establish a connection to the Service Locator server. This method will be * called if property locatorClient is null. For this purpose was defined * additional properties to instantiate ServiceLocatorImpl. * * @throws InterruptedException * @throws ServiceLocatorException */ public void initLocator() throws InterruptedException, ServiceLocatorException { if (locatorClient == null) { if (LOG.isLoggable(Level.FINE)) { LOG.fine("Instantiate locatorClient client for Locator Server " + locatorEndpoints + "..."); } ServiceLocatorImpl client = new ServiceLocatorImpl(); client.setLocatorEndpoints(locatorEndpoints); client.setConnectionTimeout(connectionTimeout); client.setSessionTimeout(sessionTimeout); if (null != authenticationName) client.setName(authenticationName); if (null != authenticationPassword) client.setPassword(authenticationPassword); locatorClient = client; locatorClient.connect(); } } /** * Should use as destroy method. Disconnects from a Service Locator server. * All endpoints that were registered before are removed from the server. * Set property locatorClient to null. * * @throws InterruptedException * @throws ServiceLocatorException */ public void disconnectLocator() throws InterruptedException, ServiceLocatorException { if (LOG.isLoggable(Level.FINE)) { LOG.fine("Destroy Locator client"); } if (endpointCollector != null) { endpointCollector.stopScheduledCollection(); } if (locatorClient != null) { locatorClient.disconnect(); locatorClient = null; } } /** * Register the endpoint for given service. * * @param input * RegisterEndpointRequestType encapsulate name of service and * endpointURL. Must not be <code>null</code> */ @Override public void registerEndpoint(QName serviceName, String endpointURL, org.talend.schemas.esb.locator._2011._11.BindingType binding, org.talend.schemas.esb.locator._2011._11.TransportType transport, SLPropertiesType properties) throws ServiceLocatorFault, InterruptedExceptionFault { if (LOG.isLoggable(Level.FINE)) { LOG.fine("Registering endpoint " + endpointURL + " for service " + serviceName + "..."); } try { initLocator(); BindingType bindingType = binding == null ? BindingType.SOAP11 : BindingType.valueOf(binding.value()); TransportType transportType = transport == null ? TransportType.HTTP : TransportType.valueOf(transport.value()); SLPropertiesImpl slProps = null; if (properties != null) { slProps = new SLPropertiesImpl(); List<EntryType> entries = properties.getEntry(); for (EntryType entry : entries) { slProps.addProperty(entry.getKey(), entry.getValue()); } } SimpleEndpoint eprProvider = new SimpleEndpoint(serviceName, endpointURL, bindingType, transportType, slProps); locatorClient.register(eprProvider, true); } catch (ServiceLocatorException e) { ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail(serviceName.toString() + "throws ServiceLocatorFault"); throw new ServiceLocatorFault(e.getMessage(), serviceFaultDetail); } catch (InterruptedException e) { InterruptionFaultDetail interruptionFaultDetail = new InterruptionFaultDetail(); interruptionFaultDetail.setInterruptionDetail(serviceName .toString() + "throws InterruptionFault"); throw new InterruptedExceptionFault(e.getMessage(), interruptionFaultDetail); } } /** * Unregister the endpoint for given service. * * @param input * UnregisterEndpointRequestType encapsulate name of service and * endpointURL. Must not be <code>null</code> */ @Override public void unregisterEndpoint(QName serviceName, String endpointURL) throws ServiceLocatorFault, InterruptedExceptionFault { if (LOG.isLoggable(Level.FINE)) { LOG.fine("Unregistering endpoint " + endpointURL + " for service " + serviceName + "..."); } try { initLocator(); locatorClient.unregister(serviceName, endpointURL); } catch (ServiceLocatorException e) { ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail(serviceName.toString() + "throws ServiceLocatorFault"); throw new ServiceLocatorFault(e.getMessage(), serviceFaultDetail); } catch (InterruptedException e) { InterruptionFaultDetail interruptionFaultDetail = new InterruptionFaultDetail(); interruptionFaultDetail.setInterruptionDetail(serviceName .toString() + "throws InterruptionFault"); throw new InterruptedExceptionFault(e.getMessage(), interruptionFaultDetail); } } /** * @see ServiceLocator */ @Override public void updateTimetolive(QName serviceName, String endpointURL, int timetolive) throws ServiceLocatorFault, InterruptedExceptionFault { if (LOG.isLoggable(Level.FINE)) { LOG.fine("Updating expiring time to happen in " + timetolive + " seconds on endpoint " + endpointURL + " for service " + serviceName + "..."); } try { initLocator(); locatorClient.updateTimetolive(serviceName, endpointURL, timetolive); } catch (ServiceLocatorException e) { ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail(serviceName.toString() + "throws ServiceLocatorFault"); throw new ServiceLocatorFault(e.getMessage(), serviceFaultDetail); } catch (InterruptedException e) { InterruptionFaultDetail interruptionFaultDetail = new InterruptionFaultDetail(); interruptionFaultDetail .setInterruptionDetail(serviceName.toString() + "throws InterruptionFault"); throw new InterruptedExceptionFault(e.getMessage(), interruptionFaultDetail); } } @Override public LookupEndpointResponse lookupEndpoint(LookupRequestType parameters) throws ServiceLocatorFault, InterruptedExceptionFault { W3CEndpointReference epr = lookupEndpoint(parameters.getServiceName(), parameters.getMatcherData()); LookupEndpointResponse response = new LookupEndpointResponse(); response.setEndpointReference(epr); return response; } /** * For the given service return endpoint reference randomly selected from * list of endpoints currently registered at the service locator server. * * @param serviceName * the name of the service for which to get the endpoints, must * not be <code>null</code> * @return endpoint references or <code>null</code> */ W3CEndpointReference lookupEndpoint(QName serviceName, MatcherDataType matcherData) throws ServiceLocatorFault, InterruptedExceptionFault { List<String> names = null; String adress; try { initLocator(); SLPropertiesMatcher matcher = createMatcher(matcherData); if (matcher == null) { names = locatorClient.lookup(serviceName); } else { names = locatorClient.lookup(serviceName, matcher); } } catch (ServiceLocatorException e) { ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail(serviceName.toString() + "throws ServiceLocatorFault"); throw new ServiceLocatorFault(e.getMessage(), serviceFaultDetail); } catch (InterruptedException e) { InterruptionFaultDetail interruptionFaultDetail = new InterruptionFaultDetail(); interruptionFaultDetail.setInterruptionDetail(serviceName .toString() + "throws InterruptionFault"); throw new InterruptedExceptionFault(e.getMessage(), interruptionFaultDetail); } if (names != null && !names.isEmpty()) { names = getRotatedList(names); adress = names.get(0); } else { if (LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, "lookup Endpoint for " + serviceName + " failed, service is not known."); } ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail("lookup Endpoint for " + serviceName + " failed, service is not known."); throw new ServiceLocatorFault("Can not find Endpoint", serviceFaultDetail); } return buildEndpoint(serviceName, adress); } @Override public LookupEndpointsResponse lookupEndpoints(LookupRequestType parameters) throws ServiceLocatorFault, InterruptedExceptionFault { List<W3CEndpointReference> eprs = lookupEndpoints( parameters.getServiceName(), parameters.getMatcherData()); LookupEndpointsResponse response = new LookupEndpointsResponse(); response.getEndpointReference().addAll(eprs); return response; } /** * For the given service name return list of endpoint references currently * registered at the service locator server endpoints. * * @param serviceName * the name of the service for which to get the endpoints, must * not be <code>null</code> * @return EndpointReferenceListType encapsulate list of endpoint references * or <code>null</code> * */ List<W3CEndpointReference> lookupEndpoints(QName serviceName, MatcherDataType matcherData) throws ServiceLocatorFault, InterruptedExceptionFault { SLPropertiesMatcher matcher = createMatcher(matcherData); List<String> names = null; List<W3CEndpointReference> result = new ArrayList<W3CEndpointReference>(); String adress; try { initLocator(); if (matcher == null) { names = locatorClient.lookup(serviceName); } else { names = locatorClient.lookup(serviceName, matcher); } } catch (ServiceLocatorException e) { ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail(serviceName.toString() + "throws ServiceLocatorFault"); throw new ServiceLocatorFault(e.getMessage(), serviceFaultDetail); } catch (InterruptedException e) { InterruptionFaultDetail interruptionFaultDetail = new InterruptionFaultDetail(); interruptionFaultDetail.setInterruptionDetail(serviceName .toString() + "throws InterruptionFault"); throw new InterruptedExceptionFault(e.getMessage(), interruptionFaultDetail); } if (names != null && !names.isEmpty()) { for (int i = 0; i < names.size(); i++) { adress = names.get(i); result.add(buildEndpoint(serviceName, adress)); } } else { if (LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, "lookup Endpoints for " + serviceName + " failed, service is not known."); } ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail("lookup Endpoint for " + serviceName + " failed, service is not known."); throw new ServiceLocatorFault("Can not find Endpoint", serviceFaultDetail); } return result; } private SLPropertiesMatcher createMatcher(MatcherDataType matcherData) { SLPropertiesMatcher matcher = null; if (matcherData != null) { matcher = new SLPropertiesMatcher(); List<AssertionType> assertions = matcherData.getEntry(); for (AssertionType assertion : assertions) { matcher.addAssertion(assertion.getKey(), assertion.getValue()); } } return matcher; } /** * Rotate list of String. Used for randomize selection of received endpoints * * @param strings * list of Strings * @return the same list in random order */ private List<String> getRotatedList(List<String> strings) { int index = RANDOM.nextInt(strings.size()); List<String> rotated = new ArrayList<String>(); for (int i = 0; i < strings.size(); i++) { rotated.add(strings.get(index)); index = (index + 1) % strings.size(); } return rotated; } /** * Build Endpoint Reference for giving service name and address * * @param serviceName * @param adress * @return */ private W3CEndpointReference buildEndpoint(QName serviceName, String adress) throws ServiceLocatorFault, InterruptedExceptionFault { W3CEndpointReferenceBuilder builder = new W3CEndpointReferenceBuilder(); // builder.serviceName(serviceName); builder.address(adress); SLEndpoint endpoint = null; try { endpoint = locatorClient.getEndpoint(serviceName, adress); } catch (ServiceLocatorException e) { ServiceLocatorFaultDetail serviceFaultDetail = new ServiceLocatorFaultDetail(); serviceFaultDetail.setLocatorFaultDetail(serviceName.toString() + "throws ServiceLocatorFault"); throw new ServiceLocatorFault(e.getMessage(), serviceFaultDetail); } catch (InterruptedException e) { InterruptionFaultDetail interruptionFaultDetail = new InterruptionFaultDetail(); interruptionFaultDetail.setInterruptionDetail(serviceName .toString() + "throws InterruptionFault"); throw new InterruptedExceptionFault(e.getMessage(), interruptionFaultDetail); } if (endpoint != null) { SLProperties properties = endpoint.getProperties(); if (properties != null && !properties.getPropertyNames().isEmpty()) { EndpointTransformerImpl transformer = new EndpointTransformerImpl(); DOMResult result = new DOMResult(); transformer.writePropertiesTo(properties, result); Document docResult = (Document) result.getNode(); builder.metadata(docResult.getDocumentElement()); } } return builder.build(); } public void setAuthenticationName(String authenticationName) { this.authenticationName = authenticationName; } public String getAuthenticationName() { return authenticationName; } public void setAuthenticationPassword(String authenticationPassword) { this.authenticationPassword = authenticationPassword; } public String getAuthenticationPassword() { return authenticationPassword; } }