Monday, March 31, 2003

Codebit Update; A ReadMe file for the Simplest Bean.

In response to an email request, I've added a README.txt file to http://affy.blogspot.com/java/SimpleBean.zip to indicate how to use the build.xml file and what the output looks like. Here it is for those who don't want to grab the zip file for just one file:
How to Test the SimpleBean Class
--------------------------------
1. Edit build.xml file to customize the properties at the beginning of the file.

2. Create an environmental variable called JBOSS_HOME that points to the 
installation directory of JBOSS.

	set JBOSS_HOME=D:\java\support\jboss-3.0.6_tomcat-4.1.18   # example
	set JBOSS_CONFIG=test

3. Create a clone of the %JBOSS_HOME%/server/default directory so that we don't 
affect the standard installation.

	xcopy 
	  %JBOSS_HOME%\server\default 
	  %JBOSS_HOME%\server\%JBOSS_CONFIG% 
	  /E /I /F

4. Start JBOSS from the DOS command-line.

	%JBOSS_HOME%/bin/run.bat -c test
	
5. Deploy the bean to JBoss using the "deploy" task. Note that I changed the
log4j options of JBoss so that the SQL statements that it executes are 
displayed on the console as DEBUG messages.

	Output From Ant Task
	--------------------

	Buildfile: d:\java\workspace\SimpleBean\build.xml

	check-environment:

	check-ant:

	wrong-ant:

	check-java:

	wrong-java:

	check-jboss:

	wrong-jboss:
	
	check-jboss-configuration:

	wrong-jboss-configuration:

	check-ejb-jar:

	check-jakarta-logging-jar:

	check-jboss-version:
	
	check-log4j-jar:

	check-xdoclet:

	wrong-xdoclet:

	init:

	xdoclet-generate:
	   	[ejbdoclet] Running 
   		[ejbdoclet] Generating Remote interface for 'com.affy.entity.SimpleBean'.
		[ejbdoclet] Running 
		[ejbdoclet] Generating Home interface for 'com.affy.entity.SimpleBean'.
		[ejbdoclet] Running 
		[ejbdoclet] Generating Local interface for 'com.affy.entity.SimpleBean'.
		[ejbdoclet] Running 
		[ejbdoclet] Generating Local Home interface for 'com...SimpleBean'.
		[ejbdoclet] Running 
		[ejbdoclet] Generating Util class for 'com.affy.entity.SimpleBean'.
		[ejbdoclet] Running 
		[ejbdoclet] Generating EJB deployment descriptor (ejb-jar.xml).
		[ejbdoclet] Running 
		[ejbdoclet] Generating jboss.xml.
		[ejbdoclet] Generating jbosscmp-jdbc.xml.
        [echo] Done!

	compile:
        [echo] Compiling Generated Files.
       [javac] Compiling 5 source files to D:\...\classes
        [echo] Compiling EJB Files.
       [javac] Compiling 1 source file to D:\...\classes
        [echo] Compiling Client Files.
       [javac] Compiling 1 source file to D:\...\classes
        [echo] Making Jar File.
         [jar] Building jar: D:\...\build\deploy\SimpleBean.jar

	deploy:
        [echo] Copying Jar File to Hot Deploy Directory.
        [copy] Copying 1 file to D:\...\server\test\deploy

	BUILD SUCCESSFUL
	Total time: 14 seconds
	
	Output From JBoss Server
	------------------------
	00:31:24,940 INFO  [MainDeployer] Starting deployment of package: 
		file:/D:.../SimpleBean.jar
	00:31:25,541 INFO  [EjbModule] Creating
	00:31:25,561 INFO  [EjbModule] Deploying SimpleBean
	00:31:25,641 INFO  [EjbModule] Created
	00:31:25,641 INFO  [EjbModule] Starting
	00:31:25,691 DEBUG [SimpleBean] Initializing CMP plugin for SimpleBean
	00:31:25,701 DEBUG [SimpleBean] Loading standardjbosscmp-jdbc.xml : 
		file:/D:.../server/test/conf/standardjbosscmp-jdbc.xml
	00:31:25,881 DEBUG [SimpleBean] jar:file:/D:/.../META-INF/jbosscmp-jdbc.xml 
		found. Overriding defaults
	00:31:26,042 DEBUG [SimpleBean] Entity Exists SQL: 
		SELECT COUNT(*) FROM SIMPLEBEAN WHERE pKey=?
	00:31:26,052 DEBUG [SimpleBean] Insert Entity SQL: 
		INSERT INTO SIMPLEBEAN (pKey) VALUES (?)
	00:31:26,052 DEBUG [SimpleBean] Remove SQL: 
		DELETE FROM SIMPLEBEAN WHERE pKey=?
	00:31:26,242 INFO  [SimpleBean] Table 'SIMPLEBEAN' already exists
	00:31:26,252 DEBUG [findByPrimaryKey] SQL: 
		SELECT pKey FROM SIMPLEBEAN WHERE pKey=?
	00:31:26,252 DEBUG [SimpleBean] 
		Added findByPrimaryKey query command for home interface
	00:31:26,252 DEBUG [findByPrimaryKey] SQL: 
		SELECT pKey FROM SIMPLEBEAN WHERE pKey=?
	00:31:26,252 DEBUG [SimpleBean] 
		Added findByPrimaryKey query command for local home interface
	00:31:26,252 INFO  [EjbModule] Started
	00:31:26,252 INFO  [MainDeployer] Deployed package: file:/D:/...SimpleBean.jar
	
6. Run the SimpleBeanClient program. I run it using the 
Run->Run As->Java Application menu option of Eclipse. For some reason, I am
unable to run it from Ant because I get the following error:

     [java] java.lang.IllegalAccessException: Class 
     org.apache.tools.ant.taskdefs.ExecuteJava can not access a member of 
     class com.affy.client.SimpleBeanClient with modifiers "public static"

I don't want to take time to figure out what's wrong, so I'm content to run
the client from inside Eclipse. After all, the IDE should make my life easier, no?

Here is the output of the client program:

	ID: 446ced64c0a822650064160eae80b6fd
	ID: 446ced64c0a822650064160eae80b6fd
	Done.

The ID displayed by your execution of the program will, of course, be 
different.

7. That's it. Have Fun!

Friday, March 21, 2003

CodeBit: The Simplest Possible EJB for JBoss?

I've been trying to simplify the process of making an EJB. And I think I have the simplest possible bean. And a simple client program. I've packaged this all rather neatly into a zip file so that you can instantly create an Eclipse project. Here is the zip file: http://affy.blogspot.com/java/SimpleBean.zip

SimpleBean.java

Make sure to get your JBoss server started. Then customize the build.xml file for your configuration (mostly just the first 10 lines or so). Then open a DOS window and run ant deploy. After the Ant process is done, run the SimpleBeanClient class from Eclipse.

Let me know if you have any problems.

package com.affy.entity;

import java.rmi.RemoteException;
import javax.ejb.*;
import com.affy.util.SimpleBeanUtil;

/**
 * @ejb.bean name="SimpleBean" type="CMP" cmp-version="2.x" jndi-name="ejb/affy/SimpleBean" primkey-field="pKey"
 * @ejb.util generate="physical"
 */
public abstract class SimpleBean implements EntityBean {

	public EntityContext mContext;

	/** @ejb.persistence */
	public abstract String getPKey();
	public abstract void setPKey(String pKey);

	/** @ejb.create-method view-type="remote" */
	public String ejbCreate() throws EJBException, CreateException {
		this.setPKey(SimpleBeanUtil.generateGUID(this));
		return this.getPKey();
	}

	public void ejbPostCreate() { /* do nothing */ }
	public void ejbRemove() throws RemoveException, EJBException, RemoteException {}
	public void ejbActivate() throws EJBException, RemoteException {}
	public void ejbPassivate() throws EJBException, RemoteException {}
	public void ejbLoad() throws EJBException, RemoteException {}
	public void ejbStore() throws EJBException, RemoteException {}
	public void setEntityContext(EntityContext lContext) { mContext = lContext; }
	public void unsetEntityContext() { mContext = null; }
}

SimpleClient.java

package com.affy.client;

import com.affy.remote.SimpleBean;
import com.affy.home.SimpleBeanHome;
import com.affy.util.SimpleBeanUtil;

class SimpleBeanClient {

	public static void main(String[] args) {
		System.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		System.setProperty("java.naming.provider.url", "localhost:1099");
	
		try {
			SimpleBeanHome home = SimpleBeanUtil.getHome();

			SimpleBean sb = home.create();
			String pKey = (String)sb.getPrimaryKey();
			System.out.println("ID: " + pKey);

			SimpleBean b = home.findByPrimaryKey(pKey);
			System.out.println("ID: " + b.getPrimaryKey());

			System.out.println("Done.");
		} catch(Exception e) {
			System.out.println(e.toString());
		}
	}
}

Thursday, March 13, 2003

Free? Java-Based Mail Server

I currently use SpamArrest to block spam at the server before I download messages locally. When an unknown email sender is encountered, a challenge message is sent back. Only if I authorize the sender or if the challenge message is answered does the email arrive at my local mailbox. However, I always review the suspicous messages because many people ignore the challenge message. So if I had an email client with a white list, my life might be simpler. This paragraph leads me to the MAILMILL software at http://www.metamagix.net/mailmill.html. MAILMILL is free for non-commercial use. Commercial users of MAILMILL must pay registration fee to Metamagix OEG

Read the JBoss BLUE paper.

The JBoss BLUE paper at http://www.jboss.org/blue.pdf is full of interesting tidbits.

Tuesday, March 11, 2003

Online Book; Complete Text of 'Perl 5 by Example'

I've moved my online book, Perl 5 by Example, to the Blog servers. It can now be found at http://affy.blogspot.com/p5be/index.htm. I apologize in advance for the confusion that this move will cause.

Updated Resume for David Medinets

I spoke with TunaRez last night about my resume. They made a few suggestions that sounded good. So I've updated my resume at http://affy.blogspot.com/dmm_resume/resume.htm. You'll notice that I've removed all graphics, added an Objective and Summary section, moved the Skills List towards the beginning and consolidated many of the entries into my consulting company. These changes reduced the page count to three from six. Let me know if you like the changes.

Monday, March 10, 2003

Example: A HelloWorldServlet Generater - You pick the Eclipse Project Name!

After writing the HelloWorld servlet of my last post, I realized that it's usefulness was limited because people new to servlet programming would not know what needed to be changed in order to use the project as a template. So, I've created an Ant build.xml file to do the work for you. Simply unzip my http://affy.blogspot.com/java/HelloWorldTemplateServlet.zip file into a convenient directory. Then connect to it via a DOS prompt and type ant. You'll be prompted for the Eclipse workspace directory (d:\java\workspace, for me) and the name of the project that you want to create. Try aaa just to see what happens. Follow the directions in the README.txt file in the newly-created directory and you should have the servlet runing in a short amount of time.

Saturday, March 08, 2003

Example: Building an HelloWorld Servlet for Tomcat Using Eclipse

Tomcat's documentation is great. But it doesn't specifically have an Eclipse-based example. And so, here one is. Nothing special, just how to display Hello, World using a servlet. You can find a zip file with the Eclipse project at http://affy.blogspot.com/java/HelloWorldServlet.zip. The README.TXT file provides the steps needed to run the example. Let me know if something is unclear.

Tuesday, March 04, 2003

Why Use UUID Values?

In this note, I attempt to articulate why I feel strongly that using UUID values is better than Sequences (or Autonumbering) for Primary Keys.

Debugging Production Issues - When subtle production issues arise, it is often good to be able to copy production data into a development database. When using Sequences, the process of copying production data normally involves a DBA because Primary Keys in the production system may already exist in development leads to various insert and update errors. When UUID values are used, there is no possibility of duplicate values. Therefore, moving production data back to staging and/or the development environments is much easier.

Copying Dynamic Lists Between Environments - Imagine information like a user list that starts in the development environment during the creation of a customer service application. Then the application is moved to a production customer service server. Imagine further that that data is also used as part of a company directory. Then in true-to-life fashion, a subtle bug is hit that moves the Trenton, NJ employees into the Boston, MA business unit. A bug might not cause this problem. For example, a company could be sold or a layoff could happen. If only one or two records are affected, they can be fixed using the Customer Service application. But what if 3,000 records were affected and a simple SQL statement isn�t enough to correct the bad records? In this situation, the data needs to be copied back to the development environment, a program must be written to fix the data, and then the data must be copied back to staging for testing, and then into production. Moving data is hard enough when simple tables are used. When parent-child relationships are involved the data movements routines to ensure that no Sequence classes occur are more complex. If Sequences are used each time that the data is moved, the DBA needs to write SQL to modify the Sequences for each affected table. A potentially arduous task. If UUID values are used, the problem can be resolved simply. Simply write an SQL SELECT�INTO statement to move the data between the two databases.

Synchronizing Development With Production - Much of the time, I like the data in my development environment to mirror that in production. And yet, I still want the freedom to create test data. When using Sequence numbers this scenario causes problems because the Sequence numbers between the two databases will clash. If needed a Boolean field called bFromProduction can be maintained so that production data can be separated from development data. Another method, perhaps preferred for its simplicity, could be to maintain a productionUUID table that is populated before the production data is moved. With UUID values, only the UUID need be stored, with Sequence numbers, such a table would also need to store the table name to avoid value clashes.

Easy Elimination of Redundant Form Submits - One issue when working with stateless environments revolves around users submitting their forms twice. This issue is critical when inserting and updating information. If not properly handled, duplicate records can be created in the database. Duplicate inserts can be eliminated creating a UUID value beforehand and making it part of the form information. The database (or application) can be check for the UUID value before inserting any record. Duplicate updates can be avoided by using a UUID value as an audit marker. Each change to the database can be logged to an audit table. When an update form is submitted, the UUID value can be checked against the audit table.

Permissibility Frameworks - UUID values also have advantages when used in permissibility frameworks. This advantage arises because one table can be used to store permission information for all objects in the system. Actually, the advantage works two ways. One, any object can be protected. And two, any object can be the accessor. So, ensuring that a printer can only be accessed by a specific application is easy to accomplish with the same framework that protects a file from being accessed by a user.

The Data-Driven Framework (or DDF) for ColdFusion

Get the Source Code!

In general, a development framework allows programmers to focus on the unique aspects of an application. Many frameworks have been developed over the years - even the Radio Shack Model I; back in 80's had a framework to make adding new DOS commands easy (provided you knew assembly language). Microsoft developed a framework called MFC for Windows. Today there are several frameworks for ColdFusion; CFObject and Fusebox are perhaps the most well-known.

Language Independence

I freely switch between several languages (Java, ColdFusion, and Perl being my current favorites) on a near daily basis. Therefore, the framework that I use should be able to be duplicated in any language.

Application Independence

The application code should be totally unaware of the framework. When a developer sits down to create a feature or to maintain code, she should not have to worry about what the framework is doing. In other words, the framework should be loosely coupled to the application.

Simple

Since I work in so many different environments I want to use a framework with as few rules as possible. I don't want to remember a large set of guidelines as I'm coding. No programming "tricks" that need explaining should be used.

Generic

All code in the framework should be relevant for *all* situations. Application-specific code should be delegated to include files. And those files should be generically named like [application]_init.cfm or [application]_pre_action.cfm or [application]_post_action.cfm.

Data-Driven Decisions

Whenever possible, function points in an application should be replaced by dynamic data. For example, instead of a switch or if statement to determine a hard-coded color, use a hash table (a structure) with the switch expression as the key. This approach can potentially increase the scalability of your program, but more importantly increases its flexibility. During run-time, a new hash entry can be created to accomodate a new value for your expression. If a switch statement is used, a new version of the template needs to be coded, tested, and released.

Sometimes predefining data is not possible, and that's ok. Also sometimes the various combinations of parameters such as security and time-of-day are too complex and using an algorithm is better then using data. Obviously some programmer judgement will be needed.

What is Oracle's Mysterious MERGE Keyword for?

Oracle 9i supports a new SQL statement called MERGE. It's fully documented but let me provide an example that I've just been working on.

The advantage of MERGE is that a single SQL statement handles two cases:

  • INSERT if the record doesn't exist.
  • UPDATE if the record exists.

The intended use of MERGE was to modify one database table based on another table (or view). However, through a little creativity we can use MERGE for more mundane tasks - like the standard administrative Add/Edit a single-record functions.

The following SQL shows how to use the MERGE statement to insert or update a single record.

MERGE INTO 
	dr_fulltext A
USING
	(select 'Test41' u_object, 'EN-US' u_locale from dual) B
ON 
	(A.u_object = B.u_object AND A.u_locale = B.u_locale)
WHEN MATCHED THEN 
	UPDATE SET A.keywords = '33333333333'
WHEN NOT MATCHED THEN 
	INSERT (
	    A.u_object, A.u_locale, A.keywords
	) values (
	    'Test41', 'EN-US', '222222'
	);

Since the Merge clause is designed for getting information from a table I needed to finagle the USING class in order to create what is essentially a virtual table of one record. The ON clause checks to see if that single record (from the B table) exists in the A table. If it doesn't exist the INSERT statement is run. If it does, then the UPDATE statement is run.

The parentheses around the ON clause seem to be critical but I don't know why. If the parentheses are left off, then an "ORA-00969: missing ON keyword" error results.

The alias names in the UPDATE and INSERT are logically not needed, but Oracle demands clarity because the Keywords field is used twice. If the alias name (A) is not supplied Oracle responds with an "ORA-00957: duplicate column name" error.

Is using JDBC's Prepared Class really faster than the Statement Class?

NOTE: I used the OracleConnectionPoolDataSource class to connect to Oracle9i for these tests.

Most of my reading about JDBC indicated that we should use the PreparedStatement class to take advantage of bind variables and pre-compilation of SQL. However, one article said that using the Statement class was better because of how vendors implement the JDBC drivers. So, of couse, I felt compelled to perform my own timing tests.

I executed the following simple select statement 1,000 times with both classes. Of course, when using the PreparedStatement, the string literal was replaced by a bind variable.

  select uuid, display_name, description from dr_locales where uuid = 'EN-US'

The example using the statement class took 3,564 milliseconds to run. While the PreparedStatement example took 2,594 seconds to run.

Of course, I dug a little deeper. How much overhead is involved in instantiating the two classes? In order to answer, I placed the object instantation inside the loop:

                      InsideLoop     OutsideLoop
   Statement:         3,915          3,564
   PreparedStatement: 4,486          2,594 <-- best elapsed time.

The following figure shows the relationships graphically.

A rehash of the text table.

This test shows that it really pays to reuse PreparedStatement objects.

The last question I tried to answer in my tests was; Which class is better if no bind variables are used?

   Statement:         4,636
   PreparedStatement: 3,445

So, my empiric results agree with my common sense and the majority of the literature that I've read.

It seems that the PreparedStatement class should be used in all cases.

A Java Implementation of the Nested Tree Model

NOTE: If you don't know the concepts behind the Nested Tree Model, you'll need to find a copy of Joe Celko's 'SQL for Smarties' or read the online article at http://www.intelligententerprise.com/001020/celko.shtml.

Best Practice; Ant; Always Have a Versions Task

This task is designed to display the version of every software application used during the build process. It will mainly be used when sending a debugging report to vendors. However, it could also be useful when creating archival information. Here is my implementation of a VERSIONS task:

<target name="versions">
	<!-- DOS version -->
	<exec executable="cmd.exe"><arg line="/c ver" /></exec>
	<!-- ANT version -->
	<echo>${ant.version}</echo>
	<!-- SolarMetric's KODO version -->
	<java classname="com.solarmetric.kodo.conf.JDOVersion" fork="yes">
		<classpath>
			<pathelement location="${kodo.jdo.classfile}" />
			<pathelement location="${kodo.impl.home.dir}\lib\jdo1_0.jar" />
			<pathelement location="${kodo.impl.home.dir}\lib\serp.jar" />
			<pathelement location="${kodo.impl.home.dir}\lib\jta-spec1_0_1.jar" />
			<pathelement location="${kodo.impl.home.dir}\lib\jca1.0.jar" />
		</classpath>
	</java>
</target>

When I run ant versions, here is the resulting output:

Buildfile: build.xml

versions:

     [exec] Microsoft Windows XP [Version 5.1.2600]
     [echo] Apache Ant version 1.5 compiled on July 9 2002
     [java] Kodo JDO Enterprise Edition version 2.3.1
     [java] version id: kodojdo-2.3.1-20020821-1709

     [java] os.name: Windows XP
     [java] os.version: 5.1
     [java] os.arch: x86

     [java] java.version: 1.4.0_01
     [java] java.vendor: Sun Microsystems Inc.

     [java] java.class.path:
     [java]     D:\java\jdo\impl\kodo-jdo-2.3.1\lib\kodo-jdoee.jar
     [java]     D:\java\jdo\impl\kodo-jdo-2.3.1\lib\jdo1_0.jar
     [java]     D:\java\jdo\impl\kodo-jdo-2.3.1\lib\serp.jar
     [java]     D:\java\jdo\impl\kodo-jdo-2.3.1\lib\jta-spec1_0_1.jar
     [java]     D:\java\jdo\impl\kodo-jdo-2.3.1\lib\jca1.0.jar

     [java] user.dir: D:\java\WORKSP~1\REFERE~1

A Reference Data Framework Using Java Data Objects (JDO)

The MS Word version of the document can be found at http://affy.blogspot.com/reference_data_framework/Reference Data Framework.doc.

The source code that supports the framework can be found at http://affy.blogspot.com/reference_data_framework/reference_data_framework.zip.

Abstract - This paper describes one of the packages developed during a consultancy engagement between Ogilvie Partners Ltd and Eclectic Consulting in Arlington, VA, during July 2002. Our joint aim in publishing our results is to add to the evolving body of knowledge about the application of JDO to real-world projects.

Every application requires some form of reference data to be persisted and managed. Projects tend to treat the topic in different ways which results in duplication of design and implementation effort. As part of a much larger design effort we faced this issue and attempted to write a generic framework that could be reused across different projects.

An Example of Object Persistence (or Prevalence) Using Prevayler

Several years ago, while I was working for Toysrus.com I created an In-Memory database of their inventory items using ColdFusion. There were about 30,000 parts and ColdFusion was easily able to handle that much memory in their structures. The time-consuming ascept of that project was developing the code to read the information from the database into memory. Today, in Java world, Object Prevalance, makes the same task much easier.

The home page for the Object Prevalence system that I use is http://www.prevayler.org/wiki.jsp?topic=StartingPoints. I won't spend any time describing the concepts, but you can read about them there. I first started looking at Object Persistence technologies because I wanted to write a JarSearcher application. I could search the store for any class. Frequently when I'm compiling someone else's code, I find class references that I'm unfamilar with and don't know which Jar file the class is in. My JarSearcher would pre-search Jar files so that I could quickly find the class that I need. The application works in two steps. First, .jar files are indexed. And then class names are found as needed. You'll find my source code at JarSearcher.zip. The docomentation is rather sparse for now. The js.bat file shows how to invoke the application. The java_projects.txt file shows how to create a script for the application to follow. Please send comments to myself at medined@mtolive.com. After you send email, you'll be asked to verify that you're human (instead of a spammer) by SpamArrest.

Monday, March 03, 2003

CodeBit; How Can I Update All CPAN Perl Modules At Once?

Run the following from a command-line:

perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'

2008-04-08 Update: An observant reader noticed that my example was missing an ending quote.

CodeBit; How to Demote a Domain Controller Using Microsoft Windows 2000?

Run the DCPROMO program from the Win2000 command line.

CodeBit; Sorting Arrays With Numbers Using Perl

If you are looking to use the sort method to sort an array which contains numbers, the regular sort @array technique won't do you much good.

To sort an array, do the following:

# from least to greatest
foreach$number(sort { $a <=> $b } @numbers) {
   print $number\n";
}
# from greatest to least:
foreach$number(sort { $b <=> $a } @numbers) {
   print $number\n";
}

CodeBit; Reading a whole file into a scalar Using Perl

Quite often, it is very useful to read the contents of a file into a scalar variable. The following example shows how this can be done. $fileName is the name of the input file. $buffer is a scalar where the file contents is stored. The $/ variable contains the end-of-record delimitor. By undefining the variable, Perl will be forced to read the entire file in one shot.

Usage:

$buffer = readFileContents($fileName)

Code:

sub readFileContents {
  my($fileName) = shift;
  my($buffer);
  local($/) = undef;

  open(FILE, $fileName)
    or die "couldn't open $filename for reading: $!\n";

  $buffer = <FILE>;
  close(FILE);
  return($buffer);
}

CodeBit; How Do I Store Text in the Windows Clipboard Using JavaScript?

Click on the first line of text in order to see that text pasted into the third line of text:

<HEAD>
<SCRIPT>
function IsWhitespace(ch) {
  return(
    ch == ' ' || ch == '\n' || ch == '\r' || 
    ch == '\t' || ch == '\f' || ch == '\v' || ch == '\b'
  );
}

// SaveToClibboard
function S2CB() {
  maxLen = 80;
  numLines = event.srcElement.innerText.length / maxLen;
  newStr = '';
  startPos = 0;
  for (x = 0; x < numLines; x++) {
    endPos = startPos + maxLen;
    while (! IsWhitespace(event.srcElement.innerText.charAt(endPos)))
      endPos--;
    newStr = newStr + event.srcElement.innerText.substring(startPos, endPos) + '\n';
    startPos = endPos + 1;
  }
  newStr = newStr + event.srcElement.innerText.substring(
    startPos, event.srcElement.innerText.length
  ) + '\n';
  window.clipboardData.setData('Text', newStr);
  oSource2.innerText = window.clipboardData.getData('Text');
}
</SCRIPT>
</HEAD>
<BODY>
<B ID="oSource" onClick="S2CB()">@changes 2000-Nov-01 
  DMM DMM00013 Silentsurf(nph-index.cgi,Interface.pm): 
  Initial hits to the server are immediately routed to the startup 
  form which eliminates a lot of module loading in the 
  Silentsurf package./</B><br>
<B ID="oSource1" onClick="S2CB()">222</B><br>
<pre>!!<B ID="oSource2" onClick="S2CB()">333</B>!!</pre><br>
</BODY>
</HTML>

CodeBit; How do I Reset the Root password of MySQL Using Linux?

  1. /usr/local/mysql/bin/safe_mysqld --skip-grant-tables &
  2. /usr/local/mysql
  3. use mysql;
  4. update user set password = password('.......') where user = 'root' and host='localhost';
  5. Stop and Start the MySQL server. [2003Oct03 Note] A reader mentioned that it is easier to 'flush privileges' instead of restarting the server.

CodeBit; How do I Set the CLASSPATH Variable Using Linux?

Create a file called /etc/profile.d/jdk.sh and fill it with this:

  if [ -z "${JAVA_HOME}" ] ; then
    export JAVA_HOME=/usr/lib/jdk116
  fi
  if [ -z "${JDK_HOME}" ] ; then
    export JDK_HOME=/usr/lib/jdk116
  fi
  SW=`cat /etc/profile.d/java`
  SW=`echo ${SW}  | sed -e "s/ /:/g"`
  MYPATH="${JDK_HOME}/lib/classes.zip:${SW}"
  export CLASSPATH="${MYPATH}"
  MYPATH="${JDK_HOME}/bin/"
  echo ":${PATH}:"| grep "${MYPATH}" >/dev/null ||\
    PATH="${PATH}:${MYPATH}"

  export PATH
  unset SW MYPATH

Create a file called /etc/profile.d/javaM and fill it with a list of directories, jars, and zips.

CodeBit; How to Redirect to New URL Using JavaScript

This example shows how to redirect a web browser to another page. The JavaScript performs a countdown of the number of seconds left before the redirection is performed.

<HTML>
<HEAD>
  <TITLE>"Some Page" has moved!</TITLE>
  <META HTTP-EQUIV=Refresh CONTENT=6;URL=http://www.codebits.com/>
  <SCRIPT LANGUAGE="Javascript">
    <!--
    function countdown() {
      if ( document.myform.count.value > 0 ) {
        document.myform.count.value = document.myform.count.value-1;
        setTimeout("countdown()", 1000);
      }
    }
    //-->
  </SCRIPT>
  </HEAD>
  <BODY><H1>"Some Page" has Moved!</H1>
  The new address is: 
  <A HREF="http://www.codebits.com/" TARGET=_top>http://www.codebits.com</A>.
  <P><FORM NAME=myform>
  You will be redirected to the above page in 
  <INPUT NAME="count" SIZE="1" value="6"> secs.....)</FORM>
  <SCRIPT LANGUAGE="Javascript">
    <!--
    countdown();
    //-->
  </SCRIPT>
  </BODY>
</HTML>

Sunday, March 02, 2003

CodeBit; How Do I Load An Image and Determine Height and Width Using Java?

When loading an image over the net you frequently have to allow for long load times. The MediaTracker class is used to monitor a resource so that other things can happen (ie. threads) while the image is loading. However, sometimes you really need for the image to totally load because you need the height and width measurements before continuing. The following code fragment show how to wait for an image to finish loading. - from Bob Withers in comp.lang.java.api.

// url is a String containing the URL of the image to load.
MediaTracker tr;
Image        im = toolkit.getImage(url);

tr.addImage(im, 0);
tr.waitForID(0);

// at this point the image is finished
// loading and the height and width can
// be determined.
int w = im.getWidth(this);
int h = im.getHeight(this);

CodeBit; How Can I Improve the I/O Speed for System.out.println Using Java?

Normally, the System.out print stream has a buffer size of 128 and flushes the buffer whenever a newline character is encountered. The following four lines of java change the buffer size to 1024 and doesn't flush the buffer for newline characters.

FileOutputStream fdout = new FileOutputStream(FileDescriptor.out);
BufferedOutputStream bos = new BufferedOutputStream(fdout, 1024);
PrintStream ps = new PrintStream(bos, false);
System.setOut(ps);

Saturday, March 01, 2003

CodeBit; How to Find the Parent Frame of a Component Using Java

Frame getParentFrame() {
  Component p = this;

  while ( (p = p.getParent()) != null && !(p instanceof Frame) )
    ;
  return( (Frame)p );
}

CodeBit; Using Perl to Generate a Table of Contents for HTML Pages

This script is designed to create a Table of Contents page for HTML documents. It reads any files listed on the command line (wildcards are OK) and searches for the HTML <Hn> tags.

To index an entire directory use: perl toc.pl *.html

NOTE: The files will be read in alphabetical order which may not be the order that you need. Simply cut and paste the resulting HTML until the order is correct.

#!/usr/bin/perl -w
#
# To index an entire directory use: 
#     perl toc.pl *.html
#
use strict;

# holds the name of each file
# as it is being processed.
my($file);       

# holds the text of the heading
# (from the anchor tag).
my($heading);   
                
# holds the last heading level
# for comparision.
my($oldLevel);   
                
# holds each line of the file 
# as it is being processed.
my($line);      
                
# used as temporary variables 
# to shorten script line widths
my($match);     
my($href);      

# holds the name of the heading 
# from the anchor tag.
my($name);      
                
# holds the level of the current heading.
my($newLevel);  

# First, I open an output file and print the 
# beginning of the HTML that is needed.
#
$outputFile = "fulltoc.htm";
open(OUT, ">$outputFile");
print OUT ("<HTML><HEAD><TITLE>");
print OUT ("Detailed Table of Contents\n");
print OUT ("</TITLE></HEAD><BODY>\n");

# Now, loop through every file in the command 
# line looking for Header tags. When found, Look 
# for an Anchor tag so that the NAME attribute can 
# be used. The NAME attribute might be different
# from the actual heading.
#
foreach $file (sort(@ARGV)) {
    next if $file =~ m/^\.htm$/i;
    print("$file\n");
    open(INP, "$file");
    print OUT ("<UL>\n");
    $oldLevel = 1;
    while (<INP>) {
        if (m!(<H\d>.+?</H\d>)!i) {
            # remove anchors from header.
            $line = $1;
            $match = '<A NAME="(.+?)">(.+?)</A>';
            if ($line =~ m!$match!i) {
                $name = $1;
                $heading = $2;
            }
            else {
                $match = '<H\d>(.+?)</H\d>';
                $line =~ m!$match!i;
                $name = $1;
                $heading = $1;
            }
            m!<H(\d)>!;
            $newLevel = $1;
            if ($oldLevel > $newLevel) {
                print OUT ("</UL>\n");
            }
            if ($oldLevel < $newLevel) {
                print OUT ("<UL>\n");
            }
            $oldLevel = $newLevel;
            my($href) = "\"$file#$name\"";
            print OUT ("<LI>");
            print OUT ("<A HREF=$href>");
            print OUT ("$heading</A>\n");
        }
    }
    while ($oldLevel--) {
        print OUT ("</UL>\n");
    }
    close(INP);
}

# End the HTML document and close the output file.
#
print OUT ("</BODY></HTML>");
close(OUT);

CodeBit; How to Reduce HTML Size Yet Still Use Long Style Names Using ColdFusion

Here's a suggestion for dealing with styles donated by Steve Runyon.

Long style names, like "tabCellSelected" or "tabCellUnselected", cause HTML page sizes to grow. For example, if you have a table with 8 columns and 20 rows, with 1 column selected, you're expending 2680 bytes on the names of the styles. ((7 * 20 * 17) + (1 * 20 * 15) = 2680)

The page size can be reduced by creating (application?) variables named like the style, whose values are short placeholders:

<cfset application.TabCellSelected_sty = "s001">
<cfset application.TabCellUnselected_sty = "s002">

Your style definitions then look like this:

TD.#application.TabCellSelected_sty# {
	[etc]
}
TD.#application.TabCellUnselected_sty# {
	[etc]
}

And your generated html looks like this:

<td class=s001>data</td>
<td class=s002>data</td>

On that same 8x20 table, you're now using only 640 bytes for the styles. (8 * 20 * 4)

CodeBit; Making ColdFusion Modules More Secure

While reading an article written by Matt Reider (Macromedia), I noticed the following tidbit that ensures that a CF module is not called directly via a URL.

<!--- security - this template must be called as a custom tag --->
<CFIF NOT isDefined("caller")>
    <CFABORT>
<CFELSE>
    <!--- 
        make sure caller is a structure� otherwise 
        they could have passed it in the URL
     --->
    <CFIF NOT isStruct(caller)>
        <CFABORT>
    </CFIF>
</CFIF>

CodeBit; How Do I Prevent a Page From Caching in the Browser Using ColdFusion?

The following code should work in most situations. This code is courtesy of Cameron Childress).

<!--- Anti-cache --->
<CFSET gmts = gettimezoneinfo()>
<CFSET gmt = gmts.utcHourOffset>
<CFIF gmt EQ 0>
  <CFSET gmt = "">
<CFELSEIF gmt GT 0>
  <CFSET gmt = "+" & gmt >
</CFIF>
 
<CFHEADER NAME="Expires" VALUE="Mon, 06 Jan 1990 00:00:01 GMT">
<CFHEADER NAME="Pragma" VALUE="no-cache">
<CFHEADER NAME="cache-control" VALUE="no-cache, must-revalidate">
<CFHEADER NAME="Last-Modified" 
  VALUE="#dateformat(now(), 'ddd, dd mmm yyyy')# #timeformat(now(), 'HH:mm:ss')# GMT#gmt#">

CodeBit; How Do I Clear a CachedWithin Query Using ColdFusion?

If you use a dynamic timespan instead of a fixed timespan, you can clear the cache by setting the timespan to zero when the query is executed.

<cfif url.clear_cache eq 1>
    <cfset time_span = CreateTimeSpan(0,0,0,0)>
<cfelse>
    <cfset time_span = CreateTimeSpan(0,0,30,0)>
</cfif>

<cfquery ... cachedwithin="#time_span#">
   ... do some sql here.
</cfquery>

CodeBit; How to Unset or Undefine Environment Variables Using Perl

Environment variables are stored as entries in the %ENV hash. Therefore you can use the delete() function to unset them. Sometimes unsetting environment variables is usefull to control the environment of a child process.

CodeBit; Using Perl to Process HTML Form Information

I've found using a hash variable to hold form information to be the easiest way to work. The function shown below is called getFormData. It reads each form field into a hash, with either 'scalar_' or 'array_' prepended to the field names. This technique works well when you have form field with the same name, like checkboxes.

In order to effectively use this code, you need to be familiar with references. If you need a refresher on this topic, please see Chapter 8 of my book at http://www.CodeBits.com/p5be/ch08.cfm.

Here is the code that I place towards the top of my CGI scripts:

    getFormData(\%FORM);

The printFORM function is used for debugging. It prints all of the values in the FORM hash. Notice that it displays both scalar and array versions of the form data.

sub printFORM {
  print "Form Variables\n";
  print "--------------\n";

  foreach $key (sort(keys(%FORM))) {
    print "$key = @{$FORM{$key}}\n"
      if ref($FORM{$key}) eq "ARRAY";
    print "$key = $FORM{$key}\n"
      if ref($FORM{$key}) ne "ARRAY";
  }
}

And then towards the end of the script, I place the following routine:

sub getFormData {
  my($hashRef) = shift;
  my($buffer) = "";

  if ($ENV{'REQUEST_METHOD'} eq 'GET') {
    $buffer = $ENV{'QUERY_METHOD'};
  }
  else {
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
  }

  foreach (split(/&/, $buffer)) {
    my($key, $value) = split(/=/, $_);

    $key = decodeURL($key);
    $value = decodeURL($value);

    $hashRef->{"scalar_$key"} = $value;

    if (! defined($hashRef->{"array_$key"})) {
      $hashRef->{"array_$key"} = [ $value ];
    }
    else {
      push @{$hashRef->{"array_$key"}}, $value;
    }
  }
}

CodeBit; Sorting Perl Hashes by Keys and by Values

Code

#/usr/bin/perl -w
use strict;
my(%hash);
# Create a hash with four elements.
$hash{'01'} = 'D';
$hash{'02'} = 'C';
$hash{'03'} = 'B';
$hash{'04'} = 'A';
# Sort the hash according to its keys.
my(@sortedByKey) = sort(keys(%hash));
# Print out the hash entries in sorted order.
print "Sorted by Key:\n";
foreach (@sortedByKey) {
  print "\t$_: $hash{$_}\n";
}
# Sort the hash according to its keys. The 
# $a and $b scalars are part of the main
# package namespace. Therefore, the main
# package name needs to be specified when
# using the strict pragma.
my(@sortedByValue) = sort { $hash{$main::a} cmp $hash{$main::b} } keys %hash;
# Print out the hash entries in sorted order.
print "Sorted by Value:\n";
foreach (@sortedByValue) {
  print "\t$_: $hash{$_}\n";
}

output

Sorted by Keys:
        01: D
        02: C
        03: B
        04: A
Sorted by Values:
        04: A
        03: B
        02: C
        01: D

CodeBit; Using Hashes in Bash Scripts

This codebit was donated by Phil Howard on 1998Dec03. Hash data structures are very convenient. They let you use strings as indexes instead of numbers. The value script, shown below, demonstrates how to use Bash's eval command to simulate a hash structure. The command, value david prints "The email address for david is medined@mtolive.com".

#!/bin/bash
# value.sh

email_phil="phil@rigel.ipal.net"
email_david="medined@mtolive.com"

eval 'email=${email_'"${1}"'}'
echo "The email address for ${1} is ${email}"