Tuesday, December 30, 2008

java.io.FileNotFoundException: /home/mtccruise/cruisecontrol-bin-2.8.1/projects/sugar_service/junitvmwatcher1613190630.properties (No such file or dir

I got this error after I set up the cruisecontrol.

snippet in ant file:

java.io.FileNotFoundException: /home/mtccruise/cruisecontrol-bin-2.8.1/projects/sugar_service/junitvmwatcher1613190630.properties (No such file or directory)

The reason is that a different version of ant exist. The classpath defined in red color includes a couple of ant jars which are version 1.6, but the actual ant I'm running is version 1.7. Remove those jars, the problem solved.

Monday, December 8, 2008

Setup new repository in SVN failed.

Move a Subversion repository from one machine to another

Even if the machines are on different operating systems, this is dead easy. On the source machine, simply 'dump' the repository:

svnadmin dump /path/to/repo > reponame.dump
tar zcf reponame.tgz reponame.dump
scp reponame.tgz hostname:/path/to/new/repo

Then login to the new machine, and set up the new repo:

cd /path/to/new
svnadmin create reponame
tar zxf reponame.tgz
svnadmin load reponame < reponame.dump

That's all there is to it. Then you can of course delete the dump files, the .tgz files, and even the source repo if you are brave.


All those are fine. But I can't access repository. Spend hours and then figured out SELinux security restriction cause the problem.
Martin said I can use audit2why to generate a policy script and apply it by using audit2allow. But I didn't make it work.

Find a command from http://subversion.tigris.org/faq.html, How do I set repository permissions correctly?
  $ chcon -R -h -t httpd_sys_content_t PATH_TO_REPOSITORY

Then problem solved.

Thursday, November 20, 2008

Using PGP

1. If you want to ask Jerry send you a PGP encrypt file.
    Generate a pair of key (public key and private key). send the public key to Jerry, Jerry will encrypt the file with the public key. and send back the encrypt file, then you can decrypt the file with your private key.

2. Keyring is the place hold your keys. It includes public keyring and private keyring.

Monday, November 10, 2008

Can't delete dist folder by using ant delete

In the Windows platform, seems like some program is using dist folder. But I can't find any except ant itself. The reason is

<path id="classpath.lib">
        <fileset refid="fileset.project.jar"/>
        <fileset refid="fileset.common.jar"/>
        <fileset dir="${root.dir}">
                 <include name="**/dist/*.jar" />
                <exclude name="${basedir}/dist/*.jar"/>
        </fileset>
  </path>

I defined classpath include all dist folder, even exclude the jar in current project, but ant still load this file which cause it can't delete dist folder.

I move the red portion into Javac task, then problem solved.

Saturday, November 8, 2008

Install Trac on Solaris 10

1. test if python is installed.
    #python
Python 2.4.4 (#1, Jan  9 2007, 23:31:33) [C] on sunos5
Type "help", "copyright", "credits" or "license" for more information.
>>>

  1.a I want python 2.5, then remove 2.4.
      #pkgchk -l -p `which python`
      #pkgrm SMCpython
      #pkg-get install python

2. install setuptools 0.6c9 which is a tool makes download, build, install, upgrade, and uninstall Python packages easier!
  setuptools-0.6c9-py2.5.egg (md5)
  (match the version)

3. install trac by using following command, it will install trac-0.11 (Reference to Trac Installation)
 #
easy_install Trac
  3.a Before install Trac, I have to install SQLite, I have tried to use MySQL, but have trouble to find some library.
   #pkg-get install sqlite
  3.b Install Python to SqLIte engine
    #pkg-get install pyslite
  3.c Prerequired packages
    #easy-install Genshi

4. run trac-admin to create project environment
 # trac-admin /path/to/myproject initenv
It will ask a series of questions. Since I use SQLite, all use default.
change owner of /path/to/myproject to web user. I check the file /etc/apache2/httpd.conf, find User and Group, which is webservd.
#chown -R webservd:webservd /path/to/myproject

5. Start stand-alone Trac server
#tracd --port 8998 /path/to/myproject



Cruisecontrol and Maven2

<cruisecontrol>
<!-- Load environment variables -->
<property environment="env" toupper="true"/>

<!-- Commonly used directories -->
<property name="project.dir" value="projects/${project.name}"/>
<property name="log.dir" value="logs/${project.name}"/>

<!-- Defaults for email -->
<property name="buildmaster.email" value="matt@raibledesigns.com"/>
<property name="buildmaster.name" value="Matt Raible"/>

<!-- CruiseControl settings -->
<property name="interval" value="1800"/>
<property name="build.server" value="home.raibledesigns.com:8280"/>

<!-- Preconfigure our plugins -->
<plugin name="currentbuildstatuslistener" file="${log.dir}/status.txt"/>
<plugin name="currentbuildstatuspublisher" file="${log.dir}/status.txt"/>
<plugin name="svn" localWorkingCopy="${project.dir}"/>

<plugin name="htmlemail"
buildresultsurl="http://${build.server}/buildresults/${project.name}"
subjectprefix="[CruiseControl] " css="webapps/cruisecontrol/css/cruisecontrol.css"
xsldir="webapps/cruisecontrol/xsl" logdir="logs/${project.name}"
mailhost="localhost" defaultsuffix="@dev.java.net" reportsuccess="fixes"
returnaddress="${buildmaster.email}" returnname="${buildmaster.name}"/>

<plugin name="email"
buildresultsurl="http://${build.server}/buildresults/${project.name}"
subjectprefix="[CruiseControl] " reportsuccess="always"
mailhost="localhost" defaultsuffix="@dev.java.net"
returnaddress="${buildmaster.email}" returnname="${buildmaster.name}"/>

<project name="appfuse-2.x">
<listeners><currentbuildstatuslistener/></listeners>

<bootstrappers>
<svnbootstrapper localWorkingCopy="projects/${project.name}" />
</bootstrappers>

<modificationset><svn/></modificationset>

<schedule interval="${interval}">
<maven2 mvnhome="${env.M2_HOME}" pomfile="projects/${project.name}/pom.xml" goal="clean scm:update install"/>
</schedule>

<log>
<merge dir="projects/${project.name}/data/common/target/surefire-reports"/>
<merge dir="projects/${project.name}/data/hibernate/target/surefire-reports"/>
<merge dir="projects/${project.name}/data/ibatis/target/surefire-reports"/>
<merge dir="projects/${project.name}/data/service/target/surefire-reports"/>
<merge dir="projects/${project.name}/web/common/target/surefire-reports"/>
<merge dir="projects/${project.name}/web/common-war/target/surefire-reports"/>
<merge dir="projects/${project.name}/web/jsf/target/surefire-reports"/>
<merge dir="projects/${project.name}/web/spring/target/surefire-reports"/>
<merge dir="projects/${project.name}/web/struts/target/surefire-reports"/>
<merge dir="projects/${project.name}/web/tapestry/target/surefire-reports"/>
</log>

<publishers>
<onsuccess>
<artifactspublisher dest="artifacts/${project.name}" dir="${env.HOME}/.m2/repository/org/appfuse"/>
</onsuccess>

<currentbuildstatuspublisher/>
<email><always address="${buildmaster.email}"/></email>
</publishers>
</project>
</cruisecontrol>
Continuum vs. CruiseControl for Maven 2 (from Raible Designs)

I spent some time this past weekend getting automated builds setup for AppFuse 2. Since the project now uses Maven 2, I figured I'd give Continuum a try. I pointed it at my pom.xml in SVN and expected everything to work out-of-the-box. No dice. It seems that Continuum reads the artifactIds instead of the module names for sub-project resolution. To workaround this issue, I'd basically have to rename all my sub-projects to have an "appfuse-" prefix. Doesn't that violate the whole DRY principle? Sure, there's projects that do this, but there's others that don't.

Since I didn't feel like renaming the modules/directories in SVN, I gave CruiseControl a try instead. It took a bit of elbow grease on my part, but I ended up with a config.xml file that works splendidly. It seems somewhat ironic to me that the CruiseControl works better with Maven 2 than Continuum does.

Monday, June 2, 2008

How to get last day of each month

import java.util.Calendar;

public class CalProblem
{
  public static void main(String[] args)
  {
     Calendar myCal     = Calendar.getInstance();

     myCal.set(Calendar.MONTH, 1);
     myCal.set(Calendar.YEAR, 2007);
     System.out.println("");
     System.out.println("Year               => "+myCal.get(Calendar.YEAR));
     System.out.println("Month              => "+myCal.get(Calendar.MONTH));
     System.out.println("Last Day of Month  => "+myCal.getActualMaximum(Calendar.DAY_OF_MONTH));

     myCal.set(Calendar.MONTH, 1);
     myCal.set(Calendar.YEAR, 2008);
     System.out.println("");
     System.out.println("Year               => "+myCal.get(Calendar.YEAR));
     System.out.println("Month              => "+myCal.get(Calendar.MONTH));
     System.out.println("Last Day of Month  => "+myCal.getActualMaximum(Calendar.DAY_OF_MONTH));

  }
}

Sunday, June 1, 2008

Using grep

New Linux users unfamiliar with this standard Unix tool may not
realize how useful it is. In this tutorial for the novice user, Eric
demonstrates grep techniques.

When I first started working in systems integration, I was primarily a
PC support person. I spent a lot of time installing and supporting
Windows applications in various PC LAN configurations, running various
versions (and vendors) of TCP/IP transports. Since then, I have
successfully ditched DOS and moved on. Now, after working on various
versions of Unix for a few years, I porting some of our networking and
data manipulation libraries to other platforms and environments, such
as the AS/400 minicomputer and the Macintosh. This ongoing experience
has given me a chance to appreciate just how powerful the tools we
take for granted with Linux really are.

Searching for a word (or any other value) in a group of files is a
very common task. Whether it's searching for a function in a group of
source code modules, trying to find a parameter in a set of
configuration files, or simply looking for a misplaced e-mail message,
text searching and matching operations are common in all environments.

Unfortunately, this common task doesn't have an easy solution on all
platforms. On most, the best solution available is to use the search
function in an editor. But when it comes to Linux (and other Unix
descendants), you have many solutions. One of them is grep.

grep is an acronym for "global regular expression print," a reference
to the command in the old ed line editor that prints all of the lines
in a file containing a specified sequence of characters. grep does
exactly that: it prints out lines in a file that contain a match for a
regular expression. We'll gradually delve into what a regular
expression is as we go on.
Starting Out

First, let's look at a quick example. We will search for a word in the
Configure script provided with Linux for setting up the Linux kernel
source, which is usually installed in the /usr/src/linux directory.
Change to that directory and type (the $ character is the prompt,
don't type it):

$ grep glob Configure

You should see:

# Disable filename globbing once and for all.

glob is in bold to illustrate what grep matched. grep does not
actually print matches in bold.

grep looked for the sequence of characters glob and printed the line
of the Configure file with that sequence. It did not look for the word
glob. It looked for g followed by l followed by o followed by b. This
points out one important aspect of regular expressions: they match
sequences of characters, not words.

Before we dig any deeper into the specifics of pattern matching, let's
look at grep's "user interface" with a few examples. Try the following
two commands:

$ grep glob < Configure
$ cat Configure | grep glob

both of these two commands should print

# Disable filename globbing once and for all.

which probably looks familiar.

In all of these commands, we have specified the regular expression as
the first argument to grep. With the exception of any command line
switches, grep always expects the regular expression as the first
argument.

However, we presented grep with three different situations and
received the same response. In the first exercise, we provided grep
with the name of a file, and it opened that file and searched it. grep
can also take a list of filenames to search.

In the other two exercises we illustrated a feature that grep shares
with many other utilities. If no files are specified on the command
line, grep reads standard input. To further illustrate standard input
let's try one more example:

$ grep foo

When you run that, grep appears to "hang" waiting for something. It
is. It's waiting for input. Type:

tttt

and press return. Nothing happens. Now type:

foobar

and press enter. This time, grep sees the string foo in foobar and
echos the line foobar back at you, which is why foobar appears twice.
Now type ctrl-d, the "end-of-file" character, to tell grep that it has
reached the end of the file, whereupon it exits.

You just gave grep an input file that consisted of tttt, a newline
character, foobar, a newline character, and the end-of-file character.

Piping input into grep from standard input also has another frequent
use: filtering the output of other commands. Sometimes cutting out the
unnecessary lines with grep is more convenient than reading output
page by page with more or less:

$ ps ax | grep cron

efficiently gives you the process information for crond.
Special Characters

Many Unix utilities use regular expressions to specify patterns.
Before we go into actual examples of regular expressions, let's define
a few terms and explain a few conventions that I will use in the
exercises.

*

Character any printable symbol, such as a letter, number, or
punctuation mark.
*

String a sequence of characters, such as cat or segment
(sometimes referred to as a literal).
*

Expression also a sequence of characters. The difference between
a string and an expression is that while strings are to be taken
literally, expressions must be evaluated before their actual value can
be determined. (The manual page for GNU grep compares regular
expressions to mathematical expressions.) An expression usually can
stand for more than one thing, for example the regular expression
th[ae]n can stand for then or than. Also, the shell has its own type
of expression, called globbing, which is usually used to specify file
names. For example, *.c matches any file ending in the characters .c.
*

Metacharacters the characters whose presence turns a string into
an expression. Metacharacters can be thought of as the operators that
determine how expressions are evaluated. This will become more clear
as we work through the examples below.

Interference

You have probably entered a shell command like

$ ls -l *.c

at some time. The shell "knows" that it is supposed to replace *.c
with a list of all the files in the current directory whose names end
in the characters .c.

This gets in the way if we want to pass a literal * (or ?, |, $, etc.)
character to grep. Enclosing the regular expression in `single quotes'
will prevent the shell from evaluating any of the shell's
metacharacters. When in doubt, enclose your regular expression in
single quotes.
Basic Searches

The most basic regular expression is simply a string. Therefore a
string such as foo is a regular expression that has only one match:
foo.

We'll continue our examples with another file in the same directory,
so make sure you are still in the /usr/src/linux directory:

$ grep Linus CREDITS

Linus
N: Linus Torvalds
E: Linus.Torvalds@Helsinki.FI
D: Personal information about Linus

This quite naturally gives the four lines that have Linus Torvalds'
name in them.

As I said earlier, the Unix shells have different metacharacters, and
use different kinds of expressions. The metacharacters . and * cause
the most confusion for people learning regular expression syntax after
they have been using shells (and DOS, for that matter).

In regular expressions, the character . acts very much like the ? at
the shell prompt: it matches any single character. The *, by contrast,
has quite a different meaning: it matches zero or more instances of
the previous character.

If we type

$ grep tha. CREDITS

we get this (partial listing only):

S: Northampton
E: Hein@Informatik.TU-Clausthal.de

As you can see, grep printed every instance of tha followed by any
character. Now try

$ grep 'tha*' CREDITS
S: Northampton
D: Author of serial driver
D: Author of the new e2fsck
D: Author of loopback device driver

We received a much larger response with "*". Since "*" matches zero or
more instances of the previous character (in this case the letter
"a"), we greatly increase our possibility of a match because we made
th a legal match!
Character Classes

One of the most powerful constructs available in regular expression
syntax is the character class. A character class specifies a range or
set of characters to be matched. The characters in a class are
delineated by the [ and ] symbols. The class [a-z] matches the
lowercase letters a through z, the class [a-zA-Z] matches all letters,
uppercase or lowercase, and [Lh] would match upper case L or lower
case h.

$ grep 'sm[ai]' CREDITS
E: csmith@convex.com
D: Author of several small utilities

since our expression matches sma or smi. The command

$ grep '[a-z]' CREDITS

gives us most of the file. If you look at the file closely, you'll see
that a few lines have no lowercase letters; these are the only lines
that grep does not print.

Now since we can match a set of characters, why not exclude them
instead? The circumflex, ^, when included as the first member of a
character class, matches any character except the characters specified
in the class.

$ grep Sm CREDITS

gives us three lines:

D: Small patches for kernel, libc
D: Smail binary packages for Slackware and Debian
N: Chris Smith
$ grep 'Sm[^i]' CREDITS

gives us two

D: Small patches for kernel, libc
D: Smail binary packages for Slackware and Debian

because we excluded i as a possible letter to follow Sm.

To search for a class of characters including a literal ^ character,
don't place it first in the class. To search for a class including a
literal -, place it the very last character of the class. To search
for a class including the literal character ], place it the first
character of the class.

Often it is convenient to base searches on the position of the
characters on a line. The ^ character matches the beginning of a line
(outside of a character class, of course) and the $ matches the end.
(Users of vi may recognize these metacharacters as commands.) Earlier,
searching for Linus gave us four lines. Let's change that to:

grep 'Linus$' CREDITS

which gives us

Linus
D: Personal information about Linus

two lines, since we specified that Linus must be the last five
characters of the line. Similarly,

grep - CREDITS

produces 99 lines, while

grep '^-' CREDITS

produces only one line:

----------

In some circumstances you may need to match a metacharacter. Inside a
character class set all characters are taken as literals (except ^, -,
and ], as shown above). However, outside of classes we need a way to
turn a metacharacter into a literal character to match.
Matching Metacharacters

For this purpose the special metacharacter \ is used to escape
metacharacters. Escaped metacharacters are interpreted literally, not
as a component of an expression. Therefore \[ would match any sequence
with a [ in it:

$ grep '[' CREDITS

produces an error message:

grep: Unmatched [ or [^

but

$ grep '\[' CREDITS

produces two lines:

E: hennus@sky.ow.nl [My uucp-fed Linux box at home]
D: The XFree86[tm] Project

If you need to search for a \ character, escape it just like any other
metacharacter: \\
Options

As you can see, with just its support of regular expression syntax,
grep provides us with some very powerful capabilities. Its command
line options add even more power.

Sometimes you are looking for a string, but don't know whether it is
upper, lower, or mixed case. For this situation grep offers the -i
switch. With this option, case is completely ignored:

$ grep -i lINuS CREDITS
Linus
N: Linus Torvalds
E: Linus.Torvalds@Helsinki.FI
D: Personal information about Linus

The -v option causes grep to print all lines that do not contain the
specified regular expression:

$ grep -v '^#" /etc/syslog.conf | grep -v '^$'

prints all the lines from /etc/syslog.com that are neither commented
(starting with #) nor empty (^$). This prints six lines on my system,
although my syslog.conf file really has 21 lines.

If you need to know how many lines match, pass grep the -c option.
This will output the number of matching lines (not the number of
matches; two matches in one line count as one) without printing the
lines that match:

$ grep -c Linux CREDITS
33

If you are searching for filenames that contain a given string,
instead of the actual lines that contain it, use grep's -l switch:

$ grep -l Linux *
CREDITS
README
README.modules

grep also notifies us, for each subdirectory, that it can't search
through a directory. This is normal and will happen whenever you use a
wildcard that happens to include directory names as well as file
names.

The opposite of -l is -L. This option will cause grep to return the
names of files that do not contain the specified pattern.

If you are searching for a word and want to suppress matches that are
partial words use the -w option. Without the -w option,

$ grep -c a README

tells us that it matched 146 lines, but

$ grep -wc a README

returns only 35 since we matched only the word a, not every line with
the character a.

Two more useful options:

$ grep -b Linus CREDITS
301: Linus
17446:N: Linus Torvalds
17464:E: Linus.Torvalds@Helsinki.FI
20561:D: Personal information about Linus
$ grep -n Linus CREDITS
7: Linus
793:N: Linus Torvalds
794:E: Linus.Torvalds@Helsinki.FI
924:D: Personal information about Linus

The -b option causes grep to print the byte offset (how many bytes the
match is from the beginning of the file) of each match before the
corresponding line of output. The -n switch gives the line number.
Another grep

GNU also provides egrep (enhanced grep). The regular expression syntax
supported by GNU egrep adds a few other metacharacters:

*

? Like *, except that it matches zero or one instances instead
of zero or more.
*

+ the preceding character is matched one or more times.
*

| separates regular expressions by ORing them together.

$ egrep -i 'linux|linus' CREDITS

outputs any line that contains linus or linux.

To allow for legibility, parentheses "(" and ")" can be used in
conjunction with "|" to separate and group expressions.
More Than Just grep

This covers many of the features provided by grep. If you look at the
manual page, which I strongly recommend, you will see that I did leave
out some command-line options, such as different ways to format grep's
output and a method for searching for strings without employing
regular expressions.

Learning how to use these powerful tools provides Linux users with two
very valuable advantages. The first (and most immediate) of these is a
time-saving way to process files and output from other commands.

The second is familiarity with regular expressions. Regular
expressions are used throughout the Unix world in tools such as find
and sed and languages such as awk, perl and Tcl. Learning this syntax
prepares you to use some of the most powerful computing tools
available.

A mini-tutorial on the Unix/Linux find command

Locating Files:

The find command is used to locate files on a Unix or Linux system.
find will search any set of directories you specify for files that
match the supplied search criteria. You can search for files by name,
owner, group, type, permissions, date, and other criteria. The search
is recursive in that it will search all subdirectories too. The
syntax looks like this:

find where-to-look criteria what-to-do

All arguments to find are optional, and there are defaults for all
parts. (This may depend on which version of find is used. Here we
discuss the freely available GNU version of find, which is the version
available on YborStudent.) For example where-to-look defaults to .
(that is, the current working directory), criteria defaults to none
(that is, show all files), and what-to-do (known as the find action)
defaults to -print (that is, display found files to standard output).

For example:

find

will display all files in the current directory and all
subdirectories. The commands

find . -print
find .

do the exact same thing. Here's an example find command using a
search criteria and the default action:

find / -name foo

will search the whole system for any files named foo and display them.
Here we are using the criteria -name with the argument foo to tell
find to perform a name search for the filename foo. The output might
look like this:

/home/wpollock/foo
/home/ua02/foo
/tmp/foo

If find doesn't locate any matching files, it produces no output.

The above example said to search the whole system, by specifying the
root directory (/) to search. If you don't run this command as root,
find will display a error message for each directory on which you
don't have read permission. This can be a lot of messages, and the
matching files that are found may scroll right off your screen. A
good way to deal with this problem is to redirect the error messages
so you don't have to see them at all:

find / -name foo 2>/dev/null

Other Features And Applications:

The -print action lists the files separated by a space when the output
is piped to another command. This can lead to a problem if any found
files contain spaces in their names, as the output doesn't use any
quoting. In such cases, when the output of find contains a file name
such as foo bar and is piped into another command, that command sees
two file names, not one file name containing a space.

In such cases you can specify the action -print0 instead, which lists
the found files separated not with a space, but with a null character
(which is not a legal character in Unix or Linux file names). Of
course the command that reads the output of find must be able to
handle such a list of file names. Many commands commonly used with
find (such as tar or cpio) have special options to read in file names
separated with nulls instead of spaces.

You can use shell-style wildcards in the -name search argument:

find . -name foo\*bar

This will search from the current directory down for foo*bar (that is,
any filename that begins with foo and ends with bar). Note that
wildcards in the name argument must be quoted so the shell doesn't
expand them before passing them to find. Also, unlike regular shell
wildcards, these will match leading periods in filenames. (For
example find -name \*.txt.)

You can search for other criteria beside the name. Also you can list
multiple search criteria. When you have multiple criteria any found
files must match all listed criteria. That is, there is an implied
Boolean AND operator between the listed search criteria. find also
allows OR and NOT Boolean operators, as well as grouping, to combine
search criteria in powerful ways (not shown here.)

Here's an example using two search criteria:

find / -type f -mtime -7 | xargs tar -rf weekly_incremental.tar
gzip weekly_incremental.tar

will find any regular files (i.e., not directories or other special
files) with the criteria -type f, and only those modified seven or
fewer days ago (-mtime -7). Note the use of xargs, a handy utility
that coverts a stream of input (in this case the output of find) into
command line arguments for the supplied command (in this case tar,
used to create a backup archive). 1

Another use of xargs is illustrated below. This command will
efficiently remove all files named core from your system (provided you
run the command as root of course):

find / -name core | xargs /bin/rm -f
find / -name core -exec /bin/rm -f '{}' \; # same thing
find / -name core -delete # same if using Gnu find

(The last two forms run the rm command once per file, and are not as
efficient as the first form.)

One of my favorite find criteria is to locate files modified less than
10 minutes ago. I use this right after using some system
administration tool, to learn which files got changed by that tool:

find / -mmin -10

(This search is also useful when I've downloaded some file but can't locate it.)

Another common use is to locate all files owned by a given user (-user
username). This is useful when deleting user accounts.

You can also find files with various permissions set. -perm
/permissions means to find files with any of the specified permissions
on, -perm -permissions means to find files with all of the specified
permissions on, and -perm permissions means to find files with exactly
permissions. Permisisons can be specified either symbolically
(preferred) or with an octal number. The following will locate files
that are writeable by others:

find . -perm +o=w

(Using -perm is more complex than this example shows. You should
check both the POSIX documentation for find (which explains how the
symbolic modes work) and the Gnu find man page (which describes the
Gnu extensions).

When using find to locate files for backups, it often pays to use the
-depth option, which forces the output to be depth-first—that is,
files first and then the directories containing them. This helps when
the directories have restrictive permissions, and restoring the
directory first could prevent the files from restoring at all (and
would change the time stamp on the directory in any case). Normally,
find returns the directory first, before any of the files in that
directory. This is useful when using the -prune action to prevent
find from examining any files you want to ignore:

find / -name /dev -prune | xargs tar ...

When specifying time with find options such as -mmin (minutes) or
-mtime (24 hour periods, starting from now), you can specify a number
n to mean exactly n, -n to mean less than n, and +n to mean more than
n. 2 For example:

find . -mtime 0 # find files modified within the past 24 hours
find . -mtime -1 # find files modified within the past 24 hours
find . -mtime 1 # find files modified between 24 and 48 hours ago
find . -mtime +1 # find files modified more than 48 hours ago
find . -mmin +5 -mmin -10 # find files modifed between 6 and 9 minutes ago

The following displays non-hidden (no leading dot) files in the
current directory only (no subdirectories), with an arbitrary output
format (see the man page for the dozens of possibilities with the
-printf action):

find . -maxdepth 1 -name '[!.]*' -printf 'Name: %16f Size: %6s\n'

As a system administrator you can use find to locate suspicious files
(e.g., world writable files, files with no valid owner and/or group,
SetUID files, files with unusual permissions, sizes, names, or dates).
Here's a final more complex example (which I save as a shell script):

find / -noleaf -wholename '/proc' -prune \
-o -wholename '/sys' -prune \
-o -wholename '/dev' -prune \
-o -wholename '/windows-C-Drive' -prune \
-o -perm -2 ! -type l ! -type s \
! \( -type d -perm -1000 \) -print

This says to seach the whole system, skipping the directories /proc,
/sys, /dev, and /windows-C-Drive (presumably a Windows partition on a
dual-booted computer). The -noleaf option tells find to not assume
all remaining mounted filesystems are Unix file systems (you might
have a mounted CD for instance). The -o is the Boolean OR operator,
and ! is the Boolean NOT operator (applies to the following criteria).
So this criteria says to locate files that are world writable (-perm
-2) and NOT symlinks (! -type l) and NOT sockets (! -type s) and NOT
directories with the sticky (or text) bit set (! \( -type d -perm
-1000 \)). (Symlinks, sockets and directories with the sticky bit set
are often world-writable and generally not suspicious.)

A common request is a way to find all the hard links to some file.
Using ls -li file will tell you how many hard links the file has, and
the inode number. You can locate all pathnames to this file with:

find mount-point -xdev -inum inode-number

Since hard links are restricted to a single filesystem, you need to
search that whole filesystem so you start the search at the
filesystem's mount point. (This is likely to be either /home or / for
files in your home directory.) The -xdev options tells find to not
search any other filesystems.

(While most Unix and all Linux systems have a find command that
supports the -inum criteria, this isn't POSIX standard. Older Unix
systems provided the ncheck command instead that could be used for
this.)
Using -exec Efficiently

The -exec option to find is great, but since it runs the command
listed for every found file, it isn't very efficient. On a large
system this makes a difference! One solution is to combine find with
xargs as discussed above:

find whatever... | xargs command

However this approach has two limitations. Firstly not all commands
accept the list of files at the end of the command. A good example is
cp:

find . -name \*.txt | xargs cp /tmp # This won't work!

(Note the Gnu version of cp has a non-POSIX option -t for this.)

Secondly filenames may contain spaces or newlines, which would confuse
the command used with xargs. (Again Gnu tools have options for that,
find ... -print0 |xargs -0 ....)

There are POSIX (but non-obvious) solutions to both problems. An
alternate form of -exec ends with a plus-sign, not a semi-colon. This
form collects the filenames into groups or sets, and runs the command
once per set. (This is exactly what xargs does, to prevent argument
lists from becoming too long for the system to handle.) In this form
the {} argument expands to the set of filenames. For example:

find / -name core -exec /bin/rm -f '{}' +

This form of -exec can be combined with a shell feature to solve the
other problem. The POSIX shell allows us to use:

sh -c 'command-line' [ command-name [ args... ] ]

(We don't usually care about the command-name, so X, dummy, or inline
cmd is used.) Here's an example of efficiently copying found files,
in a POSIX-compliant way 3:

find . -name '*.txt' -exec sh -c 'cp "$@" /tmp' dummy {} +

Or even better:

find . -name '*.txt' -type f \
-exec sh -c 'exec cp -f "$@" /tmp' find-copy {} +

The find command can be amazingly useful. See the man page to learn
all the criteria and options you can use.

Monday, May 12, 2008

Smartly load your properties


Strive for disk location-independent code nirvana

August 8, 2003

QWhat is the best strategy for loading property and configuration files in Java?

A When you think about how to load an external resource in Java, several options immediately come to mind: files, classpath resources, and URLs. Although all of them eventually get the job done, experience shows that classpath resources and URLs are by far the most flexible and user-friendly options.

In general, a configuration file can have an arbitrarily complex structure (e.g., an XML schema definition file). But for simplicity, I assume below that we're dealing with a flat list of name-value pairs (the familiar .properties format). There's no reason, however, why you can't apply the ideas shown below in other situations, as long as the resource in question is constructed from an InputStream.

Evil java.io.File

Using good old files (via FileInputStream, FileReader, and RandomAccessFile) is simple enough and certainly the obvious route to consider for anyone without a Java background. But it is the worst option in terms of ease of Java application deployment. Using absolute filenames in your code is not the way to write portable and disk position-independent code. Using relative filenames seems like a better alternative, but remember that they are resolved relative to the JVM's current directory. This directory setting depends on the details of the JVM's launch process, which can be obfuscated by startup shell scripts, etc. Determining the setting places an unfair amount of configuration burden on the eventual user (and in some cases, an unjustified amount of trust in the user's abilities). And in other contexts (such an Enterprise JavaBeans (EJB)/Web application server), neither you nor the user has much control over the JVM's current directory in the first place.

An ideal Java module is something you add to the classpath, and it's ready to go. Think EJB jars, Web applications packaged in .war files, and other similarly convenient deployment strategies. java.io.File is the least platform-independent area of Java. Unless you absolutely must use them, just say no to files.

Classpath resources

Having dispensed with the above diatribe, let's talk about a better option: loading resources through classloaders. This is much better because classloaders essentially act as a layer of abstraction between a resource name and its actual location on disk (or elsewhere).

Let's say you need to load a classpath resource that corresponds to a some/pkg/resource.properties file. I use classpath resource to mean something that's packaged in one of the application jars or added to the classpath before the application launches. You can add to the classpath via the -classpath JVM option each time the application starts or by placing the file in the <jre home>\classes directory once and for all. The key point is that deploying a classpath resource is similar to deploying a compiled Java class, and therein lies the convenience.

You can get at some/pkg/resource.properties programmatically from your Java code in several ways. First, try:

  ClassLoader.getResourceAsStream ("some/pkg/resource.properties");
Class.getResourceAsStream ("/some/pkg/resource.properties");
ResourceBundle.getBundle ("some.pkg.resource");


Additionally, if the code is in a class within a some.pkg Java package, then the following works as well:

  Class.getResourceAsStream ("resource.properties");


Note the subtle differences in parameter formatting for these methods. All getResourceAsStream() methods use slashes to separate package name segments, and the resource name includes the file extension. Compare that with resource bundles where the resource name looks more like a Java identifier, with dots separating package name segments (the .properties extension is implied here). Of course, that is because a resource bundle does not have to be backed by a .properties file: it can be a class, for a example.

To slightly complicate the picture, java.lang.Class's getResourceAsStream() instance method can perform package-relative resource searches (which can be handy as well, see "Got Resources?"). To distinguish between relative and absolute resource names, Class.getResourceAsStream() uses leading slashes for absolute names. In general, there's no need to use this method if you are not planning to use package-relative resource naming in code.

It is easy to get mixed up in these small behavioral differences for ClassLoader.getResourceAsStream(), Class.getResourceAsStream(), and ResourceBundle.getBundle(). The following table summarizes the salient points to help you remember:

Behavioral differences

Method Parameter format Lookup failure behavior Usage example
ClassLoader.
getResourceAsStream()
"/"-separated names; no leading "/" (all names are absolute) Silent (returns null) this.getClass().getClassLoader()
.getResourceAsStream
("some/pkg/resource.properties")
Class.
getResourceAsStream()
"/"-separated names; leading "/" indicates absolute names; all other names are relative to the class's package Silent (returns null) this.getClass()
.getResourceAsStream
("resource.properties")
ResourceBundle.
getBundle()
"."-separated names; all names are absolute; .properties suffix is implied Throws unchecked
java.util.MissingResourceException
ResourceBundle.getBundle
("some.pkg.resource")


From data streams to java.util.Properties

You might have noticed that some previously mentioned methods are half measures only: they return InputStreams and nothing resembling a list of name-value pairs. Fortunately, loading data into such a list (which can be an instance of java.util.Properties) is easy enough. Because you will find yourself doing this over and over again, it makes sense to create a couple of helper methods for this purpose.

The small behavioral difference among Java's built-in methods for classpath resource loading can also be a nuisance, especially if some resource names were hardcoded but you now want to switch to another load method. It makes sense to abstract away little things like whether slashes or dots are used as name separators, etc. Without further ado, here's my PropertyLoader API that you might find useful (available with this article's download):

public abstract class PropertyLoader
{
/**
* Looks up a resource named 'name' in the classpath. The resource must map
* to a file with .properties extention. The name is assumed to be absolute
* and can use either "/" or "." for package segment separation with an
* optional leading "/" and optional ".properties" suffix. Thus, the
* following names refer to the same resource:
* <pre>
* some.pkg.Resource
* some.pkg.Resource.properties
* some/pkg/Resource
* some/pkg/Resource.properties
* /some/pkg/Resource
* /some/pkg/Resource.properties
* </pre>
*
* @param name classpath resource name [may not be null]
* @param loader classloader through which to load the resource [null
* is equivalent to the application loader]
*
* @return resource converted to java.util.Properties [may be null if the
* resource was not found and THROW_ON_LOAD_FAILURE is false]
* @throws IllegalArgumentException if the resource was not found and
* THROW_ON_LOAD_FAILURE is true
*/
public static Properties loadProperties (String name, ClassLoader loader)
{
if (name == null)
throw new IllegalArgumentException ("null input: name");

if (name.startsWith ("/"))
name = name.substring (1);

if (name.endsWith (SUFFIX))
name = name.substring (0, name.length () - SUFFIX.length ());

Properties result = null;

InputStream in = null;
try
{
if (loader == null) loader = ClassLoader.getSystemClassLoader ();

if (LOAD_AS_RESOURCE_BUNDLE)
{
name = name.replace ('/', '.');
// Throws MissingResourceException on lookup failures:
final ResourceBundle rb = ResourceBundle.getBundle (name,
Locale.getDefault (), loader);

result = new Properties ();
for (Enumeration keys = rb.getKeys (); keys.hasMoreElements ();)
{
final String key = (String) keys.nextElement ();
final String value = rb.getString (key);

result.put (key, value);
}
}
else
{
name = name.replace ('.', '/');

if (! name.endsWith (SUFFIX))
name = name.concat (SUFFIX);

// Returns null on lookup failures:
in = loader.getResourceAsStream (name);
if (in != null)
{
result = new Properties ();
result.load (in); // Can throw IOException
}
}
}
catch (Exception e)
{
result = null;
}
finally
{
if (in != null) try { in.close (); } catch (Throwable ignore) {}
}

if (THROW_ON_LOAD_FAILURE && (result == null))
{
throw new IllegalArgumentException ("could not load [" + name + "]"+
" as " + (LOAD_AS_RESOURCE_BUNDLE
? "a resource bundle"
: "a classloader resource"));
}

return result;
}

/**
* A convenience overload of {@link #loadProperties(String, ClassLoader)}
* that uses the current thread's context classloader.
*/
public static Properties loadProperties (final String name)
{
return loadProperties (name,
Thread.currentThread ().getContextClassLoader ());
}

private static final boolean THROW_ON_LOAD_FAILURE = true;
private static final boolean LOAD_AS_RESOURCE_BUNDLE = false;
private static final String SUFFIX = ".properties";
} // End of class


The Javadoc comment for the loadProperties() method shows that the method's input requirements are quite relaxed: it accepts a resource name formatted according to any of the native method's schemes (except for package-relative names possible with Class.getResourceAsStream()) and normalizes it internally to do the right thing.

The shorter loadProperties() convenience method decides which classloader to use for loading the resource. The solution shown is reasonable but not perfect; you might consider using techniques described in "Find a Way Out of the ClassLoader Maze" instead.

Note that two conditional compilation constants control loadProperties() behavior, and you can tune them to suit your tastes:

  • THROW_ON_LOAD_FAILURE selects whether loadProperties() throws an exception or merely returns null when it can't find the resource
  • LOAD_AS_RESOURCE_BUNDLE selects whether the resource is searched as a resource bundle or as a generic classpath resource


Setting LOAD_AS_RESOURCE_BUNDLE to true isn't advantageous unless you want to benefit from localization support built into java.util.ResourceBundle. Also, Java internally caches resource bundles, so you can avoid repeated disk file reads for the same resource name.

More things to come

I intentionally omitted an interesting classpath resource loading method, ClassLoader.getResources(). Despite its infrequent use, ClassLoader.getResources() allows for some very intriguing options in designing highly customizable and easily configurable applications.

I didn't discuss ClassLoader.getResources() in this article because it's worthy of a dedicated article. As it happens, this method goes hand in hand with the remaining way to acquire resources: java.net.URLs. You can use these as even more general-purpose resource descriptors than classpath resource name strings. Look for more details in the next Java Q&A installment.

Wednesday, April 23, 2008

MySQL and stored procedures

Takeaway: Some people resisted using MySQL because it had no support for stored procedures. But starting with MySQL 5.0, that changed--now you can do stored procedures in this popular open source database.


MySQL is "The World's Most Popular Open Source Database," at least according to the MySQL Web site. But in spite of this popularity many corporations are resistant to adopting MySQL. There are several reasons for this, from the misguided belief that open source is the software equivalent of a child's wood shop project to the belief that nothing free is ever good. There was, however, one valid complaint against MySQL—unlike its shrink-wrapped counterparts, such as Oracle or DB2, MySQL doesn't support stored procedures.

Make that past tense—the latest developer release, MySQL 5.0, does support stored procedures. If you're not familiar with stored procedures, they are collections of SQL commands and program logic stored on the database server. These stored procedures can then be invoked by application programs thus eliminating the need for programmers with varying degrees of skill to create their own SQL.

Advantages
Stored procedures allow most database access logic to be separated from the application logic. One of the indirect benefits of using stored procedures is that application code becomes smaller and easier to understand. Another advantage of stored procedures is that the SQL can be "pre-compiled" increasing the speed of the application. Because stored procedures contain program logic, more processing can take place on the database server, which can reduce the amount of bandwidth consumed sending data back to the application. Also, when implementing an n-tier application, stored procedures are used to separate the data layer from the server layer.

Security can be another advantage of stored procedures. Applications can be granted execute privileges to the stored procedures, while being unable to access the tables directly. Unfortunately, at this time, MySQL doesn't support "GRANT EXECUTE". That means unless the application has the authority to access a table, then calling a stored procedure that accesses the same table won't work either. It's a good bet that this feature is pretty high up on the "to do" list for a future release.

Standards
Unlike either of the shrink-wrapped Oracle or Microsoft relational databases, which do not follow the current SQL:2003 syntax for stored procedures, MySQL and IBM's DB2 do conform to the syntax. Theoretically this means that, if the database structure is the same, stored procedures written for one will run on the other.

Supported SQL statements
Even though the paint isn't quite dry on MySQL's support of stored procedures, there's enough to get many tasks done, as Table A shows. In addition, the MySQL stored procedure documentation indicates that there may be future compatibility for Oracle's PL/SQL and SQL Server's T-SQL. My general impression of stored procedure support is that it is proceeding slowly in order to avoid any missteps that often plague large software development projects.
Table A
Statement Description
CREATE PROCEDURE Creates a stored procedure, which is stored in the proc table in the MySQL database.
CREATE FUNCTION Creates a user-defined function, essentially a stored procedure that returns data.
ALTER PROCEDURE Alters a previously defined stored procedure that was created using the CREATE PROCEDURE statement.
It does not affect related stored procedures or stored functions.
ALTER FUNCTION Alters a previously defined stored function that was created using the CREATE FUNCTION statement. It does not affect related stored procedures or stored functions.
DROP PROCEDURE Removes one or more stored procedures from MySQL's proc table.
DROP FUNCTION Removes one or more stored functions from MySQL's proc table.
SHOW CREATE PROCEDURE Returns the text of a previously defined stored procedure that was created using the CREATE PROCEDURE statement. This statement is a MySQL extension to the SQL:2003 specification.
SHOW CREATE FUNCTION Returns the text of a previously defined stored function that was created using the CREATE FUNCTION statement. This statement is a MySQL extension to the SQL:2003 specification.
SHOW PROCEDURE STATUS Returns the characteristics of a previously defined stored procedure; including name, type, creator, creation date, and modification date. This statement is a MySQL extension to the SQL:2003 specification.
SHOW FUNCTION STATUS Returns the characteristics of a previously defined stored function; including name, type, creator, creation date, and modification date. This statement is a MySQL extension to the SQL:2003 specification.
CALL Invokes a previously defined stored procedure that was created using the CREATE PROCEDURE statement.
BEGIN ... END Contains a group of multiple statements for execution.
DECLARE Used to define local variables, conditions, handlers, and cursors.
SET Used to alter the values of both local variables and global server variables.
SELECT ... INTO Used to store the indicated columns directly into variables.
OPEN Used to open a cursor.
FETCH Retrieves the next row using the specified cursor and advances the cursor one row.
CLOSE Used to close and open cursor.
IF An if-then-else-end if condition statement.
CASE ... WHEN A case statement conditional construct.
LOOP A simple looping structure; exiting is performed using the LEAVE statement.
LEAVE Used to exit IF, CASE, LOOP, REPEAT and WHILE statements.
ITERATE Used within loops to restart at the beginning of the loop.
REPEAT A loop with the conditional test at the end.
WHILE A loop with the conditional test at the beginning.
RETURNS Returns a value from a stored function.
Stored procedure statements supported in MySQL 5.0

It is important to remember that support of stored procedures in the current incarnation of MySQL isn't as mature as Oracle, SQL Server or DB2. Also remember that it's more important to have a small number of features that work well rather than a ton of features that are, for lack of a better word, flaky. I know that it's an odd concept, but maybe the folks in the open source community have struck upon an idea that was somehow missed by the rest of the world.

Sunday, April 13, 2008

Java 推荐读物与源代码阅读

         

1. Java语言基础
谈 到Java语言基础学习的书籍,大家肯定会推荐Bruce Eckel的《Thinking in Java》。它是一本写的相当深刻的技术书籍, Java语言基础部分基本没有其它任何一本书可以超越它。该书的作者Bruce Eckel在网络上被称为天才的投机者,作者的 《Thinking in C++》在1995年曾获SoftwareDevelopment Jolt Award最佳书籍大奖, 《Thinking in Java》被评为1999年Java World"最爱读者欢迎图书",并且赢得了编辑首选图书奖。作者从1986年至今,已 经发表了超过150篇计算机技术文章,出版了6本书(其中4本是关于C++的),并且在全世界做了数百次演讲。他是 《Thinking in Java》、《Thinking in C++》、《C++ Inside & Out》《Using C++》和 《Thinking in Patterns》的作者,同时还是《Black Belt C++》文集的编辑。他的书被读者称为"最好的Java参考 书……绝对让人震惊";"购买Java参考书最明智的选择";"我见过的最棒的编程指南"。作者的非凡才华,极其跨越语言的能力,使作者被选为Java发 展10年间与Java关系最密切的10个人物之一。
《Thinking in Java》讲述了Java语言的方方面面,很多Java语言的老手都评价"这是一本将Java语言讲得相当丑陋的书"。该书谈及了java语言的很多细节,每一个方面都是相当深刻的。通过本书你可以看到"丑陋的"java语言。
网 络上关于java语言讲解的视频很多很多,其中不凡有垃圾。《翁恺?JAVA语言》可能是你学习java语言基础的唯一选择,该讲座基本按照 《Thinking in Java》这本书讲解,其中不凡有翁老师的很多有意思的笑话。我很幸运学习就是从此视频开始的。内容包括30讲,我总共看了3 遍。
不过,对于初学者我不太推荐使用《Thinking in Java》,我比较推荐Prentice Hall PTR 的  《Core Java 2》国内称为《Java 2 核心技术》,目前是第七版。网络上大家都可以下载到电子版。Oreilly的 《Java in a nutshell》也是一个不错的选择。读完以上两本后,你可以看看翁恺老师的视频,接着可以研究 《Thinking in Java》了。
2. Java数据结构
市面上关于Java数据结构的书本身就很少很少。大致有APress  的《Java Collections》,Jones 和Bartlett 的《Data Structures in Java》、《Object- oriented Data Structures Using Java》以及Prentice Hall 出版的 《Data Structures and Algorithms in Java》 (Dec 19, 2005)还有一本就是 《Data Structures And Algorithms With Object-oriented Design Patterns In Java》。 很幸运我的第一本英文书就是APress 的《Java Collections》(本书在国内可能根本就没有中文版��只能下载英文版了),很不错,讲 得很有条例、很简单,是一本完完全全Java Collections API介绍的书籍,其中不凡有扩展API的例子。这是我推荐你学习java数据结 构的唯一一本好书。其它的Jones 和Bartlett的那两本国内好像有一本中文版,想看你也可以看看。
在学习完API后,你可以看看 java.util包中对应的类了。不过只有在学习过设计模式后你才有可能完全理解整个Java Collections Framework。 Java Collections Framework使用了很多著名的设计模式如:迭代器(Iterator)模式,工厂方法模式、装饰器模式、适配器 模式等等。通过研究java.util包中数据结构的源代码,你可以知道臭名昭著的Properties类的设计了,同时可能基本具备设计简单
2
的数据结构的能力了。
所谓学习无止境,学习完Sun提供了Java Collections Framework后,你可以研究Apche的另一个Java Collections Framework,很有意思哦。互为补充的两个Framework。
在大家学习、研究Java Collections之前,我提示一下Java Collections主要包括以下三部分:接口(Interface)、实现(Implemention)和算法(Algorithm)。
1. 接口主要有List、Set、Queue和 Map。List 、Se t和Queue是 Collection接口的子接口。
2.  实现主要是实现这些接口的具体类。如实现List接口的ArrayList、LinkedList、Stack和Vector;实现Set接口的 HashSet、TreeSet 和LinkedHashSet;实现Queue接口的PriorityQueue、SynchronousQueue等 等;实现Map接口的HashMap、TreeMap、Hashtable、Properties、WeakHashMap等等。
3. 算法主要是由Arrays类和Collections类提供的,它是整个Java Collection Framework算法的核心。支持各种类型的排序,查找等常用操作。
Java Collections中包含两个版本的数据结构,主要是原先的支持同步的数据结构和后来不支持同步的数据结构。
Java Collection Framework在使用Comparator和Comparable接口支持排序。同时提供新旧两个版本的迭代器Iterator和Enumeraton,以及它们如何转换等等。
在java.util包中的Obserable接口和Observer类是考察者模式的核心。
……
3. Java IO
市 面上关于IO的书籍也仅仅只有Oreilly出版社的两本,都是Elliotte Rusty Harold的著作。两本书的风格基本一致,推荐阅读是第 一版的《Jvava I/O》,讲得比较浅显,内容相对比较集中,实例也很多。第二版今年5月国外才出版,很有幸我在网络上下载了第二版,讲得极其详细 ��726页的大块头(我化了两个星期),这次将NIO和IO和在一起,还包括J2ME部分的,不过串口、并口通信部分好像类库支持不够,自己不能实际操 作。
与第一版的《Jvava I/O》一起的Oreilly还有一本《Jvava NIO》,也是很不错的哦。
大家在依次阅读完《Jvava I/O》以及《Jvava NIO》后,可以研究java.io包中的源代码了。在大家研究源代码前我给点提示:
Java的io包主要包括:
1. 两种流:字节流(byte Stream)和字符流(character stream),这两种流不存在所谓的谁代替谁、谁比谁高级之说,它们互为补充,只是侧重点不同而已。
2. 两种对称:1.字节流、字符流的对称;2.输入、输出的对称。
3. 一个桥梁:将字节流转变为字符流的InputStreamReader和OutputStreamWriter。
其中必须注意:
1. PipedInputStream和PipedOutputStrem是两个比较有趣的类。
2. 支持Buffered的流是我们经常使用的类。
3. 装饰器(Decorator)模式在java最著名的应用就是用于io的设计。仔细研究各个Filter流与具体流的关系,多看设计模式的书籍。相信你会有所所获。
4. 学习好io包,是研究net包,rmi包……的基础哦!
3
4 . Java数据库
数 据库的书籍太多太多了,也是太烂太烂了!这方面的书我基本都研究过,推荐的你就看看Apress的 《JDBC Recipes A Problem Solution Approach 》很不错,国外2005年底才出版,(国内好像没有中文版,不过 出了中文版也不一定值得看��国内经常将国外的书翻译得一塌糊涂、不堪入目)不过我们真的很幸运,网络上有电子版的。值得一看。推荐我看的第一本比较满意 的��Wiley出版的《Java Database Bible》,讲得很不错!
Sun公司自己的关于JDBC API介绍的那一本《JDBC API Tutorial andRefernece》也不错。我第二本JDBC的就是研究的这套API。
不过目前这些书都是一些相对比较浮浅的API应用的书籍。有机会我会给大家带来介绍JDBC API以及JDBC实现内部细节的书!我尽快努力,同时希望得到大家的支持!
顺便给学习JDBC的朋友一点提示:
JDBC的学习和使用主要是这套API,其使用过程也是极其简单,下面是使用JDBC的一般流程:
1. 加载某个数据库的驱动(Driver类),通常使用Class.forName("驱动的类名");
2. 连接数据库��
Connection con = DriverManager.getConnection(url,username,password);
3. 得到会话��Statement stmt = con.createStatement();
4. 执行操作��Result rs = stmt.executeQuery("SQL查询语句");
5. 处理结果��
while(rs.next()){
String col1 = rs.getString(1);
……
}
简单吧!整个JDBC中可以变化的一般是:
1. 可以由Connection对象创建Statement、PreparedStatement和CallableStatement创建三种类型的Statement。
2. 可以创建多种类型的ResultSet:支持单向移动和个自由移动;可更新的和不可更新的;支持不同等级的交易的…..
3. 数据输入的批处理。
4. 结果集中特殊类型(Blob、Clob、Arrary和Ref、Struct)列的操作。
5. 这些特殊类型的录入数据库。
6. javax.sql包中特殊结果集(CachedRowSet、JdbcRowSet、WebRowSet)的操作。
7. 其它的就是一个DataSource了,也很简单!一个J2EE中的被管理对象
简单吧!相信大家很快就会征服JDBC。
5. Java 网络编程
网络编程��一个神秘的、充满挑战的方向。不过在谈Java网络编程之前首先感谢Sun公司的开发人员,因为它们天才的设想,充满智慧的架构,使广大java程序员学习java网络编程变得异常简单。
Java 网络编程方面的书,我推荐O'Reilly的《Java Network Programming》,目前已经第三版了,以前的版本市面上肯定有!网络上 早有第三版的电子版,国外2004年出版,706页哦!讲得很全,比较深入,太深入的可能由于Sun有些东西没有完全公开,所以也就不好讲了,有兴趣的可 以下载看看!第二本还是O'Reilly 1998年出版的《Java distributed computing 》,基础部分写得比较详细,后面的 实例还是值得研究的。
4
在大家阅读这些书之前,给大家一点提示:
java网络编程其实相对比较简单,入门也很快很快。java网络编程主要包括两个部分:1.Socket;2.URL部分。不过第二部分也完全建立在第一部分的基础上。
1. Socket包括客户端的Socket和服务器端的ServerSocket。还有就是DatagramSocket和DatagramPacket,它对应于UDP通信协议。 总之,Socket部分是建立其它高级协议的基础。
2. URL 类是一个网络资源定位器,通常和具体的网络协议如HTTP,FTP,Telnet……相关。通过该类可以连接网络上的资源,通过其openStream可 以以io包中的流(InputStream)的形式读取网络资源;通过其OpenConnection方法,可以打开一个连接,在此连接上可以不仅可以完 成读的操作,还可以完成写的操作。
Java的网络编程大体包括以上两部分。网络编程和IO以及多线程部分非常密切,在学习此部分前大家一定对这两部分了解比较透彻。
学 习了以上部分你可以研究java.net包中的与此相关的源代码了!研究所有的源代码还为时尚早。在整个net包中包含: ContentHandlerFactory、URLStreamHandlerFactory、URLStreamHandler、 URLClassLoader等辅助类,它们构成了java.net网络编程的框架,通过研究其源代码,你不仅可以快速理解java.net包,还可以为 以后扩展该包打下基础,甚至可以将此思维方式运用到自己的项目中。
到此为止你对java.net包应该才了解60%,还有一部分你可以使用 JDecompiler之类的反编译软件打开你JDK安装目录下\jdkxxx\jre\lib目录中的rt.jar,用WinRAR之类的软件打开它的 sun.net包,反编译所有的文件,它是URL类工作的细节。当研究完该sun.net包,你就会对整个网络编程很熟悉很熟悉了。
一切看起来我 们已经对网络编程很精通了。其实不然,刚刚开始而已,要想深入,请继续吧!网络上很多优秀的网络编程库甚至软件可以为我们"添加功力"。如Apache的 HttpCore和HTTPConnection 是两个和HTTP协议相关库;JGroups是研究分布式通信、群组通信的必读库;接着我们可以研究 P2P的软件包,如Sun公司的JXTA,它可能是java平台点对点通信未来的标准哦!接着你可以研究成熟得不得了,使用极其广泛得P2P软件 Azureus!www.sourceforge.net可以下载到!
千里之行始于足下!Just do it !(目前我也只研究了net包, 其它的会在不久的将来继续深入。Sun公司因为某些原因没有公开net的其它实现细节,在其允许将其源代码以文字的形式加以研究,以及允许将其没有公开的 实现写入书中时,我很希望能出一本java网络编程的书籍,以飧广大读者!!)
6. Servlet和JSP
Servlet、JSP的书 也是满地都是!值得推荐的也仅仅两三本。实推Addison Wiley的《Servlets and JavaServer pages : The J2EE Technology Web Tier》,又是一本很厚的哦!国外2003年出版、784页,讲得比较全,例子也很多,特别是第八章 Filter,举了几个不错的例子。其它所有我看到的关于Servlet和JSP的书都没有如此深入的!(可能有我没有看到而已)。O'reilly的 《Java Servlet Programming》和《Java Server Pages》相对比较好懂一些,可以读读!
在大家学习Servlet和Jsp之前我还是要提醒一下:
本质上说Servlet就是一个实现Servlet接口的、部署于服务器端的服务器端的程序罢了!它可以象写其它任何java应用程序一样编写,它可以操作数据库、可以操作本地文件、可以连接本地EJB……编写Servlet程序的一般流程为:
1. 继承一个HttpServlet类;
2. 覆盖其doGet、doPost方法;
3. 在覆盖方法的内部操作方法参数HttpServletRequest和HttpServletResponse。
4.  读取请求利用HttpServletRequest。利用HttpServletRequest你可以操作Http协议的协议头、可以得到请求的操作方 法、可以得到请求的路径、可以得到请求的字符串、以及和请求客户相关的信息,更主要的你可以得到Cookie和HttpSession这两个对象。
5. 利用Cookie你可以操作"甜心"对象或者将其写入HttpServletResponse中。
5
6. 向客户输出信息可以使用HttpServletResponse。使用HttpServletResponse可以写入各种类型的协议头、可以增加Cookie、可以重定向其它URL、可以向客户发送Http协议的状态码。
7. 利用HttpSession在会话内完成你想实现的任何功能。
同时Servlet还提供了一些事件和事件监听器(简单的观察者模式而已)。还有就是过滤器(Filter)和包装器(ServletRequestWrapper、ServletResponseWrapper)��简单的流的使用和装饰器模式的使用。
学习Sevlet、JSP必然要部署到服务器中,记住通常文件部署的步骤和参数的设置以及在程序中如何使用就可以了。
完全理解Servlet后,学习jsp相对比较容易了!Jsp完全建立在Servlet的基础上,它是为了迎合那些喜欢在Html文档中嵌入脚本(如:PHP之类的网页编程语言)的程序员的需要罢了!学起来也相当的容易!
一 切看起来似乎那么的风平浪静,简单好学!简单的表象背后有其复杂的机理。要想对Servlet和Jsp彻底研究,你得研究Tomcat等开源软件的具体实 现。它无非就是一个服务器,在客户利用网页通过HTTP协议向服务器发送请求后,服务器将此HTTP请求转化为相应的 HttpServletRequest对象,调用你编写的Servlet罢了,在你的Servlet中你肯定操作了此 HttpServletRequest了吧,同时操作了HttpServletResponse了吧,服务器就将此 HttpServletResponse按照HTTP协议的要求利用HTTP协议发送给你的浏览器了!在服务器端的Jsp网页在被客户请求后, Tomcat会利用编译软件,使用javax.servlet.jsp包中的模板,编译此jsp文件,编译后就是一个Servlet!以后的操作和 Servlet完全一样哦!
在Servlet和Jsp的基础上出现了,所谓的高级技术:JSTL,Struts……无非就是一些标签和MVC模式的使用。
继续前进吧!胜利就在前方!!
7. 多线程
一个看起来很神秘,却很容易上手、很难精通的方向!
我 推荐两本我感觉很好的书籍。首先是我第一本能上手看的这方面的书,Sams 1998年出版的《Java Thread Programming》,写得 暴好,很容易读懂,我有空还时常看当时的笔记!要知道怎么好你自己看吧!第二本OReilly三次出版的《Java Threads》,最新是2004 版,国内好像有中文版,推荐你还是看英文版的吧!书中谈到了与多线程相关的N个方向,如IO、Swing、Collection等等。
给大家一点 提示吧!java类库中与多线程相关的类不是很多,主要有:Thread、ThreadGroup以及ThreadLocal和 InheritableThreadLocal四个类和一个Runnable接口;关键字synchronize、volatile ;以及Object 对象的wait、notify、notifyAll方法!
1 Thread是多线程的核心类,提供了一系列创建和操作多线程的方法。
2 ThreadGroup是一个管理Thread的工具类。
3 ThreadLocal和InheritableThreadLocal为Thread提供了一个类似保险箱功能的存储线程对象的类!
4 Runnable不用说了吧!
5 synchronize 是同步方法和同步块的核心哦!多个线程调用此方法时,只有一个线程可以使用此方法,其它方法阻塞,从而保证被操作对象内部状态完整性。某个线程调用带有 synchronize的方法或块时会得到该对象的对象锁,完成块中的操作后释放此对象锁,从而其它对象可以继续操作。
6 wait、notify、notifyAll提供了有效的等待/通知机制。Java语言中每一个对象都有一个休息室,任何线程在其操作的对象的状态不满足的情况下,在该对象的休息室中
6
休息,释放对象锁;当其它线程操作该对象后,唤醒休息室中的线程,它们再检查条件,当条件满足后,执行相应的操作。
多 线程大致就这么多基础的!简单吗!这对于一个真正的程序员应该是不够的,真正对多线程要有所掌握,请您研究java.util.concurrent包 吧!大师Doug Lea的作品,原先是一个开源的一致性编程的库,后来被Sun公司并入java类库。作者的网站上也有另外一个版本的该类库!值得研究 的好东西!Hibernation、OpenJMS等开源软件都使用了此包!
8. 设计模式
谈到设计模式很多人多会推荐GOF的那本,该书在Amzon上是五星级的推荐书籍。不过对于学习java没多久的、特别是java初学者,我很不推荐这本书。主要是该书的例子基本都是C++的,很多细节没有讲述得足够清楚。
我给大家推荐的第一本是阎宏博士的《Java 与模式》,它是第一本中国人自己写的关于设计模式的书籍,写的比较有趣,融合了很多中华民族的文化和观念,例子、类图都比较多,且相对简单!非常不错的入门书籍��又是大块头哦!
其次我推荐Wiley出版社出版的《Pattern In Java》一套三本,我才看了第一本,好像第二本不怎么样,第三本还不错!
第三本是中文翻译版的关于多线程模式的(很难得的中文翻译版)中国铁道出版社2003年出版的《Java多线程设计模式》,将多线程模式讲得非常浅显,配有大量的图例,每章都有习题,最后有答案!我研究多线程模式就是由它开始的!
第四本,今年出版的Head First系列的《Head First Design Pattern》,秉承Head First系列图书的优点,大量的类图、丰富的实例、有趣的注解,值得购买!
其 次在J2EE方向你可以研究阅读Addison Wesley 2002年出版的 《Patterns of Enterprise Application Architecture》,众多大腕的作品,讲企业消息集成的!Sun提供 的《J2EE PATTERNS SL500》也很好!晚了推荐那一本Amzon 4星半的《Holub on patterns》,大师的作品,提供 了,很值得研究的例子,不过对上面四本不是很熟悉的读者,最好不要读它!可能会让你比较累!
我学习设计模式经过一段很曲折的路线,前前后后大约看 了20本,阎宏博士的《Java 与模式》我看了4遍,还排除我第一次基本没看懂的看!记得研一时老师给我们讲了GOF的那本,作为选修课,我和它们计算 机系的硕士、博士们一起,到最后一个班40-50个人,不超过3个人明白,我也没有明白任何一点(基础差吧��主要我对C++语言一点都不了解),凭我不 伏输的性格,我认为我对java语言理解还可以,我就借了《Java 与模式》,结果还是基本没看懂。很有幸的是读研三时,听过了上交大饶若楠老师关于 Java OOP语言的讲座,我懂了组合书籍模式等三种设计模式后,对其它模式有了强烈的兴趣和要征服它的愿望!工作后我买的第一本就是《Java 与模 式》,第一遍花了2个月研究了这个1000多页的大块头,后来第三遍15天左右就可以搞定,笔记记了一大本!从此一发不可收拾。
选对书、埋头研究。相信很快就会入门的!
学 习Java语言8个简单的部分,这只是我们研究Java语言的开始!这些都懂了充其量一个java程序员而已,后面的路很长很长!我们可以继续研究数据库 实现的源代码、Servlet服务器的源代码、RMI、EJB、JNDI、面向方面编程、重构、ANT工具、Eclipse工具、Spring工具、 JBoss、JOnAS、Apache Geronimo等J2EE服务器!研究了这些你可能会成为一个出色的J2EE Architecture!你可 以继续研究剖析器、编译器、JNODE(java写的操作系统)……
感谢大家有此耐心,听我罗罗嗦嗦大半天!感谢大家的阅读,感谢群里的朋友!这篇文章主要应群
7
里朋友的呼声��不知道如何选书、不知道从何看起!大半天的功夫完成赶此文章,字句上难免有失误,同时由于能力有限不凡有错误!请阅读后批评指正!
上面基本是我研究java语言的顺序,以上书籍都是我阅读过的,不存在替任何出版社宣传的成分!有的方法可能不适合你,假如你能收获一点,两点甚至更多,请你不要吝啬推荐给你的朋友��共同学习!
感谢大家的阅读;感谢互联网的设计者;感谢java的设计师;感谢www.open-open.comwww.sourceforge.net网站!

Thursday, April 10, 2008

Code conversion in PHP

    In html, some special character will be encode to
        character                html
         space                   &nbsp;
         "                       &quot;
         &                       &amp;
         <                       &lt;
         >                       &gt;
        
    In html query string, the special character has to be encode to the pattern like %<ASCII>, for instance:
       character                query string
         space                    %20
          &                       %28
          '                       %29
    In PHP, those character has to be escaped by slash(/)
   
    PHP provides a serial methods to convert those.
   
    html_entity_decode()          Converts HTML entities to characters      4
    htmlentities()                 Converts characters to HTML entities     3
    htmlspecialchars_decode()     Converts some predefined HTML entities to characters     5
    htmlspecialchars()             Converts some predefined characters to HTML entities     3

Tuesday, April 8, 2008

Installing MySQL on Solaris 10

"Configuring MySQL to Use With Service Management Facility (SMF)", by William Pool (Puddle), October 2005.  From http://www.sun.com/bigadmin/content/submitted/mysql_smf_tip.html

The Solaris 10 OS uses the Service Management Facility (SMF) to handle services.  Traditional means like /etc/rc?.d scripts still work, but as a legacy means.  To take advantage of the SMF in the Solaris 10 OS using MySQL, follow these steps.  (Note: Read the scripts and "change" the path of MySQL or MySQL's data-directory accordingly!)

If you haven't initialized the MySQL database, do that first:

/opt/sfw/bin/mysql_install_db

This will install the database into /var/mysql to override that use:

/opt/sfw/bin/mysql_install_db -ldata=/opt/sfw/var/mysql

Note: If you change the location, change the information below!

First create a mysql group:

/usr/sbin/groupadd mysql

Then create the mysql user:

/usr/sbin/useradd -s /bin/false -g mysql \
   -d /var/mysql -c "MySQL User" mysql

Create a service manifest file that contains the following:

cat > /var/svc/manifest/network/mysql.xml <<'EOF'

<?xml version='1.0'?>
 <!DOCTYPE service_bundle SYSTEM
 '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<!--  William Pool (Puddle) 02/05
      Service manifest for MySQL
      E-mail: puddle@flipmotion.com
 -->

<service_bundle type='manifest' name='mysql:mysql'>

 <service
  name='network/mysql'
  type='service'
  version='1'>
 <create_default_instance enabled='false' />
  <single_instance />

  <dependency name='fs'

   grouping='require_all'

   restart_on='none'

   type='service'>

  <service_fmri value='svc:/system/filesystem/local' />

   </dependency>

  <dependency name='net'

   grouping='require_all'

   restart_on='none'

   type='service'>

  <service_fmri value='svc:/network/loopback' />

 </dependency>

 <exec_method

  type='method'

  name='start'

  exec='/lib/svc/method/svc-mysql start'

  timeout_seconds='-1'>

 <method_context>

  <method_credential user='mysql' group='mysql' />

  </method_context>

 </exec_method>

 <exec_method

  type='method'

  name='stop'

  exec=':kill'

  timeout_seconds='-1'>

 </exec_method>

 <exec_method

  type='method'

  name='restart'

  exec='/lib/svc/method/svc-mysql restart'

  timeout_seconds='-1'>

 </exec_method>

 </service>

</service_bundle>

EOF

 

Now create your "Service Method File" in /lib/svc/method called svc-mysql:

#!/usr/bin/sh

#

#        William Pool (Puddle) 01/05

#        SMF Method file for MySQL

#        E-mail: puddle@flipmotion.com

#

# This uses Sun's default MySQL packages

# SUNWmysqlu SUNWmysqlr

# Modify accordingly!

#

# NOTE: Make sure DB_DIR is owned BY the mysql

# user and group and chmod 700.

#

. /lib/svc/share/smf_include.sh

DB_DIR=/var/mysql

PIDFILE=${DB_DIR}/`/usr/bin/uname -n`.pid

 

case "$1" in

 start)

  /usr/sfw/sbin/mysqld_safe --user=mysql \
  --datadir=${DB_DIR} --pid-file=${PIDFILE} \
  > /dev/null &

 ;;

 stop)

  if [ -f ${PIDFILE} ]; then

   /usr/bin/pkill mysqld_safe >/dev/null 2>&1

   /usr/bin/kill `cat ${PIDFILE}` > /dev/null 2>&1 \
    && echo -n ' mysqld'

   fi

 ;;

 'restart')

  stop

  while pgrep mysqld > /dev/null

  do

   sleep 1

  done

  start

 ;;

 *)

  echo ""

  echo "Usage: `basename $0` \
    { start | stop | restart }"

  echo ""

  exit 64

 ;;

esac

Now fix the permissions for the two files created:

chown root:bin /lib/svc/method/svc-mysql
chmod 555 /lib/svc/method/svc-mysql
chown root:sys /var/svc/manifest/network/mysql.xml
chmod 444 /var/svc/manifest/network/mysql.xml

Fix permissions on the MySQL data directory:

chown -R mysql:mysql /var/mysql
chmod -R 700 /var/mysql

Import the service into the service repository:

svccfg import /var/svc/manifest/network/mysql.xml

Enable the service:

svcadm -v enable mysql

 

Google+