Picking up from after Labbook.May15.txt, it's now 2005.May.17 at 07:44
and I'm ready to start the actual code to convert list of tokens into
parsed s-expression using nested MyList structures ... taking a break
at 10:36 to handle a personal matter.
Resuming at 12:12 ... finished at 13:49, including an XML generator so
that after parsing something we can see that it really did parse it
(when we use the s-expression printer, the output looks just like the
input and we can't prove we didn't just normalize spaces between
tokens, but with XML output it's blatantly clear we really did parse
it as well as clear that we want to work with nice terse s-expressions
instead of horribly verbose XML). Cleaned up test/demo, now it's
14:10. Here's a test run, with the first s-expression canned and the
rest typed in by the usr:
The canned input string was:
"JunkString1" (("FirstName" "Robert")("LastName" "Maas") ("City" "Sunnyvale"))
"JunkString1"
"JunkString1"
"FirstName"
"Robert"
"LastName"
"Maas"
"City"
"Sunnyvale"
(("FirstName" "Robert") ("LastName" "Maas") ("City" "Sunnyvale"))
Enter one or more s-expressions(s): (("a")) () "foo" ("whatever" "now" ())
"a"
(("a"))
()
"foo"
"foo"
"whatever"
"now"
("whatever" "now" ())
Next to write the actual test rig for MyHttpApplet, but first a nap.
Now 15:04 and it occurs to me that I need to allow [] as well as () to
delimit lists on input, to make it easy to include s-expressions as
literal string constants in test-rig programs. So I'll do that now ...
wait a minute, at 15:32 I realized this is pointless, it's quotemarks,
not parens, that are a problem in strings, what was I thinking?? Well
some of that work is still correct, and some was wasted, not anything
to get really upset about waste of time, compared with the many many
days of lost work due to deploytool and J2EE not working. Anyway,
switching now to using brackets as stand-ins for quote marks, not as
stand-ins for parentheses!! Done at 16:10, here's new demo:
The canned input string was:
"JunkString1" (("FirstName" [Robert])([LastName] [Maas]) ([City] [Sunnyvale]))
(Note that for input only, you can write a string as either "sometext"
or [sometext], but on output strings alwasys show as "sometext".)
"JunkString1"
"JunkString1"
"FirstName"
"Robert"
"LastName"
"Maas"
"City"
"Sunnyvale"
(("FirstName" "Robert") ("LastName" "Maas") ("City" "Sunnyvale"))
Enter one or more s-expressions(s): ([apple] [pear] [banana])
"apple"
"pear"
"banana"
("apple" "pear" "banana")
Enter one or more s-expressions(s): (([fruit] [apple]) ("animal" "bear")) "a"
"fruit"
"apple"
"animal"
"bear"
(("fruit" "apple") ("animal" "bear"))
"a"
"a"
*** Had to rush to take shower then catch bus to class for midterm ***
Next day, May 18, at 12:39. Last night it occurred to me that my XML
for string literals isn't proper. Because the representation of the
string is explicitly delimited by quote marks, it should be a property
within a non-container tag, rather than between start and end tags of
a container tag. The problem is that I need to make up a totally
useless name for that tag, such as:
Can anybody think of a non-useless name to put there?
Alternately I could use a container tag, but omit the quote marks:
JunkString1
Would that be proper XML? I can't choose, and it's not important,
so I won't bother to fix it either way right now, at 12:44. Break.
Resuming work at 16:20, checking some info I found on the net earlier
... OK, I've found that
Runtime rt = Runtime.getRuntime();
rt.exec("anyShellCommandString");
runs fine except the output from executing it goes to /dev/null, and I
can't even use stdout redirection > outputfile in the command, that's
ignored. But I found a trick to get output to a file: Write a shell
command file with the stdout redirection in it, and then in the
rt.exec simply invoke your favorite shell (such as sh) with the shell
command file name as parameter. I also tried
System.getenv("HOME");
which is listed in the 1.3.1 API documentation as "depricated", but in fact
when I try to run that it throws an exception:
Exception in thread "main" java.lang.Error: getenv no longer supported, use properties and -D instead: HOME
at java.lang.System.getenv(System.java:677)
at T2.main(T2.java:6)
But I think I know a simple way for a java program to learn that info,
specifically anything that the 'env' system command spews out. Working
on testing my idea at 17:39 ... yes it works! Here's the code:
Runtime rt = Runtime.getRuntime();
rt.exec("sh envx.sh");
ResourceBundle rb = ResourceBundle.getBundle("env");
Enumeration en = rb.getKeys();
System.out.print("Keys are:");
while (en.hasMoreElements()) {
System.out.print(" " + Sexpr1.toSexpr(en.nextElement()));
}
System.out.println();
String home = rb.getString("HOME");
System.out.println("HOME = " + home);
and here is the output:
Keys are: "DISPLAY" "HOSTTYPE" "XFILESEARCHPATH" "APPHOME" "BASH_ENV" "RUNLEVEL" "PATH" "JREHOME" "LOGNAME" "SHLVL" "INIT_VERSION" "COLORTERM" "HISTSIZE" "HISTFILESIZE" "ANT_HOME" "XAUTHORITY" "INPUTRC" "SHELL" "PREVLEVEL" "HOSTNAME" "AUTOBOOT" "SESSION_MANAGER" "OSTYPE" "WINDOWID" "MAIL" "LANG" "LD_LIBRARY_PATH" "HOME" "USERNAME" "LINGUAS" "LC_ALL" "J2EE_HOME" "NLSPATH" "GDMSESSION" "USER" "JAVA_HOME" "TERM" "GDM_LANG" "CONSOLE" "BOOT_IMAGE" "_"
HOME = /home/rem
So now it's 18:04 and I'll take a nap, etc.
Now later that evening (May.18) at 21:21, going to see if I can do
what I planned back on May.12, namely getting environment info in both
JSP and handcoded servlet, and checking what calls are made from the
JSP/Servlet, to make sure I know what I need to emulate ... looking
for which files to inspect, but they're all gone until I start the
J2EE server, doing that now at 21:27, waiting for it to start
... 21:34 it's ready. First I'm trying all the installed applications
to find out which are working tonight:
- date (jsp) -- completely working, but see also:
- date/index2.jsp -- My modified code working.
- date/index3.jsp -- Cross-link to doGet method for hello1.java/class works
- date/getstuff.jsp -- My modified code working.
- hello1 -- Broken, just gives me a directory listing for / which shows
original.war and duke.waving.gif, showing / really means public_html/hello1/
The other deployed things that work are either more JSPs, or EJBs, not
any working hand-coded HttpServlets. So I'm going to give up comparing
JSP environment against direct hand-coded HttpServlet
environment. I'll look only at JSP environment and just assume that's
the same as it would be with hand-coded servlets. But I'll look at the
code in all the examples I can find in source-code (JSP or java) form,
to see what kinds of environment calls I might need to handle, such as
asking the request object to reveal the session object, or writing
data to the output stream within the response object, etc. So starting
to look at source code ...
bookstore1/
BookDetailsServlet.java
getServletContext().getAttribute("bookDB");
throw new UnavailableException("Couldn't get database.");
HttpSession session = request.getSession(true);
ResourceBundle messages = (ResourceBundle)session.getAttribute("messages");
response.setContentType("text/html");
response.setBufferSize(8192);
PrintWriter out = response.getWriter();
out.println("
" + ...
response.encodeURL(request.getContextPath() + ...
response.encodeURL(request.getContextPath() + "/catalog") +
catch (BookNotFoundException ex) {
response.resetBuffer();
throw new ServletException(ex);
(Those same kinds of method calls are repeated in nearly each *.java file.)
hello1/
GreetingServlet.java
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("/response");
if (dispatcher != null)
dispatcher.include(request, response);
So I'm glad I made that scan, because now I know there are actually
only a very few features of request/response/session objects that are
commonly used, so I won't need to implement much in my fake classes.
So now it's 22:23, and I need to install test code to get list of all
possible keywords for:
getServletContext().getAttribute("..."); // Called from init()
// also called from doGet(...)
session.getAttribute("messages"); // Called from doGet(...)
and I'll need to check what kind of string is generated by code like this:
response.encodeURL(request.getContextPath() + "/catalog")
So let's do these in sequence, working from the class we're in
(HttpServlet) and the classes of the two parameters we have at the
start of the Servlet (HttpServletRequest and HttpServletResponse):
In class javax.servlet.http.HttpServlet, method getServletContext() is
inherited from javax.servlet.GenericServlet, return value is of type
javax.servlet.ServletContext, I'll need to check that [#1] in the JSP
environment. In that class, getAttribute(String) [[Modem lost
connection as it usually does several times per day, need to reconnect
to get that info I need at 22:49, this random-modem-crapout has been
happening ever since the local phone circuits were switched to
digitally encoded ... done and back to where I was looking in API doc
at 22:53]], return value is declared as Object, string parameter is
supposed to follow fully-qualified rules, such as javax.*
etc. getAttributeNames() can be used to get the list of all such names
in use in this servlet container, via an Enumeration as the return
value there. So I need to write code like this (in a java scriptlet in
the JSP acting as a javax.servlet.http.HttpServlet):
javax.servlet.ServletContext sc = getServletContext();
(Verify class of actual object I got back)
Enumeration en = sc.getAttributeNames();
(usual while loop to println each name)
At 23:04, starting to put that code in the JSP I was playing with ...
23:13 have code in the JSP which is not recompiling ... 23:15 it's
ready, but got Servlet exception. Oh, when I copied a line of code
from elsewhere I forgot to change the name of the variable, fixed and
recompiling again ... 23:18 done and this time it worked:
Servlet context is
org.apache.catalina.core.ApplicationContextFacade@1c2192
Going to list each property in that context: locales
javax.servlet.context.tempdir org.apache.catalina.resources
org.apache.catalina.WELCOME_FILES org.apache.catalina.jsp_classpath
That's not very many, so I'll change the code to actually list the
value of each key, done at 23:28, waiting for JSP to recompile ...
oops, compiler error, fixed my mistake, recompiling at 23:30 ...
oops, another bad line of code:
String val = sc.getAttribute(key);
I'm so used to properties files which have string values, I forgot
that attributes can be *any* Java object, will fix that ... done,
23:32 recompiling ... 23:34 finally working:
Going to list each property in that context:
* [locales] = [MyLocales@127275]
* [javax.servlet.context.tempdir] =
[/usr/java/j2sdkee1.3/repository/adsl-63-192-44-196.roadguy.com/web/da
te]
* [org.apache.catalina.resources] =
[org.apache.naming.resources.ProxyDirContext@187298]
* [org.apache.catalina.WELCOME_FILES] = [[Ljava.lang.String;@b7298]
* [org.apache.catalina.jsp_classpath] =
[/usr/java/j2sdkee1.3/public_html/date/WEB-INF/classes/:/usr/java/j2sd
kee1.3/repository/adsl-63-192-44-196.roadguy.com/applications/DateApp1
115343413769Server.jar]
OK, that's enough of that for now. The jsp_classpath might be useful
to change in my test rig. Now on to the other thing I need to
investigate, with new test code, regarding session object and
getAttribute on that. My test code already has (from the other day)
this code:
out.println("** session object" + br + s2 + session + br);
HttpSession sess = request.getSession(false);
out.println("** sess = request.getSession(false)" + br+ar + sess+br);
String sessid = sess.getId();
String sessionid = session.getId();
out.println("session.getId(): " + sessionid + br);
out.println(s3+"sess.getId(): " + sessid + br);
out.println(s4 + s4 + s3 + s3 + s3 +
"(They " + (sessionid.equals(sessid) ? "" : "dis")
+ "agree.)" + br);
String rs = request.getRequestedSessionId();
out.println("* rs = request.getRequestedSessionId()" + br + s4 + s3 + s3
+ s2 + ar + rs + br);
out.println(s4 + s4 + s3 + s3 + s3 + "(That request was " +
(sessionid.equals(rs) ? "" : "not ")
+ "satisfied.)" + br);
which produces this output:
** session object
org.apache.catalina.session.StandardSessionFacade@5562b
** sess = request.getSession(false)
--> org.apache.catalina.session.StandardSessionFacade@5c30f6
session.getId(): B1D6A4C80382C5A743B0D4E69414B476
sess.getId(): B1D6A4C80382C5A743B0D4E69414B476
(They agree.)
* rs = request.getRequestedSessionId()
--> B1D6A4C80382C5A743B0D4E69414B476
(That request was satisfied.)
so now I need new test code calling session.getAttributeNames(),
except this time the enumeration is guaranteed to contain nothing
except strings. Copying the code from the other getAttributeNames call
(from the other class) and adapting it... done, JSP recompiling at
23:55 ... hmm, no output from that new code except the header, as if
the system object had no properties whatsoever. I'll have to debug my
test code by setting a couple properties and see if they show up in
the output ... lost modem connection again but all I need is the
method signature, so rather than going back online I used my
reflection utility, which showed this method:
12: public abstract void javax.servlet.http.HttpSession.setAttribute(java.lang.String,java.lang.Object)
I wonder why it accepts Object, when they are supposed to always be
Strings?? Oh well. Upcasting is safe so I don't care. Done, new code:
session.setAttribute("school", "De Anza");
session.setAttribute("city", "Cupertino");
and it works, output from enumeration loop now says:
* [school] = [De Anza]
* [city] = [Cupertino]
One last capability of the servlet environment to test,
out.println("* The encoded URL is: " +
response.encodeURL(request.getContextPath() + "/catalog"));
done, recompling JSP on Thursday May.19 at 00:16 ... done, output:
* The encoded URL is: /date/catalog
OK, I think I understand how these features work. Next to write a test
rig that provides a capability and a pseudo-HttpServlet which makes
calls such as found in the sample servlets earlier, but it's bedtime
right now, at 00:20, so I'll upload this log file then go to bed.