/* * #%L * Service Locator Commands * %% * Copyright (C) 2011 - 2014 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.commands; import java.text.DateFormat; import java.util.*; import javax.xml.namespace.QName; import org.apache.karaf.shell.api.action.Action; import org.apache.karaf.shell.api.action.Argument; import org.apache.karaf.shell.api.action.Command; import org.apache.karaf.shell.api.action.Completion; import org.apache.karaf.shell.api.action.Option; import org.apache.karaf.shell.api.action.lifecycle.Reference; import org.apache.karaf.shell.api.action.lifecycle.Service; import org.talend.esb.locator.completer.ServiceNameCompleter; import org.talend.esb.locator.tracker.ServiceLocatorTracker; import org.talend.esb.servicelocator.client.SLEndpoint; import org.talend.esb.servicelocator.client.SLProperties; import org.talend.esb.servicelocator.client.ServiceLocator; import org.talend.esb.servicelocator.client.ServiceLocatorException; @Command(scope = "tlocator", name = "list", description = "List Service Locator Endpoints") @Service public class ListOperation implements Action { @Option(name = "-v", aliases = {"--verbose"}, required = false, description = "Verbose output. Prints all service and endpoint attributes.", multiValued = false) boolean verbose; @Option(name = "-ns", aliases = {"--namespace"}, required = false, description = "Prints service name including namespace", multiValued = false) boolean printServiceNamespace; @Option(name = "-p", aliases = {"--protocol"}, required = false, description = "Prints message protocol for endpoints", multiValued = false) boolean printProtocol; @Option(name = "-t", aliases = {"--transport"}, required = false, description = "Prints transport protocol for endpoints", multiValued = false) boolean printTransport; @Option(name = "-d", aliases = {"--date"}, required = false, description = "Prints date for endpoints: online/offline since...", multiValued = false) boolean printDate; @Option(name = "-ep", aliases = {"--properties", "--prop"}, required = false, description = "Prints optional endpoint properties", multiValued = false) boolean printProperties; @Option(name = "-o", aliases = {"--offline-endpoints"}, required = false, description = "Prints only services with at least one offline endpoint", multiValued = false) boolean offlineEndpointsOnly; @Option(name = "-O", aliases = {"--offline-services"}, required = false, description = "Prints only services with no active endpoint", multiValued = false) boolean offlineServicesOnly; @Argument(index = 0, name = "filter", description = "Servicename filter. True if any part of the service name matches this filter. " + "This filter is case sensitive.", required = false, multiValued = false) @Completion(ServiceNameCompleter.class) String filter; @Reference private ServiceLocator sl; @Override public Object execute() throws Exception { ServiceLocatorTracker slt = ServiceLocatorTracker.getInstance(sl); slt.updateServiceList(); try { List<QName> services = new ArrayList<QName>(slt.getServiceQNames()); if (services.isEmpty()) { System.out.println(); System.out.println("No Services registered at Service Locator"); System.out.println(); return null; } sortServices(services); for (QName service : services) { if (filter != null && filter.length() > 0 && !service.toString().contains(filter)) { // Filter is set but does not match continue; } StringBuilder sb = new StringBuilder(); List<SLEndpoint> endpoints = sl.getEndpoints(service); sortEndpoints(endpoints); int offlineEndpointsCount = 0; int onlineEndpointsCount = 0; for (SLEndpoint endpoint : endpoints) { boolean alive = endpoint.isLive(); if (alive) { onlineEndpointsCount++; } else { offlineEndpointsCount++; } if (!offlineEndpointsOnly || offlineEndpointsOnly && !alive) { sb.append(" |-"); sb.append(alive ? "\u001b[1;32m online \u001b[0m : " : "\u001b[1;31m offline\u001b[0m : "); String address = endpoint.getAddress(); sb.append(address); if (printProtocol || verbose) { String protocol = endpoint.getBinding().getValue(); sb.append(" : ").append(protocol); } if (printTransport || verbose) { String transport = endpoint.getTransport().getValue(); sb.append(" : ").append(transport); } if (printDate || verbose) { if (alive) { long lastTimeStarted = endpoint.getLastTimeStarted(); sb.append(" : online since ").append(formatTimeStamp(lastTimeStarted)); } else { long lastTimeStopped = endpoint.getLastTimeStopped(); sb.append(" : offline since ").append(formatTimeStamp(lastTimeStopped)); } } sb.append("\n"); if (printProperties || verbose) { sb.append(printProperties(endpoint.getProperties())); } } } // Now add first line including endpoint count StringBuilder sbServiceName = new StringBuilder(); if (printServiceNamespace || verbose) { sbServiceName.append("{").append(service.getNamespaceURI()).append("}"); } sbServiceName.append("\u001b[1;37m").append(service.getLocalPart()).append("\u001b[0m"); sbServiceName.append(" (").append(onlineEndpointsCount).append("/").append(onlineEndpointsCount + offlineEndpointsCount).append(")"); sbServiceName.append("\n"); sb.insert(0, sbServiceName); // Now print complete StringBuilder content if (!offlineServicesOnly && !offlineEndpointsOnly // No offline filter applied || offlineServicesOnly && onlineEndpointsCount == 0 // Only services with no active endpoint || offlineEndpointsOnly && !offlineServicesOnly && offlineEndpointsCount > 0) // Only offline endpoints { System.out.println(); System.out.println(sb); } } } catch (ServiceLocatorException e) { System.err.println(e.getMessage()); } System.out.println(); return null; } private void sortEndpoints(List<SLEndpoint> endpoints) { Collections.sort(endpoints, new Comparator<SLEndpoint>() { @Override public int compare(SLEndpoint o1, SLEndpoint o2) { if (o1 == null || o1.getAddress() == null) { return -1; } else if (o2 == null) { return 1; } return o1.getAddress().compareTo(o2.getAddress()); } }); } private void sortServices(List<QName> services) { Collections.sort(services, new Comparator<QName>() { @Override public int compare(QName o1, QName o2) { if (o1 == null || o1.getLocalPart() == null) { return -1; } else if (o2 == null) { return 1; } return o1.getLocalPart().compareTo(o2.getLocalPart()); } }); } private String printProperties(SLProperties properties) { StringBuilder sb = new StringBuilder(); Collection<String> keys = properties.getPropertyNames(); if (keys.isEmpty()) { // sb.append(" |- no properties set"); } else { for (String key : keys) { String values = properties.getValues(key).toString(); sb.append(" |- " + key + " : " + values.substring(1, values.length() - 1)).append("\n"); } } return sb.toString(); } private String formatTimeStamp(long timestamp) { String timeStampStr; if (timestamp >= 0) { Calendar timeStarted = Calendar.getInstance(); DateFormat df = DateFormat.getDateTimeInstance(); timeStarted.setTimeInMillis(timestamp); timeStampStr = df.format(timeStarted.getTime()); } else { timeStampStr = ""; } return timeStampStr; } }