/*
* Copyright 2008 FatWire Corporation. All Rights Reserved.
*
* 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 com.fatwire.gst.foundation;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import COM.FutureTense.Interfaces.ICS;
import com.fatwire.assetapi.common.AssetAccessException;
import com.fatwire.assetapi.data.AssetData;
import com.fatwire.assetapi.data.AssetId;
import com.fatwire.assetapi.data.AttributeData;
import com.fatwire.assetapi.data.BlobObject;
import com.fatwire.assetapi.data.BlobObject.BlobAddress;
import com.fatwire.assetapi.def.AssetAssociationDef;
import com.fatwire.assetapi.def.AttributeDef;
import com.fatwire.assetapi.def.AttributeDefProperties;
import com.fatwire.assetapi.def.AttributeTypeEnum;
import com.fatwire.mda.Dimension;
/**
* Various helper methods for debugging.
*
* @author Dolf Dijkstra
* @deprecated - moved to new namespace
* @see "tools.gsf.runtime.DebugHelper"
*/
public final class DebugHelper {
protected static final Logger LOG = LoggerFactory.getLogger("tools.gsf.legacy.DebugHelper.debug");
private static final Logger LOG_TIME = LoggerFactory.getLogger("tools.gsf.legacy.DebugHelper.debug.time");
private DebugHelper() {
}
public static void dumpVars(final ICS ics) {
dumpVars(ics, LOG);
}
@SuppressWarnings("unchecked")
public static void dumpVars(final ICS ics, final Logger log) {
if (log.isDebugEnabled()) {
for (final Enumeration<String> e = ics.GetVars(); e.hasMoreElements();) {
final String n = e.nextElement();
log.debug("ICS variable: " + n + "=" + ics.GetVar(n));
}
}
}
@SuppressWarnings("unchecked")
public static void dumpVars(final ICS ics, final PrintWriter pw) {
for (final Enumeration<String> e = ics.GetVars(); e.hasMoreElements();) {
final String n = e.nextElement();
pw.println("ICS variable: " + n + "=" + ics.GetVar(n));
}
}
@SuppressWarnings("unchecked")
public static void dumpSSVars(final ICS ics, final PrintWriter pw) {
for (final Enumeration<String> e = ics.GetSSVars(); e.hasMoreElements();) {
final String n = e.nextElement();
pw.println("session variable: " + n + "=" + ics.GetSSVar(n));
}
}
/**
* Retrieves the root exception of a <code>Throwable</code>.
*
*
* @param e the exception with nested exceptions (causes)
* @return the root cause
*/
public static Throwable findRootCause(final Throwable e) {
Throwable p = e;
while (p.getCause() != null) {
p = p.getCause();
// alternative would be to set the root on e => e.initCause(p);
}
return p;
}
/**
*
* Converts an elapsed time in micro seconds to a human readable string with
* seconds and milliseconds precision on larger elapsed times.
*
* @param elapsed the elapsed time in micro seconds (us)
* @return A human readable string for the elapsed micro seconds
*/
public static String microToHuman(final long elapsed) {
String human = "(" + elapsed + "us) ";
if (elapsed > 1000000) {
final long e = elapsed / 1000;
human += Long.toString(e / 1000) + "." + String.format("%03d", (e % 1000)) + "s";
} else if (elapsed > 1000) {
human += Long.toString(elapsed / 1000) + "." + String.format("%03d", (elapsed % 1000)) + "ms";
} else {
human += Long.toString(elapsed) + "us";
}
return human;
}
/**
*
* Converts an elapsed time in nano seconds to a human readable string with
* microseconds, seconds and milliseconds precision on larger elapsed times.
* Precision is dropped to microseconds precision.
*
* @param elapsed the elapsed time in nano seconds (us)
* @return A human readable string for the elapsed micro seconds
*/
public static String milliToHuman(final long elapsed) {
String human = "(" + elapsed + "ms) ";
if (elapsed > 1000 * 60L) {
// final long e = elapsed / 60000;
final long mins = elapsed / 60000L;
final long secs = (elapsed - mins * 60000) / 1000L;
human += Long.toString(mins) + "m " + Long.toString(secs) + "s";
} else if (elapsed > 1000L) {
human += Long.toString(elapsed / 1000) + "." + String.format("%03d", (elapsed % 1000)) + "ms";
} else {
human += Long.toString(elapsed) + "ms";
}
return human;
}
/**
*
* Converts an elapsed time in milli seconds to a human readable string with
* minutes and seconds precision on larger elapsed times.
*
* @param elapsed the elapsed time in nano seconds (us)
* @return A human readable string for the elapsed micro seconds
*/
public static String nanoToHuman(final long elapsed) {
return microToHuman(elapsed / 1000L);
}
/**
* Print the elapsed time between the <tt>start</tt> and <tt>end</tt> to the
* provided logger in a human readable form.
*
* @param log The logger where the message will be printed to.
* @param msg The message as an indicator of the operation that was
* monitored.
* @param start time in nanoseconds {@link System#nanoTime()}
* @param end time in nanoseconds {@link System#nanoTime()}
* @see DebugHelper#microToHuman(long)
*/
public static void printTime(final Logger log, final String msg, final long start, final long end) {
if (start > 0) {
final long elapsed = (end - start) / 1000;
log.debug(msg + " took " + microToHuman(elapsed));
}
}
/**
*
* Print the elapsed time since the <tt>start</tt> to the provided Log.
*
* @param log The logger where the message will be printed to.
* @param msg The message as an indicator of the operation that was
* monitored.
* @param start time in nanoseconds {@link System#nanoTime()}
* @see DebugHelper#microToHuman(long)
*/
public static void printTime(final Logger log, final String msg, final long start) {
if (start > 0) {
printTime(log, msg, start, System.nanoTime());
}
}
/**
* Print the elapsed time since the <tt>start</tt> to the default time
* logger {@link DebugHelper#LOG_TIME}.
*
*
* @param msg The message as an indicator of the operation that was
* monitored.
* @param start time in nanoseconds {@link System#nanoTime()}
* @see DebugHelper#microToHuman(long)
*
*/
public static void printTime(final String msg, final long start) {
if (start > 0) {
printTime(LOG_TIME, msg, start);
}
}
/**
* Print the AssetData to a string for debugging purposes.
*
* @param ad the asset date
* @return String with asset attributes etc
* @throws AssetAccessException asset access exception
*/
@SuppressWarnings("unchecked")
public static String printAsset(final AssetData ad) throws AssetAccessException {
if (ad == null) {
return null;
}
final StringWriter sw = new StringWriter();
final PrintWriter out = new PrintWriter(sw);
out.println(ad.getAssetId() + " '" + ad.getAssetTypeDef().getName() + "' '" + ad.getAssetTypeDef().getSubtype()
+ "'");
out.println("defs --- name (type [meta/valuecount/inherited/derived])");
for (final AttributeDef def : ad.getAssetTypeDef().getAttributeDefs()) {
final AttributeDefProperties props = def.getProperties();
out.println("\t" + def.getName() + " (" + def.getType() + " [" + def.isMetaDataAttribute() + "/"
+ props.getValueCount().name() + "/" + props.isInheritedFlexAttribute() + "/"
+ props.isDerivedFlexAttribute() + "])");
}
final List<AttributeDef> parentDefs = ad.getAssetTypeDef().getParentDefs();
if (parentDefs != null) {
out.println("parent defs --- name (type [meta/valuecount/inherited/derived])");
for (final AttributeDef def : parentDefs) {
final AttributeDefProperties props = def.getProperties();
out.println("\t" + def.getName() + " (" + def.getType() + " [" + def.isMetaDataAttribute() + "/"
+ props.getValueCount().name() + "/" + props.isInheritedFlexAttribute() + "/"
+ props.isDerivedFlexAttribute() + "])");
}
}
out.println("attribute names --- ");
out.println("\t" + ad.getAttributeNames());
out.println("attributes --- name (type [meta/valuecount/inherited/derived])");
for (final AttributeData attr : ad.getAttributeData()) {
final AttributeDefProperties props = attr.getAttributeDef().getProperties();
// props.getDataMap()
out.print("\t" + attr.getAttributeName() + " (" + attr.getType() + " ["
+ attr.getAttributeDef().isMetaDataAttribute() + "/" + props.getValueCount().name() + "/"
+ props.isInheritedFlexAttribute() + "/" + props.isDerivedFlexAttribute() + "]): ");
if (attr.getType() == AttributeTypeEnum.URL || attr.getType() == AttributeTypeEnum.BLOB) {
final BlobObject blob = (BlobObject) attr.getData();
if (blob != null) {
final BlobAddress addr = blob.getBlobAddress();
out.print(addr.getIdentifier());
out.print(" " + addr.getIdentifierColumnName());
out.print(" " + addr.getColumnName());
out.println(" " + addr.getTableName());
} else {
out.println("NULL BLOB");
}
} else {
final Object data = attr.getData();
if (data != null) {
out.print(" (" + data.getClass().getName() + ") ");
out.println(data);
} else {
out.println("NULL");
}
}
}
out.println("parents --- ");
for (final AssetId parent : ad.getParents()) {
out.println("\t" + parent);
}
out.println("associations --- ");
for (final AssetAssociationDef adef : ad.getAssetTypeDef().getAssociations()) {
for (final AssetId association : ad.getAssociatedAssets(adef.getName())) {
out.println("\t" + adef.getName() + ":" + association);
}
}
out.println("dimension --- group/name/id");
try {
final AttributeData locale = ad.getAttributeData("Dimension");
if (locale != null) {
for (final Object o1 : locale.getDataAsList()) {
if (o1 instanceof Collection) { // o1 is probably a Set
for (final Object o2 : (Collection<?>) o1) {
if (o2 instanceof Dimension) {
final Dimension dim2 = (Dimension) o2;
out.print("\t" + dim2.getGroup());
out.print("/" + dim2.getName());
out.println("/" + dim2.getId());
} else {
out.println("\t" + String.valueOf(o2));
}
}
}
}
}
} catch (final NullPointerException e) {
out.println("\tgetting the dimension attribute threw a " + e.getMessage());
}
final AttributeData mapping = ad.getAttributeData("Mapping");
if (mapping != null) {
int i = 0;
final List<AttributeData> mappingArray = mapping.getDataAsList();
for (final AttributeData s : mappingArray) {
@SuppressWarnings("rawtypes")
final List<Map<String, AttributeData>> structList = (List) s.getData();
for (final Map<String, AttributeData> m : structList) {
final String key = (String) m.get("key").getData();
final String type = (String) m.get("type").getData();
final String value = (String) m.get("value").getData();
final String siteid = (String) m.get("siteid").getData();
out.println("Mapping Entry #" + String.valueOf(i + 1));
out.println("Key: " + key);
out.println("Type: " + type);
out.println("Value: " + value);
out.println("Siteid: " + siteid);
}
i++;
}
}
out.flush();
return sw.toString();
}
/**
* Returns the assetid in as a human readable string in the format of
* type:id.
*
* @param assetId the asset id.
* @return a String concatenated with type and id.
*/
public static String toString(final AssetId assetId) {
return assetId.getType() + ":" + assetId.getId();
}
/**
* Creates a String from the Throwable.
*
* @param t the throwable to print.
* @return a string with the message and the stacktrace.
*/
public static String toString(final Throwable t) {
if (t == null) {
return "null";
}
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.close();
return sw.toString();
}
/**
* Prints the StackTrace of the Throwable to the Writer.
*
* @param writer writer to write to.
* @param t the Throwable to print the stacktrace of.
*/
public static void printStackTrace(final Writer writer, final Throwable t) {
if (writer instanceof PrintWriter) {
t.printStackTrace((PrintWriter) writer);
} else if (writer != null) {
t.printStackTrace(new PrintWriter(writer));
} else {
throw new IllegalArgumentException("Writer cannot be null.");
}
}
/**
* Dumps to current ICS state (Content Server variables, session
* variables,ICS objects,elementname,page url and stacktrace) as a String.
*
* @param ics Content Server context object
* @return the state of ICS.
*/
public static String printState(final ICS ics) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
pw.println("page url: " + ics.pageURL());
pw.println("elementname: " + ics.ResolveVariables("CS.elementname"));
pw.println();
dumpVars(ics, pw);
pw.println();
dumpSSVars(ics, pw);
pw.println();
dumpObjects(ics, pw);
pw.println();
dumpAttributes(ics, pw);
pw.println();
dumpHttpHeaders(ics, pw);
pw.println();
dumpCgiVars(ics, pw);
pw.println();
for (final StackTraceElement e : Thread.currentThread().getStackTrace()) {
pw.println(" at " + e.toString());
}
return sw.toString();
}
@SuppressWarnings("unchecked")
private static void dumpAttributes(final ICS ics, final PrintWriter pw) {
for (final Enumeration<String> e = ics.getAttributeNames(); e.hasMoreElements();) {
final String n = e.nextElement();
pw.println("request attribute: " + n + "=" + ics.getAttribute(n));
}
}
@SuppressWarnings({"deprecation" })
private static void dumpHttpHeaders(final ICS ics, final PrintWriter pw) {
try {
for (Enumeration<String> e = ics.getIServlet().getServletRequest().getHeaderNames(); e.hasMoreElements();) {
String n = e.nextElement();
pw.println("http header: " + n + "=" + ics.ResolveVariables("CS.Header." + n));
}
} catch (Exception e) {
LOG.warn(e.getMessage());
}
}
private static void dumpCgiVars(final ICS ics, final PrintWriter pw) {
String[] headers = { "CS.Browser", "CS.HTTPS", "CS.PATH_INFO", "CS.QUERY_STRING", "CS.REMOTE_ADDR",
"CS.REMOTE_HOST", "CS.REQUEST_METHOD", "CS.SERVER_NAME", "CS.SERVER_PORT", "CS.SERVER_PROTOCOL" };
for (String n : headers) {
pw.println("cgi var: " + n + "=" + ics.ResolveVariables(n));
}
}
@SuppressWarnings("unused")
private String printClassOrder(Class<?> c) {
StringBuilder b = new StringBuilder();
b.append("class " + c.getName());
if (c.isInterface()) {
b.append(" is an interface");
}
Class<?>[] interfaces = c.getInterfaces();
if (interfaces.length > 0) {
for (Class<?> i : interfaces) {
b.append(" ");
b.append(i.getName());
b.append(",");
}
}
Class<?> s = c.getSuperclass();
while (s != null) {
b.append(" extends " + s.getName());
s = c.getSuperclass();
}
return b.toString();
}
@SuppressWarnings("unchecked")
private static void dumpObjects(final ICS ics, final PrintWriter pw) {
for (final Method m : ics.getClass().getMethods()) {
final Class<?> c = m.getReturnType();
if (m.getParameterTypes().length == 0 && Collection.class.isAssignableFrom(c)) {
Object o;
try {
o = m.invoke(ics, new Object[0]);
if (o instanceof Collection) {
for (final String x : (Collection<String>) o) {
Object obj = ics.GetObj(x);
pw.println("object name: '" + x + "' is a "
+ (obj == null ? "null" : obj.getClass().getName()));
}
}
} catch (final IllegalArgumentException e1) {
LOG.warn(e1.getMessage());
} catch (final IllegalAccessException e1) {
LOG.warn(e1.getMessage());
} catch (final InvocationTargetException e1) {
LOG.warn(e1.getMessage());
}
}
}
}
}