org.paxml.el.UtilFunctions.java Source code

Java tutorial

Introduction

Here is the source code for org.paxml.el.UtilFunctions.java

Source

/**
 * This file is part of PaxmlCore.
 *
 * PaxmlCore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PaxmlCore is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PaxmlCore.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.paxml.el;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.paxml.annotation.Util;
import org.paxml.core.Context;
import org.paxml.core.IEntity;
import org.paxml.core.InMemoryResource;
import org.paxml.core.PaxmlResource;
import org.paxml.core.PaxmlRuntimeException;
import org.paxml.launch.Paxml;
import org.paxml.security.Secret;
import org.paxml.tag.AbstractTag;
import org.paxml.util.ReflectUtils;

/**
 * The default util functions.
 * 
 * @author Xuetao Niu
 * 
 */
@Util("util")
public class UtilFunctions implements IUtilFunctionsFactory {

    private static final Log log = LogFactory.getLog(UtilFunctions.class);

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getUtilFunctions(Context context) {
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Class<?> getXpathUtilFunctions(Context context) {
        return XpathFunctions.class;
    }

    /**
     * Merge a list of objects into one list.
     * 
     * @param objs
     *            if an object is a Collection, all its' elements will be used,
     *            not the Collection itself.
     * @return the list , never null
     */
    public static List list(Object... objs) {
        if (objs.length == 1 && !(objs[0] instanceof Map)) {
            List r = new ArrayList();
            ReflectUtils.collect(objs[0], r, true);
            return r;
        }
        return new ArrayList(Arrays.asList(objs));

    }

    /**
     * Compose a map with keys and values.
     * 
     * @param keysAndValues
     *            each key and value pair should be given consecutively.
     * @return the map
     */
    public static Map map(Object... keysAndValues) {
        if (keysAndValues.length % 2 != 0) {
            throw new PaxmlRuntimeException("Keys and values should be pairs");
        }
        Map map = new LinkedHashMap();
        for (int i = 0; i < keysAndValues.length - 1; i += 2) {
            map.put(keysAndValues[i], keysAndValues[i + 1]);
        }
        return map;
    }

    /**
     * Get the apache commons collection utils.
     * 
     * @return the utils object
     */
    public static CollectionUtils getCollection() {
        return new CollectionUtils();
    }

    /**
     * Get the Math utils.
     * 
     * @return the utils object
     */
    public static Math getMath() {

        return ReflectUtils.createObject(Math.class);
    }

    /**
     * Select xpath objects. @see Context.xpathSelect(xpath, alwaysList)
     * 
     * @param xpath
     *            xpath
     * @param alwaysList
     *            always list
     * @return the object
     */
    public static Object xpathSelect(String xpath, boolean alwaysList) {
        return Context.getCurrentContext().xpathSelect(null, xpath, alwaysList);
    }

    /**
     * Select xpath objects. @see Context.xpathSelect(xpath)
     * 
     * @param xpath
     *            xpath
     * 
     * @return the object
     */
    public static Object xpathSelect(String xpath) {
        return Context.getCurrentContext().xpathSelect(null, xpath);
    }

    /**
     * Select xpath objects. @see Context.xpathSelect(from, xpath, alwaysList)
     * 
     * @param from
     *            from object
     * @param xpath
     *            xpath
     * @param alwaysList
     *            always list
     * @return the object
     */
    public static Object xpathSelectFrom(Object from, String xpath, boolean alwaysList) {
        return Context.getCurrentContext().xpathSelect(from, xpath, alwaysList);
    }

    /**
     * Select xpath objects. @see Context.xpathSelect(from, xpath)
     * 
     * @param from
     *            from object
     * @param xpath
     *            xpath
     * 
     * @return the object
     */
    public static Object xpathSelectFrom(Object from, String xpath) {
        return Context.getCurrentContext().xpathSelect(from, xpath);
    }

    /**
     * Check if an id exists in current context.
     * 
     * @param id
     *            the id
     * @param searchParent
     *            true to search the parent context, false not to.
     * @return true if exists, false if not.
     */
    public static boolean hasConst(String id, boolean searchParent) {
        return Context.getCurrentContext().hasConstId(id, searchParent);
    }

    /**
     * Get a copy of const ids for the current thread context.
     * 
     * @return the copy
     */
    public static Set<String> getConstIds() {
        return new HashSet<String>(Context.getCurrentContext().getConstIds());
    }

    /**
     * Get a value with id from current context. NB, this will not cause
     * exception if the id doesn't exist!
     * 
     * @param id
     *            the id
     * @param searchParent
     *            true to search the parent context, false not to.
     * @return true the value or null if not found.
     */
    public static Object getConst(String id, boolean searchParent) {
        return Context.getCurrentContext().getConst(id, searchParent);
    }

    /**
     * Set a const in context.
     * 
     * @param id
     *            the const id
     * @param value
     *            the const
     * @param top
     *            true to set on root context, false to set on its own context
     * @return the existing const if any.
     */
    public static Object setConst(String id, Object value, boolean top) {
        Context context = Context.getCurrentContext();
        context = top ? context.getRootContext() : context.getCurrentEntityContext();

        return context.setConst(id, value == null ? null : value.getClass().getName(), value, true);
    }

    /**
     * Set const in caller's context.
     * 
     * @param id
     *            the const id
     * @param value
     *            the const value
     * @return the existing const in caller's const, null if no existing const.
     */
    public static Object setConstForCaller(String id, Object value) {
        Context context = Context.getCurrentContext();
        context = context.findCallerContext();
        if (context == null) {
            throw new PaxmlRuntimeException("The current file has no caller!");
        }
        return context.setConst(id, value == null ? null : value.getClass().getName(), value, true);
    }

    /**
     * Select values by class name.
     * 
     * @param className
     *            the class name
     * @param inheritance
     *            true to also include objects whose parent class matches the
     *            given name, false to do exact name match.
     * @param excludesParentContext
     *            true not to search in parent contexts, false to search in
     *            parent contexts.
     * @param mergeWithParentContext
     *            this parameter only has effect when searching from parent
     *            contexts. true to merge the values from parent context, false
     *            to overrule values from parent upon identical id.
     * @return a list of values, never null
     * @throws Exception
     *             any Exception
     */
    public static List<Object> classSelect(String className, boolean inheritance, boolean excludesParentContext,
            boolean mergeWithParentContext) throws Exception {
        Context context = Context.getCurrentContext();

        List<Object> list = new ArrayList<Object>(0);
        Map<String, Object> map = excludesParentContext ? context.getIdConstsMap()
                : context.getIdMap(mergeWithParentContext, true);
        if (inheritance) {
            Class clazz = Class.forName(className);
            for (Object value : map.values()) {
                if (clazz.isInstance(value)) {
                    list.add(value);
                }
            }
        } else {
            for (Object value : map.values()) {
                if (value != null && value.getClass().getName().equals(className)) {
                    list.add(value);
                }
            }
        }
        return list;
    }

    /**
     * Create a random number between two double bounds.
     * 
     * @param low
     *            the low bound
     * @param high
     *            the high bound
     * @return the random number
     */
    public static double random(double low, double high) {
        if (low == high) {
            return low;
        } else if (low > high) {
            double tmp = low;
            low = high;
            high = tmp;
        }
        double range = high - low;
        return low + Math.random() * range;
    }

    /**
     * Create a random number between two long bounds.
     * 
     * @param low
     *            the low bound
     * @param high
     *            the high bound
     * @return the random number
     */
    public static long random(long low, long high) {
        return Math.round(random(low + 0.0, high));
    }

    /**
     * Get the current system time.
     * 
     * @return the system time in ms.
     */
    public static long getSystemTime() {
        return System.currentTimeMillis();
    }

    /**
     * Call a static method. If not found, exception will be thrown.
     * 
     * @param className
     *            the class name
     * @param method
     *            the method name
     * @param args
     *            the args name
     * @return the method return value.
     * 
     */
    public static Object callStaticMethod(String className, String method, Object[] args) {
        return ReflectUtils.callStaticMethod(className, method, args);
    }

    /**
     * Call a static method. If not found, exception will be thrown.
     * 
     * @param className
     *            the class name
     * @param method
     *            the method name
     * 
     * @return the method return value.
     * 
     */
    public static Object callStaticMethod(String className, String method) {
        return ReflectUtils.callStaticMethod(className, method, null);
    }

    /**
     * Call a method on an object.
     * 
     * @param obj
     *            the method owner
     * @param method
     *            the method name
     * 
     * @return the return value of the method call
     */
    public static Object callMethod(Object obj, String method) {
        return ReflectUtils.callMethod(obj, method, null);
    }

    /**
     * Call a method on an object.
     * 
     * @param obj
     *            the method owner
     * @param method
     *            the method name
     * @param args
     *            the args
     * @return the return value of the method call
     */
    public static Object callMethod(Object obj, String method, Object[] args) {
        return ReflectUtils.callMethod(obj, method, args);
    }

    /**
     * Check if an object's string value equals to any item's string value in a
     * collection.
     * 
     * @param value
     *            the object
     * @param collection
     *            the collection
     * @return true if yes, false no
     */
    public static boolean in(Object value, Collection collection) {
        if (value == null) {
            return false;
        }
        value = value.toString();

        for (Object item : collection) {
            if (String.valueOf(item).equals(value)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Break a string to parts.
     * 
     * @param str
     *            the string
     * @param delimiters
     *            delimiters applicable for StringTokenizer. If null given,
     *            ", \r\n\f\t" will be used.
     * @return the order set containing the parts
     */
    public static Set<String> breakString(String str, String delimiters) {
        return AbstractTag.parseDelimitedString(str, delimiters);
    }

    /**
     * Load a class from class name.
     * 
     * @param clazz
     *            the class name
     * @return the loaded class, never null
     */
    public static Class loadClass(String clazz) {
        return ReflectUtils.loadClassStrict(clazz, null);
    }

    /**
     * Quote a pattern literal.
     * 
     * @param literal
     *            the literal
     * @return the quoted literal to be used in pattern
     */
    public static String quotePattern(String literal) {
        return Pattern.quote(literal);
    }

    /**
     * Get today.
     * 
     * @return today
     */
    public static Date today() {
        return DateUtils.truncate(new Date(), Calendar.DATE);
    }

    /**
     * Count how many elements is in the given
     * list/map/iterator/enumeration/array.
     * 
     * @param obj
     *            list/map/iterator/enumeration/array
     * @return number of elements
     */
    public static int count(Object obj) {

        if (obj == null) {
            return 0;
        } else if (obj instanceof Collection || obj instanceof Map || obj instanceof Iterator
                || obj instanceof Enumeration || obj.getClass().isArray()) {
            return CollectionUtils.size(obj);
        } else if (obj instanceof Iterable) {
            return count(((Iterable) obj).iterator());
        } else {
            return 1;
        }

    }

    /**
     * Call a tag.
     * 
     * @param name
     *            the tag name
     * @param args
     *            the arguments map
     * @return the result
     */
    public static Object call(String name, Map<String, Object> args) {
        final Context context = Context.getCurrentContext();
        final IEntity tag = context.getPaxml().getEntity(name);
        if (tag == null) {
            throw new PaxmlRuntimeException("No tag defined as: " + name);
        }

        final Context subContext = new Context(context);
        subContext.setAsCurrentThreadContext();
        try {
            if (args != null) {
                for (Map.Entry<String, Object> entry : args.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    subContext.addConst(key, key, value, false);
                }
            }
            return tag.execute(subContext);
        } finally {
            context.setAsCurrentThreadContext();
        }

    }

    /**
     * Make a string from ascii code.
     * 
     * @param ascii
     *            ascii codes
     * @return the string
     */
    public static String makeString(byte... ascii) {
        StringBuilder sb = new StringBuilder();
        for (byte a : ascii) {
            sb.append((char) a);
        }
        return sb.toString();
    }

    /**
     * Get the caller's paxml resource.
     * 
     * @return the resource
     */
    public static PaxmlResource getCallerResource() {
        return Context.getCurrentContext().findCallerEntity().getResource();
    }

    /**
     * Get the current paxml resource.
     * 
     * @return the resource
     */
    public static PaxmlResource getCurrentyResource() {
        return Context.getCurrentContext().getCurrentEntity().getResource();
    }

    /*
     * public static ITag getCurrentTag() { return
     * Context.getCurrentContext().getCurrentTag(); }
     * 
     * public static IpaxmlEntity getCurrentEntity() { return
     * Context.getCurrentContext().getCurrentEntity(); }
     * 
     * public static void addpaxmlResource(String[] pathWithPrefixs) { for
     * (String p : pathWithPrefixs) {
     * Context.getCurrentContext().getpaxml().addResources
     * (paxmlResource.createFromPath(p)); } }
     * 
     * public static void addpaxmlTagLibrary(String[] classNames) { for (String
     * cn : classNames) { Class<? extends ITagLibrary> clazz = (Class<? extends
     * ITagLibrary>) ReflectUtils.loadClassStrict(cn, null);
     * Context.getCurrentContext().getpaxml().addTagLibrary(clazz); } }
     * 
     * public static void addpaxmlListener(String[] classNames) throws Exception
     * { paxml paxml = Context.getCurrentContext().getpaxml(); for (String cn :
     * classNames) {
     * 
     * Class<?> clazz = ReflectUtils.loadClassStrict(cn, null); if
     * (ReflectUtils.isImplementingClass(clazz, IpaxmlExecutionListener.class,
     * true)) { paxml.addpaxmlExecutionListener(((Class<? extends
     * IpaxmlExecutionListener>) clazz).newInstance()); } else if
     * (ReflectUtils.isImplementingClass(clazz, IEntityExecutionListener.class,
     * true)) { paxml.addEntityExecutionListener(((Class<? extends
     * IEntityExecutionListener>) clazz).newInstance()); } else if
     * (ReflectUtils.isImplementingClass(clazz, ITagExecutionListener.class,
     * true)) { paxml.addTagExecutionListener(((Class<? extends
     * ITagExecutionListener>) clazz).newInstance()); } else { throw new
     * paxmlRuntimeException("Unknown listener type: " + clazz.getName()); } } }
     */
    /**
     * Run a random paxml xml string.
     * 
     * @param paxml
     *            the paxml xml string
     * @return the execution result
     */
    public static Object runPaxml(String paxml) {
        if (StringUtils.isBlank(paxml)) {
            return null;
        }
        paxml = "<scenario>" + paxml.trim() + "</scenario>";
        Context context = Context.getCurrentContext();
        Paxml _paxml = context.getPaxml();
        IEntity entity = _paxml.getParser().parse(new InMemoryResource(paxml), true, null);

        return _paxml.execute(entity, context, false, false);

    }

    /**
     * Check if a tag name is callable.
     * 
     * @param tagName
     *            the name of the tag
     * @return true callable, false not
     */
    public static boolean isCallable(String tagName) {
        return null != Context.getCurrentContext().getPaxml().getResourceLocator().getResource(tagName);
    }

    /**
     * Find const id by given value.
     * 
     * @param obj
     *            the given value
     * @param strict
     *            true to do pointer comparison, false to do object equality
     *            comparison
     * @param searchParent
     *            true to look also in parent contexts, false only look in the
     *            current context
     * @param excludes
     *            ids to ignore
     * @return the id or null if no found.
     */
    public static String findConstIdExcept(Object obj, boolean strict, boolean searchParent, String[] excludes) {
        return Context.getCurrentContext().getParent().findConstId(obj, strict, searchParent,
                excludes == null ? new String[] {} : excludes);
    }

    /**
     * Find const id by given value.
     * 
     * @param obj
     *            the given value
     * @param strict
     *            true to do pointer comparison, false to do object equality
     *            comparison
     * @param searchParent
     *            true to look also in parent contexts, false only look in the
     *            current context
     * 
     * @return the id or null if no found.
     */
    public static String findConstId(Object obj, boolean strict, boolean searchParent) {
        return findConstIdExcept(obj, strict, searchParent, null);
    }

    /**
     * Find const ids by given value collection.
     * 
     * @param col
     *            the value collection
     * @param strict
     *            true to do pointer comparison, false to do object equality
     *            comparison
     * @param searchParent
     *            searchParent true to look also in parent contexts, false only
     *            look in the current context
     * @return a list of ids corresponding to each element in the given
     *         collection. Not found values will return null id in the list.
     */
    public static List<String> findConstIds(Collection col, boolean strict, boolean searchParent) {
        List<String> ids = new ArrayList<String>();
        for (Object obj : col) {
            ids.add(findConstId(obj, strict, searchParent));
        }
        return ids;
    }

    /**
     * Check if an object is empty. An object is empty if it is either of the
     * following case: - null - empty string - empty collection - empty map -
     * empty array.
     * 
     * @param obj
     *            the object to examine
     * @return true empty, false not
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        } else if (obj instanceof String) {
            return ((String) obj).isEmpty();

        } else if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        } else if (obj instanceof Map) {
            return ((Map) obj).isEmpty();
        } else if (obj.getClass().isArray()) {
            return 0 == Array.getLength(obj);
        }

        return false;
    }

    /**
     * Check if a value is logically equivalent to true, where the check logic
     * is like javascript boolean syntax.
     * 
     * @param obj
     *            the value
     * @return
     */
    public static boolean yes(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof Number) {
            if (0 == new BigDecimal(((Number) obj).toString()).compareTo(new BigDecimal(0))) {
                return false;
            }
        } else if (obj instanceof Collection) {
            if (((Collection) obj).isEmpty()) {
                return false;
            }
        } else if (obj instanceof Map) {
            if (((Map) obj).isEmpty()) {
                return false;
            }
        } else if (obj.getClass().isArray()) {
            if (0 == Array.getLength(obj)) {
                return false;
            }
        }
        final String str = String.valueOf(obj);
        if ("".equals(str) || "false".equals(str) || "null".equals(str)) {
            return false;
        }

        return true;

    }

    /**
     * The opposite of yes.
     * 
     * @param obj
     * @return
     */
    public static boolean no(Object obj) {
        return !yes(obj);
    }

    /**
     * Get the current process id.
     * 
     * @return the pid
     */
    public static long getProcessId() {
        return Context.getCurrentContext().getProcessId();
    }

    /**
     * Get the 1st non-empty object.
     * 
     * @param any
     *            all candidates
     * @return the 1st non-empty object, or null if none found.
     */
    public static Object any(Object... any) {
        for (Object obj : any) {

            if (obj != null && StringUtils.isNotEmpty(obj.toString())) {
                return obj;
            }
        }
        return null;
    }

    /**
     * Formats a String by replacing the {[0-9]+} placeholder.
     * 
     * @param formattedString
     *            - String that needs to be formatted with pattern
     *            "string {0} and {1}".
     * @param stringReplaceables
     *            . an array formating parameters.
     * @return the formatted String.
     */
    public static String formatString(String formattedString, String[] stringReplaceables) {

        int i = 0;
        for (String replaceable : stringReplaceables) {
            String regexPattern = "\\{" + i + "\\}";
            formattedString = formattedString.replaceAll(regexPattern, replaceable);
            i++;
        }
        return formattedString;
    }

    /**
     * Print date/time into xml format.
     * 
     * @param cal
     *            the calendar or date that represents the datetime. If null
     *            given, it will take the current system time.
     * @param includeTime
     *            true to include time part, false exclude time part
     * @return the xml standard date/time string
     */
    public static String printXmlDateTime(Object cal, boolean includeTime) {
        Calendar c = null;
        if (cal == null) {
            c = new GregorianCalendar();
        } else if (cal instanceof Calendar) {
            c = (Calendar) cal;
        } else if (cal instanceof Date) {
            c = new GregorianCalendar();
            c.setTime((Date) cal);
        } else {
            throw new PaxmlRuntimeException(
                    "Unsupported date time of type " + cal.getClass().getName() + ": " + cal);
        }
        return includeTime ? DatatypeConverter.printDateTime(c) : DatatypeConverter.printDate(c);

    }

    /**
     * Parse the standard xml date time.
     * 
     * @param str
     *            the date/time string
     * @return the calendar obj
     */
    public static Calendar parseXmlDateTime(String str) {
        return DatatypeConverter.parseDateTime(str);

    }

    public static String transform(String template, Object obj) {
        return null;
    }

    public static Secret getSecret(String name) {
        return Context.getCurrentContext().getSecret(name);

    }

    public static void setSecret(String name, String value) {
        Context.getCurrentContext().setSecret(name, value);
    }

    public static String ask(String question, boolean mask) {
        class DummyFrame extends JFrame {
            DummyFrame(String title) {
                super(title);
                setUndecorated(true);
                setVisible(true);
                setLocationRelativeTo(null);
            }
        }
        JPasswordField pf = new JPasswordField();
        DummyFrame frame = new DummyFrame(question);
        int okCxl = JOptionPane.showConfirmDialog(frame, pf, question, JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.QUESTION_MESSAGE);
        frame.setVisible(false);
        if (okCxl == JOptionPane.OK_OPTION) {
            return new String(pf.getPassword());
        }
        return null;
    }

    public static List sort(Collection list) {
        return sort(list, true);
    }

    public static List sort(Collection list, boolean asc) {
        List li = new ArrayList(list);
        if (asc) {
            Collections.sort(li);
        } else {
            Collections.reverse(li);
        }
        return li;
    }

    public static Object compress(Collection col) {
        switch (col.size()) {
        case 0:
            return null;
        case 1:
            return col.iterator().next();
        }
        return col;
    }

    public static List collect(Object... objs) {
        List list = new ArrayList();
        for (Object obj : objs) {
            ReflectUtils.collect(obj, list, true);
        }
        return list;
    }

    public static Object compactCollect(Object... objs) {
        return compress(collect(objs));
    }

    public static boolean confirm(String... args) {
        String msg;
        if (args.length == 0) {

            msg = "Do you want to contibue?";
        } else {
            msg = args[0];
        }
        String[] yes;
        if (args.length > 1) {
            yes = new String[args.length - 1];
            System.arraycopy(args, 1, yes, 0, yes.length);
        } else {
            yes = new String[] { "y", "yes" };
            msg += " (y/n)";
        }
        System.out.println(msg);
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String line;
        try {
            line = reader.readLine();
        } catch (IOException e) {
            throw new PaxmlRuntimeException("Cannot read from console", e);
        }
        for (String y : yes) {
            if (y.trim().equalsIgnoreCase(line.trim())) {
                return true;
            }
        }
        return false;
    }

    public static void exit() {
        Context.getCurrentContext().getStack().exit();
    }

    /**
     * Get a random available port.
     * @return the port, or minus if no available port found
     */
    public static int getRandomPort() {
        ServerSocket s = null;

        try {
            s = new ServerSocket(0);
            return s.getLocalPort();
        } catch (IOException e) {
            log.warn("Cannot get random port", e);
            return -1;
        } finally {
            try {
                if (s != null) {
                    s.close();
                }
            } catch (Exception e) {
                log.warn("Cannot close server socket of port: " + s.getLocalPort(), e);
            }
        }

    }
}