/* * Copyright 2008 the original author or authors. * * 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. */ package org.rioproject.tools.cli; import net.jini.core.lookup.ServiceItem; import org.rioproject.cybernode.Cybernode; import org.rioproject.deploy.DeployAdmin; import org.rioproject.deploy.ServiceBeanInstance; import org.rioproject.deploy.ServiceRecord; import org.rioproject.monitor.ProvisionMonitor; import org.rioproject.opstring.OperationalStringManager; import org.rioproject.opstring.ServiceElement; import org.rioproject.tools.cli.ServiceFinder.ServiceInfo; import org.rioproject.util.TimeUtil; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintStream; import java.rmi.RemoteException; import java.util.*; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** * Utility class for formatting results * * @author Dennis Reedy */ public class Formatter { static final int MAX_ITEM_LENGTH = 60; public static String asList(final ServiceItem[] items) { String[] array = formattedArray(items); StringBuilder buffer = new StringBuilder(); for(int i=0; i<array.length; i++) { if(i>0) buffer.append("\n"); buffer.append(array[i]); } return(buffer.toString()); } public static String asChoices(final ServiceItem[] items) { StringBuilder buffer = new StringBuilder(asList(items)); buffer.append(String.format("%n%-5s all", (Object[]) new String[] {"["+(items.length+1)+"]"})); return(buffer.toString()); } public static String[] formattedArray(final ServiceItem[] items) { List<OutputInfo> list = new ArrayList<OutputInfo>(); ServiceInfo[] serviceInfo = CLI.getInstance().finder.getServiceInfo(); for(int i=0; i<items.length; i++) { ServiceInfo sInfo = null; for (ServiceInfo aServiceInfo : serviceInfo) { ServiceItem item = aServiceInfo.getServiceItem(); if (item.serviceID.equals(items[i].serviceID)) { sInfo = aServiceInfo; break; } } if(sInfo==null) { sInfo = new ServiceInfo(items[i]); Future<ServiceInfo> future = CLI.getInstance().finder.resolveServiceInfo(sInfo); try { sInfo = future.get(5, TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); } } String name = sInfo.getServiceName(); String[] groups = sInfo.getGroups(); String host = sInfo.getHost(); if(groups==null) groups = new String[]{"<?>"}; String[] optionValues= new String[] {"", "", ""}; OutputInfo oi = new OutputInfo(); oi.itemNum = "["+(i+1)+"]"; oi.name = truncate(name); oi.groups = truncate(fromArray(groups)); oi.host = truncate(host); oi.option0 = optionValues[0].trim(); oi.option1 = optionValues[1].trim(); oi.option2 = optionValues[2].trim(); list.add(oi); } OutputInfo[] outputInfos = list.toArray(new OutputInfo[list.size()]); List<String> output = new ArrayList<String>(); int[] widths = new int[]{0, 0, 0, 0, 0, 0, 0}; for (OutputInfo outputInfo : outputInfos) { widths[0] = getLongest(outputInfo.itemNum, widths[0]); widths[1] = getLongest(outputInfo.name, widths[1]); widths[2] = getLongest(outputInfo.groups, widths[2]); widths[3] = getLongest(outputInfo.host, widths[3]); widths[4] = getLongest(outputInfo.option0, widths[4]); widths[5] = getLongest(outputInfo.option1, widths[5]); widths[6] = getLongest(outputInfo.option2, widths[6]); } /* add some padding */ widths[0]+=2; widths[1]+=2; widths[2]+=2; widths[3]+=2; for (OutputInfo anOi : outputInfos) { output.add(String.format("%-" + widths[0] + "s " + "%-" + widths[1] + "s " + "%-" + widths[2] + "s " + "%-" + widths[3] + "s " + getFormatString(widths[4]) + " " + getFormatString(widths[5]) + " " + getFormatString(widths[6]), anOi.itemNum, anOi.name, anOi.groups, anOi.host, anOi.option0, anOi.option1, anOi.option2)); } return(output.toArray(new String[list.size()])); } /* * Container class for holding information to be formatted */ private static class OutputInfo { String itemNum; String name; String groups; String host; String option0; String option1; String option2; } private static String truncate(final String s) { String toTruncate = s; if(s.length()> MAX_ITEM_LENGTH) { toTruncate = s.substring(0, (MAX_ITEM_LENGTH-3))+"..."; } return toTruncate; } /* * Get the longest length element */ private static int getLongest(final String s, final int i) { return(Math.max(s.length(), i)); } /* * Get the format string */ private static String getFormatString(final int w) { return((w==0?"%s":"%-"+w+"s")); } /** * Produce output for an array of Cybernodes * * @param items Array of ServiceItems * @param br A BufferedReader, allows for the user to press enter for more * @param out The output PrintStream */ public static void cybernodeLister(final ServiceItem[] items, final BufferedReader br, final PrintStream out) { Integer listLength = (Integer) CLI.getInstance().settings.get(CLI.LIST_LENGTH); String[] cybernodes = Formatter.formattedArray(items); for(int i=0, lineCounter=1; i<cybernodes.length; i++,lineCounter++) { if(lineCounter % listLength==0 && cybernodes.length > lineCounter) { out.println(cybernodes[i]); promptMore(br, out); } else { out.println(cybernodes[i]); if(items[i].service instanceof Cybernode) { listCybernode((Cybernode)items[i].service, br, out, lineCounter); } else { out.println("\tNot a Cybernode"); } } } out.println(); } /** * Produce output for an Cybernode * * @param cybernode The Cybernode * @param br A BufferredReader, allows for the user to press enter for more * @param out The output PrintStream * @param lineCounter the current line counter */ private static void listCybernode(final Cybernode cybernode, final BufferedReader br, final PrintStream out, final int lineCounter) { Integer listLength = (Integer) CLI.getInstance().settings.get(CLI.LIST_LENGTH); try { ServiceRecord[] records = cybernode.getServiceRecords(ServiceRecord.ACTIVE_SERVICE_RECORD); String status; try { status = cybernode.isEnlisted()?"enlisted":"released"; } catch (RemoteException e) { status = e.getMessage(); } out.println("\tStatus: "+status); if(records.length==0) { out.println("\tNo contained services"); } else { /* Sort by opstring */ Map<String, List<ServiceRecord>> map = new HashMap<String, List<ServiceRecord>>(); for (ServiceRecord record : records) { String opstring = record.getServiceElement().getOperationalStringName(); List<ServiceRecord> services; if(map.containsKey(opstring)) { services = map.get(opstring); } else { services = new ArrayList<ServiceRecord>(); } services.add(record); map.put(opstring, services); } int counter = lineCounter; for(Map.Entry<String, List<ServiceRecord>> entry : map.entrySet()) { String opstring = entry.getKey(); out.println(opstring); counter++; List<ServiceRecord> recordList = entry.getValue(); for (ServiceRecord record : recordList) { String groups = fromArray(record.getServiceElement().getServiceBeanConfig().getGroups()); String elapsed =TimeUtil.format(record.computeElapsedTime()); if(counter % listLength==0) promptMore(br, out); System.out.format("\t%-18.18s %-18.18s %20s%n", record.getName(), groups, elapsed); counter++; } } } } catch(Exception e) { e.printStackTrace(); } } /** * Produce output for an array of Provision Managers * * @param items Array of ServiceItems * @param br A BufferredReader, allows for the user to press enter for more * @param out The output PrintStream */ public static void provisionManagerLister(final ServiceItem[] items, final BufferedReader br, final PrintStream out) { Integer listLength = (Integer) CLI.getInstance().settings.get(CLI.LIST_LENGTH); String[] provisioners = Formatter.formattedArray(items); for(int i=0, lineCounter=1; i<provisioners.length; i++,lineCounter++) { if(lineCounter % listLength==0) promptMore(br, out); out.println(provisioners[i]); try { if(items[i].service instanceof ProvisionMonitor) { DeployAdmin deployAdmin = (DeployAdmin)((ProvisionMonitor)items[i].service).getAdmin(); OperationalStringManager[] opMgrs = deployAdmin.getOperationalStringManagers(); if(opMgrs.length==0) out.println("\tNo Managed Deployments"); for (OperationalStringManager opMgr : opMgrs) { listMgr(opMgr, br, out, lineCounter); } } else { out.println("\tNot a Provision Manager"); } } catch(Exception e) { e.printStackTrace(); } } out.println(); } /** * Produce output for an OperationalStringManager * * @param opMgr The OperationalStringManager * @param br A BufferredReader, allows for the user to press enter for more * @param out The output PrintStream * @param lineCounter the current line counter */ private static void listMgr(final OperationalStringManager opMgr, final BufferedReader br, final PrintStream out, final int lineCounter) { Integer listLength = (Integer) CLI.getInstance().settings.get(CLI.LIST_LENGTH); String pad = " "; String role = "primary"; int counter = lineCounter; try { if(!opMgr.isManaging()) role = "backup"; out.println("\t"+opMgr.getOperationalString().getName()+"\trole="+role); counter++; if(counter % listLength==0) promptMore(br, out); ServiceElement[] sElems = opMgr.getOperationalString().getServices(); for (ServiceElement sElem : sElems) { String pending = "pending="; if (role.equals("backup")) { pending = pending + "<n/a>"; } else { pending = pending + opMgr.getPendingCount(sElem); } if(counter % listLength==0) promptMore(br, out); out.println(String.format("\t%s%-30s planned=%-3s actual=%-3s %s", pad, sElem.getName(), sElem.getPlanned(), sElem.getActual(), pending)); counter++; ServiceBeanInstance[] instances = opMgr.getServiceBeanInstances(sElem); for (ServiceBeanInstance instance : instances) { Long id = instance.getServiceBeanConfig().getInstanceID(); if(counter % listLength==0) promptMore(br, out); out.println(String.format("\t%s%sid=%-3s\t%s", pad, pad, id, instance.getHostName())); counter++; } } } catch(Exception e) { e.printStackTrace(); } } /** * Utility to convert a String array to a comma delimited String * @param array An array of Strings, must not be null * * @return A comma delimited String. If the array is empty, return a String * with zero-length */ public static String fromArray(final String[] array) { return(fromArray(array, ", ")); } /** * Utility to convert a String array to a delimited String * * @param array An array of Strings, must not be null * @param delim Delimiter to use between Strings, must not be null * * @return A comma delimited String. If the array is empty, return a String * with zero-length */ public static String fromArray(final String[] array, final String delim) { if(array==null) throw new IllegalArgumentException("array is null"); if(delim==null) throw new IllegalArgumentException("delim is null"); StringBuilder buffer = new StringBuilder(); for(int i=0; i<array.length; i++) { if(i>0) buffer.append(delim); buffer.append(array[i]); } return(buffer.toString()); } /** * Convert comma-separated String to array of Strings * * @param arg The comma separated string * * @return A converted array of strings */ public static String[] toArray(final String arg) { StringTokenizer tok = new StringTokenizer(arg, " ,"); String[] array = new String[tok.countTokens()]; int i=0; while(tok.hasMoreTokens()) { array[i] = tok.nextToken(); i++; } return(array); } public static void promptMore(final BufferedReader br, final PrintStream out) { out.print("-- more --"); try { br.readLine(); } catch (IOException e) { System.err.println("busted input"); } } }