niedziela, września 21, 2008

Acer Aspire 4530

Laptop ma 14-calowy ekran, waży 2,4kg i wyposażony jest w procesor AMD Athlon X2 QL-60 1,9GHz o TDP 35W oraz zintegrowane GPU GeForce 9100 (MCP77). Notebook jest ładny i ma nowoczesny wygląd. Obudowa jest jakościowo lepsza od tej dwie generacje wstecz. Klawiatura taka sama jak w poprzednich Acerach (trzeba się do niej przyzwyczaić, mankamentem jest to, że ją mocno słychać - cyka), touchpad też ten sam - Synaptics. Nowością są głośniki - są naprawdę porządne. Puszczając muzykę z iTunes 8 byłem mile zaskoczony - na pierwszy rzut ucha brzmiały tak samo jak głośniki desktopowe. Dźwięk jest przestrzenny, nie przytłumiony, słychać więcej tonów niż w "zwykłych" głośnikach laptopowych. Obudowa znana z modelu 4520 jest dość wysoka - klawiatura znajduje się na wysokości 3 cm od blatu biurka, w starszych laptopach było to 2,5 cm. W rezultacie chcąc na niej pisać należy dostosować sobie miejsce pracy zgodnie z zasadami BHP - przesiadając się z Acera Aspire 3860 należy podnieść w górę siedzisko fotela.



Ekran wydaje się mniejszy i smuklejszy niż w starszych modelach, ale to tylko wrażenie spowodowane zaokrągleniem rogów obudowy, przez co wygląda na węższą.



Z prawej strony mamy sprawdzone DVD TSST (Toshiba Samsung Storage Technology), wejście USB na myszkę i wejście zasilania.



Z tyłu jest tylko wylot powietrza z systemu chłodzenia. W trakcie pisania tego tekstu obudowa w tym miejscu jest ciepła, ale wydmuchiwane powietrze jest chłodne. Laptop grzeje się najwięcej z powodu używania grafiki od NVidii.



Z lewej strony mamy wyjście VGA, gniazdo RJ45 karty Broadcom NetXtreme Gigabit Ethernet, gniazdo RJ11, dwa gniazda USB i wejścia/wyjścia audio (te ostatnie w starszych Acerach były z przodu, może było to odrobinę wygodniejsze). Przeniesienie gniazd USB na boki trzeba ocenić na plus, już nie trzeba trafiać na czuja w tył obudowy, żeby podłączyć myszkę.



Laptop jest oznaczony logiem SignalUp, co przeważnie przekłada się na to, że wyposażony jest w kartę Atherosa. Tak jest z modelem 4530, w którym zamontowano Atherosa 5007EG - bardzo ładnie pokazuje wszystkie sieci w okolicy, deklasując inne karty WiFi. Laptop ma zainstalowaną Vistę Home Premium. Przed skasowaniem jej zdążyłem zrobić windowsowy benchmark wydajności: procesor 4.9, grafika do Aero 4.1, gry 4.7, dysk powyżej 5-tki (Hitachi 250GB - czuć, że jest szybki, ale trochę go słychać, bardziej niż Caviara 60GB). Na laptop trafił Windows 2008 Server, który chodzi płynnie, wcale nie czuć, żeby system był ociężały (czego po Viscie można się spodziewać).



Jeszcze o obudowie: fajnie, że wyłącznik przeniesiono na środek, teraz przy przenoszeniu laptopa nie istnieje ryzyko chwycenia go tak, że przy okazji zostanie wciśnięty power-off.



Mimo (zdawałoby się) mało mobilnego sprzętu Windows przy włączonym WiFi i ekranie ustawionym na 40% jasności działa 3 godziny. Bardzo dobry wynik.



Z Linuksem jest gorzej, nie działają stany uśpienia C2, C3 ani C1 ani C1e (performance monitor pod Windows pokazuje powyżej 90% w stanie C1, sądząc po 3h działania musi być to C1e). Teoretycznie mają prawo nie działać, bo w DSDT nie ma definicji bloku power w FADT (P_LVL1*, P_LVL2* - opóźnienia i adresy rejestrów, których czytanie powoduje sen), ani nie ma sekcji _CST. Przez to Linuks wytrzymuje na bateri 1,5 - 2h i mocno grzeje sprzęt. Najwidoczniej Windows NT 6.0 ma sterowniki Cool'n'Quite, które radzą sobie bez poprawnych definicji zarządzania energią w BIOSie.



Dla Solarisa procesor jest za nowy (AMD 11h) i nie wie, jak nim zarządzać, żeby oszczędzać prąd. Ale OpenSolaris 2008.11 rozpoznaje automatycznie grafikę i ma do niej dość świeże sterowniki od NVidii.




Największą wadą laptopa jest matryca - jest taka sama jak w obecnych Lenovo czy Dellach - LG Philips - czyli dość nijaka. Kolory są blade i zupełnie nie soczyste, chyba też za bardzo niebieskie. W porównaniu do ekranu Quanta Display z Acera Aspire 3680, ten jest naprawdę low-endowy. Jeśli laptopa używamy do przeglądania sieci i programowania nie będziemy mieli z tego powodu mocno negatywnych odczuć, ale jeśli obrabiamy grafikę w Photoshopie, to będziemy musieli sobie skalibrować profil ICC.

    Plusy
  • Wydajny i jednocześnie oszczędny procesor
  • CPU wspiera sprzętową wirtualizację
  • Normalna grafika, czyli NVidia
  • Ładny design
  • Poręczny i lekki
  • Dobre głośniki
  • Dobra karta WiFi
  • dobra cena

    Minusy
  • NVidia potrafi się grzać
  • Problem z oszczędzaniem energii pod Linuksem
  • Matryca ma blade kolory, wymaga kalibracji ICC.

poniedziałek, września 15, 2008

Po czym poznać źle napisane strony WWW

Wystarczy zmienić deklarację typu dokumentu HTML i zobaczyć czy strona się rozjedzie:

  • strict: <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">

  • quirk: <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">

  • standard: <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">

wtorek, września 02, 2008

Yet another Konqueror for Windows

Mamy może mało popularne, ale porządnie sportowane Safari 3.1 dla Windowsa, mamy Konquerora z KDE 4.1 (winkde.org), a od dzisiaj mamy kolejną przeglądarkę z silnikiem KHTML - Google Chrome. Firmy wykorzystujące w swojej działalności Internet, jeśli wcześniej szanowały wybór klientów używających MacOS-a lub KDE, teraz mogą z dumą obwieścić, że ich strona jest kompatybilna z Googlem. Przykładem iPKO.

Po co Google'owi własna przeglądarka będąca Safari? Mając własną przeglądarkę z zaawansowanym silnikiem JavaScript mogą tworzyć Web 3.0. Prawda jest taka, że w DHTML-u można zrobić sporo byleby miało to sensowną wydajność. I jeszcze jedno spostrzeżenie: ludzie z Google'a używają MacBook-ów, na których mają Safari, więc przeglądarka Google na WebKit-cie to coś naturalnego.

piątek, sierpnia 22, 2008

WebLogic 10.1 MP1

Dziesiątka nie jest tak niezawodna jak dziewiątka. Przy co drugiej instalacji AdminServera zdarzają się takie błędy:

####<Aug 22, 2008 12:50:36 PM CEST> <Info> <ServletContext-/bea_wls_internal> <wls.domain.com> <AdminServer> <[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1219402236024> <BEA-000000> <HTTPClntLogin: Login rejected with code: 'Failed', reason: java.net.ProtocolException: HTTP tunneling is disabled

at weblogic.rjvm.http.HTTPServerJVMConnection.acceptJVMConnection(HTTPServerJVMConnection.java:88)

at weblogic.rjvm.http.TunnelLoginServlet.service(TunnelLoginServlet.java:80)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)

at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:226)

at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:124)

at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:283)

at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)

at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3395)

at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)

at weblogic.security.service.SecurityManager.runAs(Unknown Source)

at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2140)

at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2046)

at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1366)

at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200)

at weblogic.work.ExecuteThread.run(ExecuteThread.java:172)

Workaround: Zaznaczamy w 'Server -> Protocol -> General': [*] enable tunnelling, a zakładce Channels dodajemy nowy kanał o nazwie AdminServer: protokół http, kanał ma być wyłączony, adres nasłuchu: podajemy zewnętrzny IP, port nasłuchu: -1, adres publiczny: ten sam IP, port publiczny: -1; dodatkowo zaznaczamy enable tunnelling i http tunnelling.
Po restarcie serwer powinien zachowywać się normalnie i sam nie składać.

środa, sierpnia 20, 2008

JCall - wołaj funkcje C z Javy

W środowiskach korporacyjnych króluje Java, w nich też używa się czasem wirtualizacji np. VMWare Servera. Fajnie by było, gdyby pewne operacje na maszynach wirtualnych zautomatyzować za pomocą jakiegoś własnego oprogramowania. EMC dostarcza API VIX w wydaniach dla C i Perla, ale nie ma Java bindings. Chciałem coś takiego zrobić samemu, ale z Javy nie można tak łatwo dostać się do C jak w .NET-cie. Są biblioteki np. J/Invoke, ale są płatne i zamknięte. No to napisałem swoją własną biblioteczkę - pomysł jest taki, że pobieramy adres funkcji z biblioteki so, wrzucamy go do eax-a, wrzucamy argumenty na stos i wołamy eax-a. Tak, tak, używamy assemblera :). Okazuje się, że jak się ma fajne gcc pod Windows i zrobi parę makrodefinicji, to ten sam kod napisany pod Linuksa, da się skompilować i uruchamiać pod Windows. Całość wrzuciłem na systest.googlecode.com.

piątek, lipca 25, 2008

Oszczędzanie energii

  • Przyciemniony ekran
  • Czarne tło pulpitu
  • Wyładowane sterowniki od USB, WiFI, LAN-u i dźwięku
  • Wyłączony NetworkManager, dhcdbd, arts, dbus
  • acpi_osi="Windows 2006" /*w laptopie mam BIOS do Visty*/
  • notsc clocksource=hpet
  • kernel 2.6.25 z NOHZ i WMI


Na koniec trzeba dodać, że przedmiotem eksperymentu był Acer Aspire 3680 z Celeronem M 420, w konsoli udało się zjechać nawet do 14,8W i 11 wybudzeń. Przy standardowej pracy z użyciem myszki USB i włączonym WiFi laptop pobiera 18W.

Intel 2D w X11

Sterownik xf86-video-intel na X serwerze 1.3 (i nowszym) domyślnie używa architektury akceleracji EXA (xf86-video-i810 używał XAA), co powoduje tragiczną wydajność 2D - widać to podczas przewijania strony WWW w przeglądarce, a zwłaszcza strony z Flashami (libflashplayer.so w wersji 9+ wiesza się czasem); eclipse chodzi wolno. Rozwiązania są 2:
  • Wrócić do XAA (Option "AccelMethod" "XAA")
  • albo dodać: Option "AccelMethod" "EXA", Option "MigrationHeuristic" "greedy", Option "ExaNoComposite" "false"

W celu przyśpieszenia glxgears można dodać zmienną środowiskową INTEL_BATCH=1.

środa, lipca 23, 2008

JConsole i WebLogic

JConsole z JDK 1.6 ma problemy przy odczycie danych, wypada używać wersji 1.5. Adres jest typu: 'service:jmx:iiop:///jndi/iiop://wlserver:7001/weblogic.management.mbeanservers.runtime'.

wtorek, lipca 22, 2008

VisualVM od Sun-a













Dostępny w JDK 1.6.07 albo oddzielnie.

piątek, lipca 18, 2008

Tylko 50% polskich internautów używa IE

Opublikowano najświeższe statystyki Gemius SA.

niedziela, lipca 13, 2008

Poprawki dla 2.6.25.10-rt7

Siadłem nad tym kernelem i doprowadziłem go do stanu używalności na moim laptopie:

libata: fix locking for kmap_atomic

pm_qos_params: change spinlock to rwlock

no i oczywiście żeby się kompilowało w kernel/sched.c trzeba dodać:

static inline u64 global_rt_runtime()
{
if (sysctl_sched_rt_period < 0)
return RUNTIME_INF;

return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
}
Tak przy okazji - mocny motyw:

piątek, lipca 11, 2008

Jak profilować WebLogic-a

Ściągamy YourKit Java Profiler, wgrywamy bibliotekę agenta na maszynę z WLS i w zakładce ServerStart podajemy '-agentpath:/home/weblogic/ykjprofiler/libyjpagent.so=port=9999'

poniedziałek, lipca 07, 2008

Oracle BEA - i wszystko jasne

http://blogs.oracle.com/otn/2008/07/blogging_the_oracle_fusion_mid.html
http://www.oracle.com/products/middleware/docs/oracle-middleware-strategy-briefing-072008.pdf

Oracle z marszu zamierza przestawić się z OC4J na WebLogic'a; eclipse-owe narzędzie BEA zostaną przerzucone do Oracle Eclipse Pack, a domyślnym IDE będzie JDeveloper. AquaLogic Service Bus będzie połączony z Oracle ESB i rozwijany jako Oracle Service Bus.

Tak na marginesie - te raporty Forrestera są naciągane...

piątek, lipca 04, 2008

Rzut okiem na Oracle SOA Suite 11

Funkcjonalność bardzo podobna do tej w NetBeans/OpenESB. Są aplikacje kompozytowe i procesy BPEL-owe (te ostatnie z trochę większą funkcjonalnością - można np. używać kodu Javy).


piątek, czerwca 27, 2008

Glassfish + Oracle... JDBC

czwartek, czerwca 26, 2008

SQL Module in details

It is quite OK to put user and pass in connection string. For SQL Module the connection string should be exactly the same as in Servers tab. Before generating WSDL you should call SQL probably with some given parameter (that is replace ? or :1 with some real values). When you see that query works do the right job.



For my example I have created nasty SQL function returning clob with XML inside.



As you can see the result from WebService doesn't look like real business function.
Let's try to fix it. First, create XSD schema for the output coming from DB.



Looking at the WebService WSDL we can see address for SQL-Engine handling our DB function.



To fix beauty (or the lack of) of our WebService BPEL Module will be needed.



From the left there is Partner Link from more business friendly WSDL (that we created on the side), some magic inside, and Partner Link for SQL-Engine WSDL.

First obvious action - pass input of left Partner Link to SQL-Engine and Invoke it.



That was easy, but what's up with mangled XML string? We need to get some real XML nodes from it. OK, create variable of type covered by schema generated from db output.



Do unmarshall on XML string (output of operation might require manual edition of BPEL's source: from and to parameters - if drag-and-drop doesn't work; probably NetBeans sees foreign namespace 'http://sys.one.pl/db1' of XSD schema and refuses to use it).



Now we have XML tree and can take some data from it and put into 'beatifull' WS result.



Let's drop in BPEL module into CompositeApp and make connections. Here it is:



CompositeApp with 2 WebServices: one beautifull and one ugly.

We can see business accepted output in test of 2nd WS.





To sum up:
  • SQL module for wrapping SQL command

  • EnterpriseApp for deploying JDBC connections

  • WebApp for nothing (EnterpriseApp cannot be empty and needs to have WebApp at least)

  • BPEL module for transforming ugly WS (SQL-Engine based) into beautifull WS

  • CompositeApp for hosting and linking modules

Oracle Connection for Glassfish

It can be easilly created from NetBeans. All you need to do is new EnterpriseApplication (with some content, for example with WebApp as the wizard suggests). Then is Server Resources you can add JDBC Connection Pool and JDBC Resource. Deploy ear and you will have Oracle Connection on your Glassfish.

NetBeans SOA with Oracle

NetBeans is the default IDE for OpenESB platform and uses SOA Pack common with Sun JCAPS. JCAPS comes with DataDirect OEM JDBC driver for Oracle and somehow NetBeans doesn't fully support Oracle JDBC driver - it can't generate WSDL file for SQL Module operations. I have fixed this limitation and you can download SQL Module supporting Oracle JDBC driver from NetBeans Bugzilla.


Here you can see bug report. While generating WSDL for database operation SQL Module tries to get some description of parameters used in prepared statement. However Oracle JDBC driver doesn't have this information until after the statement is executed. As a result in NetBeans messages.log you can see:

java.sql.SQLException: Handle does not exist: getMetaDataorg.netbeans.modules.sql.project.dbmodel.DBMetaData.getPrepStmtResultSetColumns

From NetBeans Bugzilla you can get patch. NetBeans SOA Pack sources are available at hg.netbeans.org (there is mercurial package for Unices and TortoiseHg for Windows). You can do patching yourself or download fixed jar file. But...

if you download new OpenESB build every two weeks the jar file will probably have wrong version number of module. Unpack jar and fix it inside MANIFEST file.

Here is some Oracle function created few posts ago.

Let's try to generate WSDL for it.

OK, it probably worked. Now create new CompositeApplication, drop inside SQL Module, call 'Clean and Build'...

... add SOAP port, deploy CompositeApp...

and run Test Cases...

(remeber to set port for SOAP endpoint)

You should have now WebService for you DB operation.

Proste serializowanie obiektu do XML-a

private static StringBuffer describeNodeMark(StringBuffer sb, Object o, String name, int level, boolean end) {
for (int i = 0; i < level-1; i++)
sb.append("\t");
sb.append(end ? "</" : "<").append( name ).append(">\r\n");
return sb;
}

private static StringBuffer describeNode(StringBuffer sb, Object o, String name, int level) throws Exception {
if (o==null) {
for (int i = 0; i < level; i++)
sb.append("\t");
sb.append("<").append( name ).append("/>\r\n");
return sb;
}
else if (o.getClass().getName().startsWith("[B")) {
sb.append("<byte[]>").append( new String( (byte[]) o) ).append("</byte[]>");
return sb;
}
else if (o.getClass().getName().startsWith("[C")) {
char[] cs = (char[])o;
for (int i=0; i<cs.length; i++) {
Character c = (Character)cs[i];
sb.append(c);
//toXmlString(sb, c, level);
}
return sb;
}
else {
for (int i = 0; i < level; i++)
sb.append("\t");
sb.append("<").append(name).append(">");
sb.append(o);
sb.append("</").append(name).append(">\r\n");
return sb;
}
}

@SuppressWarnings("unchecked")
public final static StringBuffer toXmlString(StringBuffer sb, Object o, int level) throws Exception {
if (sb==null)
sb = new StringBuffer();
level++;
if (o!=null) {
String nm = o.getClass().getName();
if (nm.contains("org.apache.axis") || nm.endsWith(";")) // skip axis TypeDef and list terminator
return sb;
}
File f = new File( o.getClass().getName().replaceAll("\\.", "/") );

if (o==null) {
return describeNode(sb, o, f.getName(), level);
}
if ((o.getClass().getName().startsWith("java.lang") || // basic Java types
o.getClass().getName().startsWith("java.math") ||
o.getClass().getName().startsWith("[B") ||
o.getClass().getName().startsWith("[C")) &&
( !o.getClass().getName().startsWith("java.lang.String")) &&
!o.getClass().getName().startsWith("java.lang.Character")
)
{
return describeNode(sb, o, f.getName(), level);
}

/////////////////////

describeNodeMark(sb, o, f.getName(), level, false);

for (Field fld : o.getClass().getDeclaredFields()) {
fld.setAccessible(true);
String name = fld.getName();
Object obj = fld.get(o);

if (!name.startsWith("__")) { // skip axis fields
if (obj==null) {
describeNode(sb, obj, name, level);
}
else {
String cname = obj.getClass().getName();

if (cname.startsWith("[L")) {
Object[] objs = (Object[]) obj;
for (Object oo : objs) {
if (oo!=null)
sb.append( toXmlString(null, oo, level) );
}
}

if (cname.startsWith("java.lang.Class"))
return sb;

if (cname.startsWith("java.lang") || cname.startsWith("java.math")) {
describeNode(sb, obj, name, level);
}
else {
if (cname.startsWith("java.util.LinkedList$Entry")) {
List list = (List)o;
for (int i = 0; i < list.size(); i++)
sb.append( toXmlString(null, list.get(i), level-1 ) );
}
else if (cname.startsWith("java.util.TreeMap$Entry")){
Map map = (TreeMap) o;
for (Object k : map.keySet()) {
sb.append( toXmlString(null, k, level-1 ) );
}
}
else {
sb.append( toXmlString(null, obj, level) );
}
}
}
}
}

for (int i = 0; i < level-1; i++)
sb.append("\t");
sb.append("</").append( f.getName() ).append(">\r\n");
return sb;
}

Yet Another Logging Utility


package com.company.util.debug;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
* Modul logowania
*
*/
public class Debug {

public final static int TRACE_DEPTH = 25;
public final static boolean LOG_INFO = true;
public final static boolean LOG_ERR = true;
public final static String THIS_PACKAGE = "com.company";

public final static int TRACE_DEPTH = 25;
public final static boolean LOG_INFO = true;
public final static boolean LOG_ERR = true;

@SuppressWarnings("unchecked")
public final static void println(String txt, Object thiz) {
if (LOG_INFO) {
Exception e = new Exception();
StringBuffer msg = new StringBuffer();
msg.append("[").append(new Date()).append("] [Caller: ");
if (thiz instanceof Class)
msg.append( ((Class)thiz).getName() ).append("@static=");
else
msg.append( thiz.getClass().getName() ).append("@");

msg.append( thiz.hashCode() ).append("]");
msg.append(" th").append(Thread.currentThread().getId());
String thName = Thread.currentThread().getName();
if (thName!=null)
msg.append("=").append(thName);
msg.append("\r\n\tat ").append(e.getStackTrace()[1]);
msg.append("\r\n\tINFO: ").append(txt).append("\r\n");
System.out.println(msg);
}
}

public final static StringBuffer describeException(StringBuffer msg, Throwable err) {
msg.append("\r\n\tERR: ").append(err.toString()).append("\r\n");
StackTraceElement[] st = err.getStackTrace();
int n = (st!=null) ? Math.min(st.length, TRACE_DEPTH) : 0;
String prev = "";
for (int i=0; i < sti =" st[i]+"> ").append(st[i]);
else
msg.append("\r\n\t").append(st[i]);
prev = sti;
}
if (n>0)
msg.append("\r\n");
return msg;
}

@SuppressWarnings("unchecked")
public final static void printlnErr(String txt, Throwable ex, Object thiz) {
if (LOG_ERR) {
Exception e = new Exception();
StringBuffer msg = new StringBuffer();
msg.append("[").append(new Date()).append("] [Caller: ");
if (thiz instanceof Class)
msg.append( ((Class)thiz).getName() ).append("@static=");
else
msg.append( thiz.getClass().getName() ).append("@");

msg.append( thiz.hashCode() ).append("]");
msg.append("\r\n\tat ").append(e.getStackTrace()[1]);
msg.append("\r\n\tERR: ").append(txt);
Throwable t = ex;
while (t!=null) {
describeException(msg, t);
t = t.getCause();
}
System.out.println(msg);
}
}

@SuppressWarnings("unchecked")
public final static String describeErr(String txt, Throwable ex, Object thiz) {
if (LOG_ERR) {
Exception e = new Exception();
StringBuffer msg = new StringBuffer();
msg.append("[").append(new Date()).append("] [Caller: ");
if (thiz instanceof Class)
msg.append( ((Class)thiz).getName() ).append("@static=");
else
msg.append( thiz.getClass().getName() ).append("@");

msg.append( thiz.hashCode() ).append("]");
msg.append("\r\n\tat ").append(e.getStackTrace()[1]);
msg.append("\r\n\tERR: ").append(txt);
Throwable t = ex;
while (t!=null) {
describeException(msg, t);
t = t.getCause();
}
return msg.toString();
}
return ex.getLocalizedMessage();
}
}