package edu.umd.rhsmith.diads.meater.util;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
/**
* Provides static constants and utility functions for use in other classes.
*
* @author dmonner
* @author rmachedo
*/
public class Util {
private Util() {
}
/**
* Conversion constant for bytes to megabytes
*/
public static final int MB = 1 << 20;
/**
* Gets the hostname of the machine running the code, foregoing the need for
* exception handling in-line when this information is needed.
*
* @return The hostname of the machine
*/
public static String getHost() {
String host = "unknown";
try {
host = InetAddress.getLocalHost().getHostName();
} catch (final UnknownHostException ex) {
ex.printStackTrace();
}
return host;
}
/**
* Get the amount of memory used by the current JVM as a fraction of the
* maximum amount of memory it is allowed to use (via the <code>-Xmx</code>
* parameter)
*
* @return Memory utilization as a <code>float</code> between
* <code>0.0</code> and <code>1.0</code>.
*/
public static float getMemoryUtilizationFraction() {
final Runtime rt = Runtime.getRuntime();
final float usedMemory = rt.totalMemory() - rt.freeMemory();
return usedMemory / rt.maxMemory();
}
/**
* Makes a list into a pretty string by putting each element on its own
* indented line and enclosing the whole thing in brackets.
*
* @param <E>
* The type of the list
* @param list
* The list to convert
* @return A string representing the list
*/
public static <E> String prettyPrintList(final List<E> list) {
final StringBuffer sb = new StringBuffer();
sb.append("[\n");
for (final E item : list) {
sb.append("\t");
sb.append(item.toString());
sb.append("\n");
}
sb.append("]");
return sb.toString();
}
/**
* Converts an object with a stack trace into a readable message which can
* be used for logging.
*
* @param t
* The object to convert
* @return A readable error message
*/
public static String traceMessage(final Throwable t) {
final StringBuffer sb = new StringBuffer();
sb.append(t.toString());
sb.append("\n");
for (final StackTraceElement elem : t.getStackTrace()) {
sb.append("\t");
sb.append(elem.toString());
sb.append("\n");
}
if (t.getCause() != null) {
sb.append("Caused by:\n");
sb.append(traceMessage(t.getCause()));
}
return sb.toString();
}
/**
* @param s
* @return the input string, with double-quotes removed on either end.
*/
public static String unquoteString(String s) {
while (s.startsWith("\"")) {
s = s.substring(1);
}
while (s.endsWith("\"")) {
s = s.substring(0, s.length() - 1);
}
return s;
}
public static String indentLines(String text, int levels, String pattern) {
String[] lines = text.replace("\r", "").split("\n");
StringBuilder indent = new StringBuilder();
for (int x = 0; x < levels; x++) {
indent.append(pattern);
}
int idx = 0;
StringBuilder total = new StringBuilder();
for (String line : lines) {
++idx;
total.append(indent);
total.append(line);
if (idx != lines.length) {
total.append('\n');
}
}
return total.toString();
}
/**
* Splits the string <code>s</code> at every delimiter <code>delim</code>,
* unless that delimiter
* is between two matched occurrences of the <code>quote</code> character.
*
* @param s
* @param delim
* @param quote
* @return
*/
public static String[] splitUnlessQuoted(final String s,
final String delim, final String quote) {
final List<String> tokens = new LinkedList<String>();
boolean quoted = false;
int start = 0;
for (int i = 0; i < s.length(); i++) {
if (s.startsWith(delim, i)) {
if (!quoted) {
if (start < i) {
tokens.add(s.substring(start, i));
start = i + delim.length();
} else {
start++;
}
}
} else if (s.startsWith(quote, i)) {
quoted = !quoted;
}
}
if (start < s.length()) {
tokens.add(s.substring(start, s.length()));
}
return tokens.toArray(new String[tokens.size()]);
}
public static String joinStrings(Iterable<?> list, String delimeter) {
StringBuilder b = new StringBuilder();
boolean first = true;
for (Object o : list) {
if (!first) {
b.append(delimeter);
}
b.append(o.toString());
first = false;
}
return b.toString();
}
/**
* The number of milliseconds before an HTTP connection is considered to
* have timed out.
*/
private static final int CONN_TIMEOUT_MS = 10 * 1000;
/**
* A utility method that takes any URL and follows all redirects recursively
* until the true target
* is reached. Useful for finding the true destination of URL-shortened
* links.
*
* @param urlStr
* A URL, possibly shortened.
* @return The true destination URL.
*/
public static String expandUrl(final String urlStr)
{
URLConnection conn = null;
try
{
// to expand the URL, just open a connection and follow it!
final URL inputURL = new URL(urlStr);
conn = inputURL.openConnection();
conn.setConnectTimeout(CONN_TIMEOUT_MS);
conn.setReadTimeout(CONN_TIMEOUT_MS);
// this is necessary to update the header fields and can lead to
// StringIndexOutOfBoundsException if bad page returned
conn.getHeaderFields();
return conn.getURL().toString();
}
catch(final SocketTimeoutException ex)
{
// log.info("Socket timeout when trying to access " + urlStr);
}
catch(final NullPointerException ex)
{
// log.info("Null URL");
}
catch(final StringIndexOutOfBoundsException ex)
{
/*
String badURL = urlStr;
try
{
badURL = conn.getURL().toString();
}
catch(final Exception ex2)
{
// log.severe(Util.traceMessage(ex2));
}
// log.info("Header issue with URL: " + badURL);
*/
}
catch(final IllegalArgumentException ex)
{
if(ex.getMessage().contains("host = null"))
{
// log.info("Null hostname in URL.");
}
else
{
// log.info("URL Error: " + ex.getMessage());
}
}
catch(final MalformedURLException ex)
{
// log.info("Invalid URL: " + urlStr);
}
catch(final IOException ex)
{
// log.info("Cannot connect to URL: " + urlStr);
}
return urlStr;
}
}