A couple of comments - in your first example, you do not even need to extend Task or import BuildException - you never throw it or use the Task infrastracture. Simply a "public void execute()" method makes a class an Ant task.
And yes, you can use an Ant task as .class not in a JAR. Use the classpath capability of taskdef to set it. An even slicker method of defining tasks is through the new Antlib capability which avoids having fully qualified classnames in your build file which are subject to change.