... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2009-11-24

JUnit 4.5.0 vs. @BeforeClass

The JUnit (4.5.0) documentation states that if you annotate a static method with @BeforeClass, it will be called after any similarly annotated methods in superclasses. This normally works, but if the method in the subclass happens to use the same name as that in a superclass (setUpClass for example), the superclass method will not be invoked first.

2009-11-10

Protovis

Protovis is another JavaScript visualization tool.

2009-11-07

JsTestDriver

JsTestDriver is an Eclipse-friendly framework for unit-testing JavaScript across multiple browsers.

2009-11-03

SQL Server vs. Identity-only Tables

Using SQL Server, if you want to insert a row into a table that contains only an identity column, you can do it like this:

INSERT INTO mytable DEFAULT VALUES

This circumstance is very unusual, but I have run into it twice... and I forgot how I solved it the first time.

2009-10-30

gRaphaël

gRaphaël is a JavaScript charting library.

2009-10-27

RAP and qooxdoo

RAP (Rich Ajax Platform) is Eclipse's GWT-like entry into the rich web application space. It uses qooxdoo on the client-side. Qooxdoo itself uses Python in its native tool chain. There is also a user-contributed GWT-alike called QWT (qooxdoo Web Toolkit).

2009-10-24

JavaScript InfoVis Toolkit

The JavaScript InfoVis Toolkit provides some nice web client-side hierarchy visualizations.

2009-10-22

Jitterbit

Jitterbit is an open source integration tool in the tradition of Kettle or QueryJoiner.

2009-10-21

SQL Server vs. Schemas

SQL Server added schema support in SQL Server 2005, but there are still some issues. There appears to be no direct way to set the implicit schema for a session. It would be nice to have something like:

USE database.schema

Alas, no such functionality exists (yet). Someone has sent Microsoft a suggestion along these lines.

There are a couple of workarounds. First, you can change the default schema for a user in a particular database using the User Mapping page in Management Studio. Equivalently, you could issue commands like:

USE myDatabase
ALTER USER myUserId WITH DEFAULT_SCHEMA = mySchema

To change the default schema for a particular session, you could try:

EXECUTE AS USER = 'mySchemaUser'

where mySchemaUser is a user who is already mapped to the desired schema. Since this approach uses impersonation, you might run into a rights issue. A common case is to target the dbo schema (through the dbo user). The exhibited command works when the original user has the db_owner role.

2009-10-16

Open Source IntelliJ

Jetbrains has created an open source community edition of IntelliJ IDEA.

2009-10-10

Head in the Cloud

I migrated my technical diary blog onto Blogger, mainly so that I can edit it from multiple locations.

A lot of older material has not been migrated since I've only been separating the generic technical content from proprietary and personal stuff in the last couple of years. Many links are broken, especially to supporting content generated by me. I'll figure out what to do about this later.

Oh... and should you happen to be editing a Blogger export XML file with OxygenXML, and Oxygen offers to reformat the file, the correct answer is "no". (Although I'm sure that tweaking options like Preserve text as it is would do the trick.)

2009-10-07

Git SVN versus Empty Directories

Git only tracks files. SVN also tracks directories. So if you are using git svn to interoperate between the two, there can be problems. If you delete a bunch of directories in a git commit and then dcommit that change up to SVN, the directories themselves will not be deleted from the SVN repository.

You can work around this problem by including the --rmdir switch on dcommit. This will delete any empty directories upon commit. If you do not care about empty directories, this works fine. But if you do care about empty directories (maybe a build script depends upon their existence), there does not appear to be a satisfactory prepackaged solution.

2009-09-29

JIRA vs. Cookies

Under some circumstances, I have seen JIRA fields disappear completely from pages, along with the "show" buttons that are supposed to reveal them.  The solution is to clear your cookies.

2009-09-14

H2

 H2 is the successor to Hypersonic DB, by the original author.

2009-09-11

Git SVN versus SVN relocate

git svn does not have an explicit feature to deal with the relocation of a Subversion repository.  I'm not sure if this was a good design choice, but git svn writes the SVN repository URL and revision number into each commit.  git svn seems to get confused if you just do the obvious thing and change all occurrences of the old repository URL to the new one.

You seem to have two choices.  The first is to point git svn to the new repository, but tell it to rewrite the URL when storing it in git.  This is accomplished easily by adding a rewriteRoot directive to the appropriate svn-remote section of the Git config:

[svn-remote "svn"]
	url = new-svn-url
	rewriteRoot = old-svn-url

Note that the log entries for any future commits in the Subversion repository will use the old (rewritten) name, so you must be willing to accept that.

If you want to update all of the URLs, the process is a bit more complex, something like:

# rewrite all of the commit comments
git filter-branch --msg-filter 'sed "s.git-svn-id: old-svn-url.git-svn-id: new-svn-url."' \
  $(git for-each-ref --format "%(refname)")

# blow away the cached SVN information
rm -rf .git/svn

# change all of the old SVN URLs in the config to the new URL
cat .git/config | sed 's.old-svn-url.new-svn-url.g' >.git/config2
mv .git/config2 .git/config

# rebase
git svn rebase

# delete the old objects that were rewritten
# rm -rf .git/refs/original
# git gc

I actually tried this as an experiment.  The message rewriting took a fair bit of time, but nowhere near the length of time for a clone from scratch.  It all went well but the next time I did a git svn fetch, it took longer than I was willing to wait before killing it.  Also, the cached SVN information did not appear to be rebuilt correctly.  Maybe I should have waited longer (than an hour or so)?  And of course all of the SHAs changed because I had rewritten the commit logs.

I think the first solution is better.  In future I will probably build any git svn repositories using a generic (rewritten) URL for the source right out of the box.  Maybe an URN is better.

This issue seems to cause quite a bit of angst in the git/SVN community.  Various workarounds have been proposed.  See, for example, GitSvnSwitch.

2009-08-29

Functional Programming Interview Question

I was reading a blog on fsharp.it that concerned a functional programming interview question. The challenge was to write a Haskell program that count occurrences of words in a text file. The blog posting exhibited an F# program to solve the problem, and briefly spoke to the comparison between functional and imperative style.

From time to time I like to tackle these toy problems in Mathematica. Mathematica is neither functional nor imperative, but rather is based upon pattern transformations. My solution to the programming problem in Mathematica was this:

{
  Import["http://www.starling-software.com/employment/input.txt", "Lines"],
  "NUMBERS",
  {"NUMBERS" -> {}, "ANIMALS" -> {}}
} //. {
  {{}, _, cs_} :> (cs /. (a_ -> b_) :> (a -> Tally@Sort@b)),
  {{c_, ws___}, _, cs:{___, c_ -> _, ___}} :> {{ws}, c, cs},
  {{w_, ws___}, c_, {cs1___, c_ -> {seen___}, cs2___}} :> {{ws}, c, {cs1, c->{w, seen}, cs2}}
}

The output from this code is:

{NUMBERS->{{one,2},{seven,1},{six,2},{three,2},{two,1}},ANIMALS->{{cow,1},{horse,2},{moose,1},{sheep,1}}}

This code uses an idiom in Mathematica that, without getting into details, repeatedly transforms an initial state until a desired final state is reached. If you know the idiom, the transformation is expressed fairly directly. If you don't know the idiom, the code is gibberish and looks like I'm trying to program without using identifiers.

All of this raises interesting questions about conciseness in programming. Functional code (and transformation code) is often radically shorter than an imperative equivalent. However, readability can suffer drastically, especially if the reader has not internalized the idioms used. It is going to be interesting to see how the current wave of interest in functional languages impacts the mainstream.

2009-08-28

JBroFuzz

Jonathan Kohl has had a great experience with JBroFuzz.  He said that it found fuzzing-type bugs that slipped through penetration testing, security testing, static analysis tools, walkthroughs and defensive coding.  One must consider, however, the user of the tool as well...

ADO Unwelcome Asynchronous Statement Execution

Using ADO, if you use Command.Execute to execute a statement that does not return a result set, then that statement will be executed asynchronously.  The function call returns immediately.  I suppose this behaviour is defensible because the return value of the function is a recordset whose status you can query.  However, if you use the flag adExecuteNoRecords and do not specify any of the flags adAsyncExecute or adAsyncFetch or adAsyncFetchNonBlocking, then you might expect the command to execute synchronously.  In fact, it does not.  The documentation was no help -- through experimentation, I found that I could achieve synchrony by calling NextRecordSet on the returned recordset.  I could have just accepted the asynchronous behaviour and blocked until I received a completion event, had I not been using JScript that cannot interact with ADO events.

It seems questionable that Command.Execute executes asynchronously by default.  But it is negligent that none of the ADO documentation even hints that this is the case, let alone lacks any advice on how to perform synchronous operations.

2009-08-06

Subtle Eclipse and OSGI Plug-In Dependency Problems

Using Eclipse 3.4.2, I found a couple of nasty bugs involving package dependencies.  Let's say I have the following situation:

  • two plug-ins plugin.a and plugin.b
  • plugin.a exports the package a.ui and has a non-exported package a.model
  • a public class, a.ui.Ui, has a method with the signature a.model.Model getModel()

In plugin.b, there is some code that looks like this:

a.ui.UI ui = ...;
if (ui.getModel().hasSomeProperty()) ...

The Eclipse compiler accepts this code.  It should not, since ui.getModel() returns an object of type a.model.Model, and the a.model package is not exported from the plug-in.  In fact, if I rewrite this code like this...

a.ui.Ui ui = ...;
a.model.Model model = ui.getModel(); // error flagged here
if (model.hasSomeProperty()) ...

... then Eclipse will complain about the second line, saying that a.model.Model is not visible.  It will offer a quick fix to export the a.model package from the plug-in.

Okay, so the compiler doesn't catch this.  Big deal!  You'll find out about your problem when the OSGI run-time tries to load the a.model.Model class, right?  Wrong!  OSGI will sometimes catch the error, and sometimes not.  Specifically, if the class a.model.Model is loaded for the very first time by code that exhibits this error, then OSGI will correctly identify that an access rule has been broken.  But if the class has already been loaded, then OSGI does not perform access checking at all.  Once a class is loaded, then that class can be accessed by any bundle that depends upon the containing bundle -- whether or not the containing package is exported.  So much for OSGI security!

This combination of bugs has an insidious effect to which I fell victim.  In my case, the code was "broken" but it "worked" because the affected class had already been loaded long before the code was invoked.  I made an apparently minor change to the affected class and suddenly a mysterious ClassNotFoundException appeared at runtime (the change had subtly altered the class-loading order).

I'm more worried about situations where the class-loading order is sensitive to actions taken by the user.  If the user performs actions in one order, everything works.  If the user tries a different order, then ClassNotFoundException.  I suppose this occurrence is rare enough that we don't have to concern ourselves about it (famous last words).

Another argument in favour of the Law of Demeter ;)

2009-07-10

Unicode Converter

There is a nifty Unicode to (fill in the blank) converter online: ishida Unicode Code Converter.

7-Zip vs UNC

Using 7-Zip 4.23, I got an error whenever I tried to save an archive using a UNC pathname that contained a dash.  7-Zip would report "System Error" and "Not Implemented".  Take out the dash.

2009-07-06

SBT

SBT (Simple Build Tool) is an internal Scala DSL internal for building Scala projects.

2009-06-22

Infinitest

Infinitest is an Eclipse plug-in that runs JUnit tests incrementally and continuously as you edit the classes under test.

It is a fantastic idea -- if it worked.  Unfortunately, it is not quite working yet.  Infinitest would find failures in my sandbox projects, but none in our main code base.  Maybe it cannot follow plug-in references yet?  The Eclipse error log always reports "No tests found to run for change []".

2009-06-18

Shrinking SQL Server Log Files

In SQL Server, the transaction log files grow unboundedly until you take some action.  To completely discard old transactions, perform the following steps in the database in question:

backup log databaseName to disk='nul:'
dbcc shrinkfile('logical log file name', 64)

If you actually want to save the contents of the transaction log, use a better pathname than nul.  If you do not know the logical log file name, execute this query:

select * from sys.database_files

In practice, I have found that you may have to run the BACKUP LOG command a few times to get the file to shrink down significantly.

2009-06-16

SQL Server 2005 vs Table-valued Functions

Experimentation has revealed that SQL Server 2005 will sometimes come up with a better query plan if you express joins using IN clauses than if you express the same joins explicitly.  For example:

SELECT
  ...
FROM dbo.fnProduction(...) AS prod
INNER JOIN dbo.tmpProjectFilter AS filter
  ON filter.projectId = prod.projectId
  AND ...

expresses a join between a normal table and a non-procedural table-valued function (i.e. pure query).  It runs quite slowly.  But if you re-express the query thus:

WITH
  filter AS (
    SELECT
      projectId
    FROM dbo.tmpProjectFilter
    WHERE ...
  )
SELECT
  ...
FROM dbo.fnProduction(...) AS prod
WHERE prod.projectId IN (SELECT * FROM filter)

... it runs faster.  It would seem that the latter form is doing a better job than the former when injecting the relevant query conditions into the table function.

This is a tool to consider when "optimizing" "declarative" SQL.

Actors... Dynamic Typing Redux?

I was reading the chapter in Programming In Scala that introduces actors.  It noted that it is a good idea to use named types for messages as opposed to basic types like tuples, arrays and lists.  This makes it easier to locate an actor who could possibly process the message.  Sound advice.  However, I was struck by the fact that if you expose Actors as part of an API, that part becomes effectively untyped (or "duck typed" in popular parlance).

I was struck further by the fact that almost all of the Erlang code to which I have been exposed uses tuples with wild abandon.  Of course, Erlang is mostly untyped so that should be no surprise.  Scala, at least, offers machinery to prevent dynamically typed signatures from escaping a module boundary (for example, by making sure an implementation has-a actor instead of is-a actor).

As a final bit of irony, I observe that Smalltalk's message selector syntax offers a pretty decent solution for identifying objects that can handle (synchronous) messages -- provided you choose a name more distinctive than at: or at:put:.  The irony lies in the fact that Smalltalk is frequently held up as the prototype for duck-typing.  I wonder if Smalltalk's message selector syntax arose to solve the very problem of searching for methods?

2009-06-13

Say "No" To Identifiers

A colleague of mine was recently faced with a large refactoring task that included changing the names of lots of program elements. When he was done, he swore that he would never name anything again.

When thinking about that statement, I wondered just how far you could get without using any identifiers in a Java program. As you might imagine, I didn't get that far. However, the result was still amusing (for me, at least). What follows is a fairly obscure implementation of "Hello, world". Be warned that this source code crashes the CheckStyle plug-in in Eclipse...

import static java.lang.Class.*;
import static java.util.Arrays.*;

public class _ {

    public static void main(String[] __) throws Exception {
        ________ _ = new ________();
        _._().__().__().__().__().__().__()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._().___()._().__().__().__().__().__().__()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._().___()._().__().__().__().__().__().__()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._().___()._().__().__().__().__().__().__()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._().___()._().__().__().__().__().__()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._().___()._().__().__()
                .__().__().__().__()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._().___()._().__().__().__().__().__().__()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._().___()._().__().__().__().__().__().__()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._().___()._()
                .__().__().__().__().__().__()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._().___()._().__().__().__().__().__()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._().___()._().__().__().__().__()
                .__().__()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._().___()._().__().__().__().__().__()
                .__()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._().___()._()
                .__().__().__().__().__().__()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._().___()._()
                .__().__().__().__().__().__()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._().___()
                ._().__().__().__().__().__().__()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                .___()._().__().__().__().__().__().__()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._().___()._____()._().__()
                .__().__().__().__().__()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._().___()._().__().__().__().__()
                .__().__()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._().___()._().__().__()
                .__().__().__().__()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._().___().______()
                ._().__().__().__().__().__().__()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._().___()._().__().__().__().__().__().__()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._().___()._().__().__().__().__().__().__()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._().___()
                ._().__().__().__().__().__().__()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._().___()._().__().__().__().__().__()
                .__()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._().___()._().__().__().__().__().__()._()._()._()._()
                ._()._()._()._()._()._()._()._().___()._().__().__().__().__()
                .__().___()._().__().__().__().__().__().__()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._().___()._().__().__().__().__().__()
                .__()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._().___()._().__().__().__().__().__().__()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._().___()._().__().__().__().__().__().__()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._().___()._().__()
                .__().__().__().__().__()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._().___().____()
                ._().__().__().__().__().__().__()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._().___()._().__()
                .__().__().__().__().__()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._().___()._().__()
                .__().__().__().__().__()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._().___()._().__().__().__().__().__().__()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._().___()._()
                .__().__().__().__().__().__()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._().___()
                ._().__().__().__().__().__().__()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._().___()._().__().__().__().__().__()
                .__()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._()._()._()._()._()._()._()._()._()._()._()._()._()._()
                ._()._().___()._______()
        ;
    }
}

class ________ {
    Object _;
    Object[] __ = {};
    Object[] ___ = {};
    char ____;
    char[] _____ = {};
    char[] ______ = {};
    ________ _______ = this;
    int ________ = 1;
    
    ________ _() {
        ____ += ________;
        return _______;
    }
    
    ________ __() {
        ____ <<= ________;
        return _______;
    }

    ________ ___() {
        _____ = copyOf(_____, _____.length+________);
        _____[_____.length-________] = ____;
        ____ = 0;
        return _______;
    }
    
    ________ ____() {
        __ = copyOf(__, __.length+1);
        __[__.length-________] = _________();
        return _______;
    }
    
    ________ _____() throws Exception {
        _ = forName(_________());
        return _______;
    }
    
    ________ ______() throws Exception {
        _ = ((Class<?>)_).getField(_________()).get(null);
        return _______;
    }

    ________ _______() throws Exception {
        _ = _.getClass().getMethod(_________(), String.class).invoke(_, __);
        return _______;
    }
    
    String _________() {
        String __________ = new String(_____);
        _____ = ______;
        return __________;
    }
}

2009-06-10

Compiler Bug in Eclipse 3.4

Eclipse 3.4 generates bad bytecode for the following Java:

package a;

abstract class AA {
    final String _value = "the value";

    protected String get() {
        return _value;
    }
}

public abstract class A extends AA {
}


package b;

public class B extends a.A {

    public static void main(String[] args) {
        B b = new B();
        b.doit();
    }

    private void doit() {
        new Runnable() {
            public void run() {
                System.out.println(get()); // IllegalAccessError thrown here
            }
        }.run();
    }

}

An IllegalAccessError is thrown on the indicated line.  A comparison of the bytecode generated by Eclipse versus that from Javac reveals only one significant difference, in the synthetic accessor method generated in B that is necessary to give B$1 (the Runnable) access to the protected method get():

   Javac:   invokevirtual #1;  //Method get:()Ljava/lang/String;

   Eclipse: invokevirtual #33; //Method a/AA.get:()Ljava/lang/String;

The Javac-version is invoking the method by its unqualified name.  The Eclipse version is using a qualified name.  Apparently the JVM gets grumpy with the latter.

This is reported as fixed in Eclipse 3.5 -- see Eclipse's Bugzilla, bug #249107.

2009-05-30

"Hello World" Using Long Integers

I enjoyed the Python program exhibited on Poromenos's blog that prints out "Hello World" using curve-fitting. I wanted to play copycat in Java, but wanted to use an exact solution to the equation instead of rounding off. The result is exhibited below.

public class HelloWorld {

    public static void main(String arguments[]) {
        for (int i = 0; i < 13; ++i) {
            System.out.print(f(i));
        }
        System.out.println();
    }
    
    private static char f(int x) {
        return (char)(
                ( 49816166400L
                + 1114492383360L * x
                - 3487560668352L * x * x
                + 4521056833128L * x * x * x
                - 3246967654612L * x * x * x * x
                + 1447974643830L * x * x * x * x * x
                - 423730694651L * x * x * x * x * x * x
                + 83502380214L * x * x * x * x * x * x * x
                - 11141107791L * x * x * x * x * x * x * x * x
                + 991358610L * x * x * x * x * x * x * x * x * x
                - 56296097L * x * x * x * x * x * x * x * x * x * x
                + 1844058L * x * x * x * x * x * x * x * x * x * x * x
                - 26497L * x * x * x * x * x * x * x * x * x * x * x * x
                ) / 479001600L
            );
    }
}

In case you are wondering, I captured a transcript of the Mathematica session where I generated that program (PDF).

2009-05-19

lambdaj

lambdaj uses CGLIB proxy generation and Hamcrest conditional expressions to implement a DSL that allows you to write pseudo-functional collection iterations in Java.  Like this:

forEach(personInFamily).setLastName("Fusco");

Or this:

List sortedByAgePersons = sort(persons, on(Person.class).getAge());

Slick, although all its tricks are done at runtime using proxies and reflection.

2009-05-01

Git Gui Bash Tool on Windows

When on Windows, you can add a Bash tool to the Git Gui by adding a config entry like this:

[guitool "Git Bash"]
	cmd = cmd //c "C:/app/Git/bin/sh.exe --login -i" &
	noconsole = true

Git/MinGW versus Windows

On Windows using the Git/MinGW package, I was trying to use the command git rebase -i HEAD~3 to rewrite history interactively.  By default, VIM is used to edit  the rebase command file.  Unfortunately, it does not function properly in a plain old CMD window.  Also, Wordpad would probably be a better choice anyway.  I ran in to difficult configuring this.  After much experimentation, I discovered that the following Git configuration would work:

git config --system core.editor "cmd //c start //wait wordpad"

The /WAIT is needed to make sure that Git doesn't just carry on immediately after START returns.  START is needed to make it easier to launch Wordpad which does not usually live on the PATH.  Finally, the doubled slashes are need to inhibit MinGW's automatic pathname expansion (which rewrites paths: /c/xyz -> c:/xyz and /wait -> c:/mingwinstalldir/wait).

2009-04-27

SVN-Monitor

SVN-Monitor is picking up some nice features.  I particularly liked the author's blog entry about using SVN-Monitor to make Subversion accessible to non-developers: How I’ve put my wife into SVN.

Up-calls as a Code Smell

Of late, I've been doing a lot of class hierarchy refactoring (in Java).  I think that "up calls", methods that call a method in a superclass, are bad news.  Calling the super implementation of a method or constructor is not so bad (being the Java equivalent of a Beta inner invocation).  At least, it is no worse than having implementation-inheritance in the first place.  But I have observed that if a class calls any other method from a superclass, then the code is usually messed up: hierarchy inversion, is-a/has-a confusion, too many responsibilities, or some other sin.  Thus, the presence of an up-call is a code smell which should make one step back and think about refactoring.

Disclaimer: I'm talking about API here, not SPI...

2009-04-24

NTFS Alternate Data Streams

Not all commands support alternate data stream (ADS) filename syntax.  Most built-in DOS commands have no idea.  However, file redirection works so you can do things like MORE <somefile.txt:streamnameWordPad will take an ADS path, but Notepad has trouble with them because it always wants to add a ".txt" extension.

Windows SP2 Attachment Manager

Windows XP SP2 introduced the Attachment Execution Service.  It manages a set of security rules that apply to files that are transmitted to the computer as attachments.  One of the key features is that downloaded files are tagged as to their originating security zone.  When you attempt to run the file, Windows consults the zone information and then executes using those zone's rules.

I came across this when an HTA failed to perform SQL operations, complaining that cross-domain access was permitted.  The HTA had been tagged as being in the Internet zone which, of course, prohibits such operations.  The main evidence for this problem could be found on the file's properties page.  It contained the message:

This file came from another computer and might be blocked to help protect this computer.

There was also a button offering to unblock the file.

Internally, the file contains an NTFS alternate data stream named Zone.Identifier.

Their is a group policy setting that controls whether zone identifiers are attached to files:

User Configuration\
  Windows Settings\
    Administrative Templates\
      Attachment Manager\
        Do no preserve zone information in file attachments

2009-04-19

Git on Windows

There is a nice walkthrough of installing msysgit on Windows: An Illustrated Guide To Git on Windows.

2009-04-17

Factorial in SQL Server 2005

Just for laughs, here is factorial calculation in SQL Server 2005:

with factorial as (
  select 0 as "n", CAST(1 AS DECIMAL(38)) as "n!"
  union all
  select "n" + 1, "n!" * ("n" + 1) from factorial
)
select top 34 * from factorial

Maximal recursive depth can be achieved using the MAXRECURSION option:

with maximal as (
  select 0 as n
  union all
  select n + 1 from maximal
)
select top 32768 * from maximal
option (maxrecursion 32767)

2009-04-07

SQL Server Access Violations

I've been getting a lot of access violations in SQL Server 2005 SP2 recently.  I cannot say with certainty what the cause is, but I strongly suspect the presence of CROSS APPLY in queries of moderate complexity.  In every case, removing the CROSS APPLY made the problem go away.  Furthermore, the queries would work correctly in SQL Server 2008.  I have yet to successfully use CROSS APPLY in anything other than a trivial case.

The access violation causes entries in the SQL Server error log that look like this:

2009-04-03 13:59:58.80 spid53      *   Exception Address = 012828F6 Module(sqlservr+002828F6)
2009-04-03 13:59:58.80 spid53      *   Exception Code    = c0000005 EXCEPTION_ACCESS_VIOLATION
2009-04-03 13:59:58.80 spid53      *   Access Violation occurred writing address 00000000

SQL Server Versions

SQL Security has a handy table of SQL Server releases.

2009-03-27

Creole

Creole is an Eclipse plug-in that brings Shrimp dependency visualization to Eclipse/Java.

2009-03-26

Hudson

Hudson is a Java-based continuous build server that requires much less configuration than CruiseControl.

2009-03-16

VisualVM

VisualVM 1.1.1 is starting to show some nice, practical functionality.

2009-03-01

Terracotta

Terracotta is a Java-based system for sharing objects across VMs -- "network-attached memory".

2009-02-28

Jailer

Jailer is a Java-based utility for subsetting relational databases.

2009-02-27

Lift Hits 1.0

The Scala-based Lift web framework has hit the 1.0 milestone.

2009-02-10

Metamath

Metamath is a kind of contemporary version of Whitehead and Russell's Principia Mathematica.

2009-02-06

SQL Server Query Optimization Woes

I had a complex view that returned, among other things, a foreign key ("spId").  I then had a select statement of the form SELECT * FROM theView WHERE spId = ?.  If I executed the query interactively, it returned the result in a couple of seconds.  But if I ran the query using sp_prepare/sp_execute, the query took a very long time to complete.  This was inconvenient since the query was actually being executed through jTDS which, by default, does the prepare/execute thing (although it can be disabled using the connection parameter prepareSQL=2).

After some research, I concluded that I was the victim of the SQL Server optimizer's sensitivity to the exact parameter value (aka "parameter sniffing").  I found some web pages that discussed this:

In short, if a query is compiled in the absence of specific query parameter values (such as in the context of sp_prepare), the execution plan may be radically different from that generated when values are available (such as when an ad hoc query is being compiled) .  Solutions range from:

  1. wrapping the query in a stored procedure that gives more clues as to the parameters type and/or value (on Ken's blog, he goes so far as to set a value on a never-supplied optional proc parameter and reference that parameter in the query)
  2. forcing a recompile of the query immediately prior to running it -- e.g. using SQL Server 2005's OPTION(RECOMPILE)
  3. giving the optimizer a hint as to parameter values -- e.g. using SQL Server 2005's OPTION(OPTIMIZE FOR (@P=1))

As I was using SQL Server 2000, I could only use the first option (which worked).  I didn't have to resort to setting up a dummy parameter -- it was enough to create a minimal proc wrapper:

CREATE PROCEDURE dbo.zot @P INT AS SELECT ... AND spId = @P

I tried to avoid the proc by changing my inline query to something like this:

DECLARE @P INT
SET @P = ?
SELECT ... AND spId = @P

but, surprisingly, the optimizer ignored the strong hint that @P was an INT.  I also had no luck with:

SELECT ... AND spId = CAST(? AS INT)

Parameter-sniffing exploits statistics, so my problems might have been caused by stale or misleading statistics.  Here are some useful diagnosis commands:

  • show statistics for a column: dbcc show_statistics('dbo.projectFilter','spId')
  • show cached plans, etc: select * from master.dbo.syscacheobjects where sql like 'dbo.projectFilter'

2009-02-03

LINQPad

LINQPad is a nifty utility for executing C#, VB and SQL expressions.

2009-01-19

erlIDE

erlIDE is an Eclipse-based development environment for Erlang.

Blog Archive