Monday, June 8, 2009
Hello!
Ubuntu
Ubuntu Introduction
Installation scripts
Editors:
Installing Eclipse
Emacs (and SLIME with Clojure)
Vim
Java:
Installing Glassfish
Getting Started with Java Persistence API
R and Java
Flex:
Learning Flex
Flexbuilder in Linux
Flex, WebServices, Glassfish, Eclipse
Clojure:
Learning Clojure (and Emacs with SLIME)
MVC in Clojure
OpenGL in Clojure
3D Grapher in Clojure (using OpenGL)
LaTeX:
Getting Started with LaTeX
Pseudocode
LaTeX in VIM
Graphics:
Installing Nvidia Drivers
OpenGL in Eclipse
OpenGL Cylinders and Spheres with inside test
Getting Started with CUDA in Ubuntu
CUDA in VIM
CUDA in Eclipse
Wordpress:
Installing Wordpress
Set up Email notifications
Unix:
Recursive word count
String replacement across many files
batch rename
delete all but a given type of file
Utilities:
zipping and unzipping
using SVN (version control) command line client
Set the desktop background from the command line
Setting Up Synergy (cross-computer keyboard and mouse sharing)
NVidia Dual Monitor setup
Turn off the system beep and ALL system sounds
Code to HTML
All code and text on this blog is in the public domain, free to use and modify with no restrictions whatsoever.
Enjoy!
Installation Scripts
#Common Things:
#install LaTeX, SVN
sudo apt-get install texlive subversion
#install and configure emacs and vim, kill the system beep
wget http://bitbucket.org/curran/ubuntuautomation/raw/c896a3c66d2f/fix_ubuntu.sh && sh ./fix_ubuntu.sh
#install eclipse
wget http://bitbucket.org/curran/ubuntuautomation/raw/c896a3c66d2f/install_eclipse.sh && ./install_eclipse.sh
#install Clojure and Clojure-SLIME
wget http://bitbucket.org/curran/ubuntuautomation/raw/1b06abf276e6/install_clojure.sh && sh ./install_clojure.sh
#Not-so-common Things:
#install glassfish
wget http://bitbucket.org/curran/ubuntuautomation/raw/c896a3c66d2f/install_glassfish_v2_1.sh && sh ./install_glassfish_v2_1.sh
To install everything at once:
wget http://bitbucket.org/curran/ubuntuautomation/raw/abb8f7116cbd/install_all.sh
#perhaps remove the things you don't want from the script...
sh ./install_all.sh
Wednesday, June 3, 2009
Command Line SVN Client
to check out:
svn checkout [svn url]
to add a file to the repository (this is NOT comitting, so after "add"ing a file, it's not actually copied into the repository, it's just marked for inclusion in the next commit):
svn add [filename]
In SVN, when you add a new file, you need to "add" it to SVN, then "commit" it - two separate steps. It becomes tedious and error prone to find which files have been newly created and execute "svn add ..." for each one. Here's how you can ensure that all new files under the current directory are added:
svn add * --force
to commit all changed files in the current directory (to actually submit them to the repository or update them - note that the files must first be "add"ed):
svn commit -m "your comment here"
To remove a file from the repository, first delete it on your system, then execute:
svn delete [filename]
The comments you (and anyone else) add with -m "your comment here" are recorded in the SVN commit history. To view the comment history:
svn log | head -n 30
This uses the "head" unix utility to show only the first 30 lines of the output of "svn log", which shows the most recent 7 or 8 comments. "svn log" alone will spew out all comments ever written.
SVN Cheat Sheet
Subversion client for Ubuntu: anything like TortoiseSVN?
SVN: Examining History
Wednesday, May 20, 2009
Linux Frustrations
Seq24 (the sequencer) sucks
Seq24, a sequencing program, is broken out of the box in Ubuntu Studio. Why is this? Do the Ubuntu Studio folks to any testing before they release? I ranted with error messages on this forum and this bug report about seq24 - the package is broken, the web site download page is out of date, and the real latest code also crashes and doesn't connect to JACK, the audio server used by many Linux DAWs and synths.
Kile (the LaTeX IDE) sucks
Now I am trying to use Kile for LaTeX editing. It's totally hosed, completely crap compared to older versions. Here are the problems:
- By default the lines don't wrap. Whats up with this? Doesn't just about EVERY SINGLE PERSON editing a LaTeX document want word wrap? Word wrap should definitely be on by default. Why not?
- The menus Compile, Convert, View, and Other (under Build) - the ones used to BUILD AND VIEW LATEX, which is the WHOLE POINT of using the program - are empty, even though I have LaTeX and Okular etc. installed and can compile and view LaTeX from the command line just fine.
- When I open a pdf in Okular, it has these two huge ass panels on the right, one with "Bookmarks", "Reviews", "Thumbnails" and "Contents" (which is blanked out, why is that even there? that makes no sense whatsoever and should be taken away unless it is needed for SOMETHING)
- So, I go to get rid of this ridiculous huge panel thing that should be hidden by default because it makes my document too small to read the text - which is the WHOLE POINT OF MY OPENING THE DOCUMENT IN THE FIRST PLACE - and I look in the "View" menu, because the panel thing - which I have no idea what it's even called, because it's not labeled - is definitely something I am viewing right now. Well, it turns out to be under Settings -> Show Navigation Panel, who'd have guessed.
Seq24
- @Ubuntu: Update the Ubuntu package to the latest version
- @seq24: fix the crash when I click "tools" and have it connect to Jack out of the box
- @Kile: Word wrap should be on by default.
- @Kile: Kile should be able to build and view LaTeX documents out of the box.
- @Ubuntu: The Kile package should be tested before releasing
- @KDE/Okular: The navigation panel should be hidden by default - I can scroll just fine, thanks, without it.
- @KDE/Okular: The navigation panel should be labeled "Navigation Panel" so I know what to look for when I want to close it.
- @KDE/Okular: Better yet, it should have a little X in the upper right corner so I could just close it, the real estate lost wouldn't hurt anybody.
Thanks for listening. I'd appreciate it if anyone told me which specific procedures to go through to get these changes made, or if some specific log files or error details would be useful (I'll post them here).
If I have some time I'd like to help in fixing these annoyances. They give Linux a bad name.
Thursday, May 14, 2009
3D Grapher in Clojure
LiquidMath
Curran Kelleher
May 13, 2009
Overview
LiquidMath is a 3D graphing calculator. It graphs implicit parametric equations, where (x,y,z) = f(u,v). Functions are input as Lisp code in the text box, and the surface is displayed as a freely rotatable 3D object. There is much room for improvement, I plan to continue developing this project.
Screenshot

Technology
LiquidMath is written in Clojure, a modern Lisp variant which compiles to Java bytecode. Java's Swing API is used for the GUI. OpenGL is used for 3D rendering, accessed via the Java OpenGL (JOGL) library. OpenGL Display Lists are used to achieve smooth rotation interaction.
Innovation
LiquidMath combines the dynamic nature of Lisp, the beauty of math, and the interactivity of modern graphics to deliver an effective educational tool for gaining insight into the nature of parametric surfaces. Conventionally, courses which explore 3D surfaces such as calculus III use only static diagrams. LiquidMath could be used by instructors during class, or by students when doing assignments.
Technology Used Block Diagram
LiquidMath is designed around the model-view-controller pattern, in which the model is the data representing salient application state, the view is the gui definition, and the controller sets up communication between the view and model. The view contains the text box and graphics panel. The text box updates the model via a listener added by the controller. The graphics panel is responsible for responding to changes in the model by generating and compiling code from the newly entered function string, then re-rendering the surface into the display list.

Additional Remarks
The full source code is posted here (public domain, feel free to use, copy, etc):
Here are some additional works that came out of this project:
- A tutorial on Clojure, Emacs, and SLIME
- JOGL example from Wikipedia ported to Clojure (and the refactored Java version was contributed back to Wikipedia)
- Blog post about a model-view-controller skeleton
- An intermediate stage was a 2D animated grapher
The following are discussions on the Clojure mailing list:
Saturday, May 9, 2009
Visualization System Ideas
The idea is that a url-accessible entity will contain a stateful resource which can be interacted with OpenGL-style via bunches of function calls (in URL requests). Some of the functions would be as follows:
- Give me a session ID
arguments:
return value: sessionID
side effect: initialize the session on the server side, make it usable - Load a data set into my session
arguments: sessionID, pointer to distributed data set resource
return value:
side effect: loads the given data set pointer into the session, makes it usable - Create a visualization
arguments: sessionID, visualization type
return value: visualizationID
side effect: load a visualization instance of the specified type, which uses the currently loaded data set, and can be referred to by the returned visualization ID - Set visualization parameters
arguments: sessionID, visualizationID, parameter map
return value:
side effect: set the values of the specified visualization instance to the values of the given visualization-type-specific parameter map, which may contain values like which data rows/columns to visualize in which way, or which color map to use. - Set selection query
arguments: data set query which can deduce a set of selected records.
return value:
side effect: - Set selection polygon
arguments: sessionID, visualizationID, width, height, and a polygon (all in rendered-visualization-image-pixel-coordinates)
return value:
side effect: calls "Set selection query" with a query which derives the set of records that lie inside the specified polygon in the specified rendered visualization instance.
- Render visualization
arguments: sessionID, visualizationID, width, height
return value: an image of the rendered visualization (using the current data set of the session, representing visually the current selection, and the current parameters of the specified visualization instance), with the specified (width, height) pixel dimensions
side effect: none, or perhaps do some setup which improves the speed of future renders.
Thats the idea, to be implemented to run on a cluster, perhaps in the cloud.
Thursday, May 7, 2009
Model-View-Controller GUI in Clojure

The idea is to have a mutable object which encapsulates the application state (model), and gui code which reflects the state (view), and provides a way to change it (controller). In this case, the model is just a string, the view is the panel that draws the string, and the controller is the text field. When you type in the text field and hit enter, the model is changed, and the panel draws the new string.
Creating the Model
Clojure is incredibly well thought out in terms of mutability and concurrency, and provides several primitives for dealing with mutable objects. I used a Clojure ref object as the model, which wraps a string. The model is created at the top level, and pushed down as an argument to the GUI code (which conveniently closes over it, making it a persistently available pointer). The following code creates the model:
(ref "Hello MVC!")Reading the Model
The text field is initialized with the value of the model with the following code:
...
(doto (JTextField.)
(.setText @model)
...
note - "@" serves to dereference a Clojure reference, yielding in this case the string wrapped by the model object.The graphics panel reads and draws the model's every time it paints itself, with the following code:
(paint [g]
(doto g
...(.drawString @model 20 40)
...
Mutating the Model
The model is mutated in the code of the ActionListener added to the text field:
(dosync (ref-set model new-text))note - dosync performs a transaction, which is necessary when mutating Clojure references. (ref-set reference new-value) sets the value of the reference.Listening to the Model
Clojure has this really cool "add-watch" feature where you can attach an update function to any mutable object! The function gets called every time the object changes. The following line attaches a watch function to the model which repaints the panel when the model changes:
(add-watch model "repaint" (fn [k r o n] (.repaint panel)))The Code
Here is the code, totaling 74 lines. Any comments are appreciated.
If anyone knows how I can get nice syntax-highlighted HTML for this code, please let me know!
;A test program exploring how to structure GUI code in Clojure
;The GUI draws whatever you type in the text field nicely in the panel below.
;license: Public domain
(import '(javax.swing JFrame JLabel JTextField JButton JPanel)
'(java.awt.event ActionListener)
'(java.awt GridBagLayout GridBagConstraints Color Font RenderingHints))
(defn make-model [] (ref "Hello MVC!"))
(defn make-graphics-panel [model]
(let [panel
(proxy [JPanel] []
(JPanel [] (println "in constructor"))
(paint [g]
(doto g
;clear the background
(.setColor (. Color black))
(.fillRect 0 0 (.getWidth this) (.getHeight this))
;draw the text
(.setRenderingHint (. RenderingHints KEY_ANTIALIASING)
(. RenderingHints VALUE_ANTIALIAS_ON))
(.setFont (Font. "Serif" (. Font PLAIN) 40))
(.setColor (. Color white))
(.drawString @model 20 40))))]
;repaint when the model changes
(add-watch model "repaint" (fn [k r o n] (.repaint panel)))
panel))
(defn make-text-field [model]
(doto (JTextField.)
(.setText @model)
(.addActionListener
(proxy [ActionListener] []
(actionPerformed [e]
(let [new-text (.getActionCommand e)]
(dosync (ref-set model new-text))))))))
(defn make-gui-panel [model]
(defn make-text-field-constraints []
(let [c (GridBagConstraints.)]
(set! (.fill c) (. GridBagConstraints HORIZONTAL))
(set! (.weightx c) 1)
c))
(defn make-panel-constraints []
(let [c (GridBagConstraints.)]
(set! (.gridy c) 1)
(set! (.weighty c) 1)
(set! (.fill c) (. GridBagConstraints BOTH))
c))
(let [gridbag (GridBagLayout.)
text-field (make-text-field model)
panel (make-graphics-panel model)]
;set up the gridbag constraints
(doto gridbag
(.setConstraints text-field (make-text-field-constraints))
(.setConstraints panel (make-panel-constraints)))
;add the components to the panel and return it
(doto (JPanel.)
(.setLayout gridbag)
(.add text-field)
(.add panel))))
(defn show-in-frame [panel width height frame-title]
(doto (JFrame. frame-title)
(.add panel)
(.setSize width height)
(.setVisible true)))
(show-in-frame (make-gui-panel (make-model)) 300 110 "GUI Test")
Tuesday, April 14, 2009
The Tree Draws Well
the code
Thursday, April 9, 2009
Visualizing the Abstract Syntax Tree
I'm not sure if this is a standard way of visualizing Lisp abstract syntax trees - representing lists with a dot. I figured I can't put the function name at the node, because then it couldn't handle code that evaluates to a function that was returned from other code, like ((fn (x y z) (+ x y z)) 1 2 3)
Here's what it looks like to far:
It has overlap issues, here's what it does to fibbonacci:
the code
Wednesday, April 8, 2009
Factorial is possible!
Now the language has the following built-in functions: +,-,*,def,fn,and if. "if" is actually a function, because I made the function implementation responsible for evaluating its arguments, which are passed in as unevaluated abstract syntax trees. I'm not sure it that's correct, but it works for now.
Implementing all the primitives made me realize that those functions in Lisps take an arbitrary number of arguments. For example, in Clojure:
(<> true
but
(<> false
Implementing "if" involved clearly defining how booleans are represented. I decided that anything non-nil is true, and true is arbitrarily chosen as the number 1. This isn't very readable for printing out results, but it gets the job done. Maybe it would be a good idea to introduce a boolean type...not sure...maybe the just the notion of a "named constant"...
In any case, factorial works:
(def ! (fn (x) (if (< x 2) 1 (* x (! (- x 1))))))
(! 6) -> 720 (which is 6*5*4*3*2*1)
Sweet!
the code
Lambdas are here!
Now it can do stuff like:
(def double (fn (x) (+ x x)))
(double 100) -> 200
Now we're getting somewhere!
Next we'll need "if", then recursion will become possible.
the code
Progress in Tiny Lisp Interpreter
(def a 8) -> 8
a -> 8
(def b (+ 5 6)) -> 11
b -> 11
(+ a b) -> 19
I wonder if, for a massively parallelized interpreter, it would be better to disallow redefinition of bindings. I would imagine it has benefits for distribution - if a symbols binding is guaranteed never to change, then the system could replicate and pass along the enclosing environment as fixed values when distribution across machines happens. Perhaps this is why Erlang is single assignment...
The next step is, hopefully, to implement lambda!
Here is the code for those interested.
Tuesday, April 7, 2009
A Tiny Lisp Interpreter
The only thing it can do now is parse and evaluate expressions like (+ 1 (+ (+ 1 2) 3 (+ 5 5))). Not very impressive, but it's a start. It has the essentials though: a recursive descent parser that transforms text into an abstract syntax tree (which is actually just (cons cells) filled with numbers and functions), and an eval/apply tree walker that runs the code.
It blows my mind that code is data in Lisps, and there is no syntax except parentheses and white space. Those aspects made writing the interpreter a lot easier than I expected. I found myself needing to write functional code in Java to make the thing work - for example, there is a tree walker that generates the code from the abstract syntax tree. That code was more natural to phrase functionally instead of object oriented-ly - x.toString() became toString(x), and suddenly the implementation became more straightforward.
Here is the code so far in case anyone is interested, (I hereby release it into the public domain!) I hope to eventually make a front end that visualizes code running in a simulated sea of parallel processors, in an effort to understand how I could implement such a system to run in an actual sea of processors.
What is Compute Intensive?
Bioinformatics - useful for drug discovery and scientific understanding:
Genomics - vast amounts of sequence data
Proteomics - protein folding simulations need lots of compute power
Microarray Analysis - very large data sets are generated from microarray experiments, which need to be statistically analyzed, which requires heavy computing power.
Geospatial Information Systems - useful in understanding soceity and natural geographic phenomena - Data sets of geographically grounded indicators (think the Census) are very large, and progress over time. Statistical analysis of these data sets is very compute intensive
Computer Graphics:
Gaming - fun - graphics are compute intensive
Computer Vision - useful in manufacturing, robotics, understanding perception - compute intensive
Physics Simulations - advancing knowledge in physics - Compute Intensive
Weather Simulations - observing and predicting the weather - VERY data and compute intensive
Text mining - information aggregation and summarization, search - Data and compute intensive
I'm envisioning a computational system which assumes an infinite sea of processors (similar to the CUDA model of computation), and uses instead of a single stack, a branching stack, in which everything that can happen in parallel does hapen in parallel. I can see that such a system is implementable on GPUs with CUDA (or possibly OpenCL, I don't know much about that yet) by implementing a Lisp-like eval-apply loop which only acts on leaves of the stack tree (which can be compacted in log(n) time in parallel).
If the system can also be designed in such a way that it can orchestrate and evolve itself (its repetitive computation delegation decisions) over a cloud of machines with various compute facilities (both GPUs and *-core CPUs) with speed optimization as an emergent property, then it could change the world ... but only if people actually need it for something practical.
Could people actually benefit from such a system? Or is it just an academic pursuit?
Monday, April 6, 2009
Memoization - wtf?
(defn memoize [f]What the heck!?
(let [mem (atom {})]
(fn [& args]
(if-let [e (find @mem args)]
(val e)
(let [ret (apply f args)]
(swap! mem assoc args ret)
ret)))))
(defn fib [n]
(if (<= n 1)
n
(+ (fib (dec n)) (fib (- n 2)))))
(time (fib 35))
user=> "Elapsed time: 941.445 msecs"
(def fib (memoize fib))
(time (fib 35))
user=> "Elapsed time: 0.044 msecs"
It wraps a function with a function that caches its return values for each signature it sees and returns the pre-baked cakes instead of baking the same cake over and over. Sweet! What a great idea!
Source: Clojure Atoms
Friday, April 3, 2009
OpenGL in Clojure
Here's a port of the JOGL example in Wikipedia to Clojure:
;This is a Clojure port of the JOGL example in Wikipedia
;Author: Curran Kelleher
;License: Public Domain
;dependencies: jogl.jar, gluegen-rt.jar
;for the REPL (use C-x C-e):
(comment
;these are the default paths of the jars in Ubuntu
(add-classpath "file:/usr/share/java/jogl.jar")
(add-classpath "file:/usr/share/java/gluegen-rt.jar")
)
(import '(java.awt Frame)
'(java.awt.event WindowListener WindowAdapter KeyListener KeyEvent)
'(javax.media.opengl GLCanvas GLEventListener GL GLAutoDrawable)
'(javax.media.opengl.glu GLU)
'(com.sun.opengl.util Animator))
(def rotateT 0)
(def glu (new GLU))
(def canvas (new GLCanvas))
(def frame (new Frame "Jogl 3D Shape/Rotation"))
(def animator (new Animator canvas))
(defn exit "Stops animation and closes the OpenGL frame." []
(.stop animator)
(.dispose frame))
(.addGLEventListener
canvas
(proxy [GLEventListener] []
(display
[#^GLAutoDrawable drawable]
(doto (.getGL drawable)
(.glClear (. GL GL_COLOR_BUFFER_BIT))
(.glClear (. GL GL_DEPTH_BUFFER_BIT))
(.glLoadIdentity)
(.glTranslatef 0 0 -5)
(.glRotatef rotateT 1 0 0)
(.glRotatef rotateT 0 1 0)
(.glRotatef rotateT 0 0 1)
(.glRotatef rotateT 0 1 0)
(.glBegin (. GL GL_TRIANGLES))
; Front
(.glColor3f 0 1 1)
(.glVertex3f 0 1 0)
(.glColor3f 0 0 1)
(.glVertex3f -1 -1 1)
(.glColor3f 0 0 0)
(.glVertex3f 1 -1 1)
; Right Side Facing Front
(.glColor3f 0 1 1)
(.glVertex3f 0 1 0)
(.glColor3f 0 0 1)
(.glVertex3f 1 -1 1)
(.glColor3f 0 0 0)
(.glVertex3f 0 -1 -1)
; Left Side Facing Front
(.glColor3f 0 1 1)
(.glVertex3f 0 1 0)
(.glColor3f 0 0 1)
(.glVertex3f 0 -1 -1)
(.glColor3f 0 0 0)
(.glVertex3f -1 -1 1)
;Bottom
(.glColor3f 0 0 0)
(.glVertex3f -1 -1 1)
(.glColor3f 0.1 0.1 0.1)
(.glVertex3f 1 -1 1)
(.glColor3f 0.2 0.2 0.2)
(.glVertex3f 0 -1 -1)
(.glEnd))
(def rotateT (+ 0.2 rotateT)))
(displayChanged [drawable m d])
(init
[#^GLAutoDrawable drawable]
(doto (.getGL drawable)
(.glShadeModel (. GL GL_SMOOTH))
(.glClearColor 0 0 0 0)
(.glClearDepth 1)
(.glEnable (. GL GL_DEPTH_TEST))
(.glDepthFunc (. GL GL_LEQUAL))
(.glHint (. GL GL_PERSPECTIVE_CORRECTION_HINT)
(. GL GL_NICEST)))
(.addKeyListener
drawable
(proxy [KeyListener] []
(keyPressed
[e]
(when (= (.getKeyCode e) (. KeyEvent VK_ESCAPE))
(exit))))))
(reshape
[#^GLAutoDrawable drawable x y w h]
(when (> h 0)
(let [gl (.getGL drawable)]
(.glMatrixMode gl (. GL GL_PROJECTION))
(.glLoadIdentity gl)
(.gluPerspective glu 50 (/ w h) 1 1000)
(.glMatrixMode gl (. GL GL_MODELVIEW))
(.glLoadIdentity gl))))))
(doto frame
(.add canvas)
(.setSize 640 480)
(.setUndecorated true)
(.setExtendedState (. Frame MAXIMIZED_BOTH))
(.addWindowListener
(proxy [WindowAdapter] []
(windowClosing [e] (exit))))
(.setVisible true))
(.start animator)
(.requestFocus canvas)
Here's a shell script that will run it:
#!/bin/sh
java -cp $CLOJURE_EXT/clojure.jar:/usr/share/java/jogl.jar:/usr/share/java/gluegen-rt.jar clojure.main joglExample.clj
The libraries can be installed in Ubuntu with
sudo apt-get install libjogl-java
Here's the refactored Java example from Wikipedia:
import javax.media.opengl.GL;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.glu.GLU;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.media.opengl.GLCanvas;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import com.sun.opengl.util.Animator;
public class joglExample implements GLEventListener, KeyListener {
float rotateT = 0.0f;
static GLU glu = new GLU();
static GLCanvas canvas = new GLCanvas();
static Frame frame = new Frame("Jogl 3D Shape/Rotation");
static Animator animator = new Animator(canvas);
public void display(GLAutoDrawable gLDrawable) {
final GL gl = gLDrawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
gl.glBegin(GL.GL_TRIANGLES);
// Front
gl.glColor3f(0.0f, 1.0f, 1.0f);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glColor3f(0.0f, 0.0f, 1.0f);
gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glVertex3f(1.0f, -1.0f, 1.0f);
// Right Side Facing Front
gl.glColor3f(0.0f, 1.0f, 1.0f);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glColor3f(0.0f, 0.0f, 1.0f);
gl.glVertex3f(1.0f, -1.0f, 1.0f);
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glVertex3f(0.0f, -1.0f, -1.0f);
// Left Side Facing Front
gl.glColor3f(0.0f, 1.0f, 1.0f);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glColor3f(0.0f, 0.0f, 1.0f);
gl.glVertex3f(0.0f, -1.0f, -1.0f);
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, 1.0f);
// Bottom
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glColor3f(0.1f, 0.1f, 0.1f);
gl.glVertex3f(1.0f, -1.0f, 1.0f);
gl.glColor3f(0.2f, 0.2f, 0.2f);
gl.glVertex3f(0.0f, -1.0f, -1.0f);
gl.glEnd();
rotateT += 0.2f;
}
public void displayChanged(GLAutoDrawable gLDrawable,
boolean modeChanged, boolean deviceChanged) {
}
public void init(GLAutoDrawable gLDrawable) {
GL gl = gLDrawable.getGL();
gl.glShadeModel(GL.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClearDepth(1.0f);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT,
GL.GL_NICEST);
gLDrawable.addKeyListener(this);
}
public void reshape(GLAutoDrawable gLDrawable, int x,
int y, int width, int height) {
GL gl = gLDrawable.getGL();
if(height <= 0) {
height = 1;
}
float h = (float)width / (float)height;
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(50.0f, h, 1.0, 1000.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
exit();
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public static void exit(){
animator.stop();
frame.dispose();
System.exit(0);
}
public static void main(String[] args) {
canvas.addGLEventListener(new joglExample());
frame.add(canvas);
frame.setSize(640, 480);
frame.setUndecorated(true);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
exit();
}
});
frame.setVisible(true);
animator.start();
canvas.requestFocus();
}
}
Here's a shell script that will run it:
#!/bin/sh
javac -cp /usr/share/java/jogl.jar:/usr/share/java/gluegen-rt.jar joglExample.java
java -cp ./:/usr/share/java/jogl.jar:/usr/share/java/gluegen-rt.jar joglExample
Enjoy!
Links:
Gears demo in Clojure
Wikipedia JOGL demo
Wednesday, March 25, 2009
Learning Clojure and Emacs
However, lots of people believe that Clojure solves many of Lisps problems, and may be the key to the future of Lisp. Clojure is a modern dialect of Lisp that compiles to Java bytecode, cleans up much of Lisps cruft and antiquated naming, enables Java <-> Lisp interoperability, and has built-in support for concurrency.
After I expressed my frustrations with learning Lisp and Emacs, one guy at the conference said to me matter of factly "You're going to have to battle the language and the IDE at the same time. That's how one starts on the road to Lisp. Once you get past the initial hump though, I guarantee you'll never want to go back to Java. Once you get there, you should fill out the road to Lisp survey!"
There does seem to be something powerful lurking in Lisp, because there are endless testimonials (Beating the Averages by Paul Graham is particularly famous and well written) on how Lisp enabled lightning fast adaptive development, is fun to program, is amazingly powerfull, is elegant, beautiful, and so on. That said, I thought I'd give Clojure a try. Emacs seems to be hailed as the best Lisp IDE, so I'll try that too.
Here's the beginning (and perhaps end, only time will tell) of my modern day adventure on the road to Lisp: Clojure + Emacs + Ant + Ubuntu:
Setting Up Clojure and Emacs
#Install Java, Ant, Subversion, and Git.
sudo apt-get install openjdk-6-jdk ant subversion git-core emacs -y
#Run these simple setup scripts derived from these tutorials from Riddell: clojure slime
wget http://www.curransoft.com/code/setupClojure.sh wget http://www.curransoft.com/code/setupClojureSlime.sh sh setupClojure.sh
sh setupClojureSlime.sh
The contents of the scripts are as follows (just so you can see):
setupClojure.sh:
setupClojureSlime.sh:#!/bin/shecho "export CLOJURE_EXT=~/.clojure
# Adapted from http://riddell.us/tutorial/clojure/clojure.html
echo "Making ~/opt directory"
mkdir ~/opt
cd ~/opt
echo "Getting Clojure code from SVN..."
svn co http://clojure.googlecode.com/svn/trunk clojure
cd clojure
echo "Building Clojure..."
ant
mkdir ~/.clojure
cp clojure.jar ~/.clojure
cd ~/opt
echo "Getting Clojure-Contrib code from Git..."
git clone git://github.com/kevinoneill/clojure-contrib.git
cd clojure-contrib
echo "Building Clojure-Contrib"
ant -Dclojure.jar=../clojure/clojure.jar
cp *.jar ~/.clojure
echo "Setting up CLOJURE_EXT environment variable and "clj" alias
PATH=\$PATH:~/opt/clojure-contrib/launchers/bash
alias clj=clj-env-dir" >> ~/.bashrcecho "Done."
#!/bin/sh
# Adapted from http://riddell.us/tutorial/slime_swank/slime_swank.html
cd ~/opt
echo "Getting Clojure-Mode from GIT..."
git clone git://github.com/jochu/clojure-mode.git
echo "Getting Slime from GIT..."
git clone git://git.boinkor.net/slime.git
echo "Getting Slime from GIT..."
git clone git://github.com/jochu/swank-clojure.git
echo "Configuring Emacs (appending to ~/.emacs"
echo ";; clojure-mode
(add-to-list 'load-path \"~/opt/clojure-mode\")
(require 'clojure-mode)
;; swank-clojure
(add-to-list 'load-path \"~/opt/swank-clojure\")
(require 'swank-clojure-autoload)
(swank-clojure-config
(setq swank-clojure-jar-path \"~/.clojure/clojure.jar\")
(setq swank-clojure-extra-classpaths
(list \"~/.clojure/clojure-contrib.jar\")))
;; slime
(eval-after-load \"slime\"
'(progn (slime-setup '(slime-repl))))
(add-to-list 'load-path \"~/opt/slime\")
(require 'slime)
(slime-setup)">>$HOME/.emacs
echo "Done."
In Emacs:
M-x slime
It works! You should get a REPL (Read-eval-print loop) in which you can type
(+ 41 1) and get 42.
Learning Emacs
As for learning Emacs, here's what I learned:
emacs -nw starts the terminal version of emacs
To get to the built-in tutorial (which is awesome for getting started), open emacs, and hit C-h t (hit Control+h, then hit t). Here are the main points of the tutorial:
- C-x means Control+x
- M-x means Alt+x
- C-x C-c closes emacs
- C-v is page down
- M-v is page up (Ironically, this collides with the very menu item which when clicked will solve the collision problem)
- C-l centers vertically on the cursor
- C-p is up arrow
- C-n is down arrow
- C-b is left arrow
- C-f is right arrow
- C-a is home (go to beginning of line)
- C-e is end (go to end of line)
- M-<> goes to end of file
- C-u gives commands numeric arguments
- (for example C-u 8 * types ******** and C-u 10 C-n goes down 10 lines)
- M- is another way of giving commands numeric arguments
- C-g cancels/stops/escapes things
- C-x 1 closes all other windows (try C-h k C-f then C-x 1)
- C-d is the delete key
- C-k kills (deletes but copies) the rest of a line
- C-spacebar sets a marker, and C-w kills text between the marker and the cursor
- C-y pastes the killed text
- M-y cycles in place through all sets of killed text (way cool! The clipboard is a stack!)
- C-/ is undo (C-x u and C-_ are also). Redo is undo after do - Emacs has a very unique way of handling redo - once a sequence of undos is broken by doing something (typing a character for example), the undos become events which can themselves be undone, making them effectively redos. So there is only undo, but it can be used to undo undos (which is to do a redo).
- C-x C-f opens ("finds") a file
- C-x C-s saves a file
- C-x C-b list buffers (remember C-x 1 to hide the list)
- C-x s saves some buffers (prompts you)
- C-z suspend
- fg (in terminal) resume
- M-x replace-string stringtofind replacement - replaces a string (repls autocompletes nicely)
- C-s is search (C-s to go to next, enter to move cursor to search result, C-g to stop search)
- C-r is backwards search
- C-x 2 splits into two windows vertically
- C-x 3 splits into two windows horizontally
- C-x o go to the other window
- C-x 4 C-f open file in new window
M-x replace-string ,C-q C-jTo replace commas with newlines: - C-x 0 close window
- Giving arguments to C-x o is useful for navigating more than 2 windows (Emacs manual on Windows)
- Copy and Paste (from here):
C-space set mark
C-w cut text between mark and cursor
M-w copy all text between mark and cursor
C-y paste - C-x k Close buffer
- M-x cd change working directory
- You can record little scripts, called emacs macros (from emacs manual):
C-x ( Start defining a keyboard macro (start-kbd-macro).
C-x ) End the definition of a keyboard macro (end-kbd-macro).
C-x e Execute the most recent keyboard macro (call-last-kbd-macro). - C-M-\ Autoformat/"indent region"/autoindent
- C-j newline and tab
- M-^ merge (join) lines (lots of Indentation tips from the emacs manual)
Start slime with M-x slime
You'll get a REPL - Read Eval Print Loop
Type 234, it will evaluate to 234
Type hello, you will get an error. To get out of SLDB (Slime Debugger), hit 0
M-p and M-n act like up and down arrows for browsing command history
Split Emacs into two vertical windows with C-x 2
In one window, use C-x C-f to open a new file called hello.clj
Buffer and window manipulation review:
C-x o: move the cursor to the "o"ther window. C-x 1: Make there be only one window (the one with the cursor in it)- C-x 2: Split the current window vertically into two windows
- C-x b: Switch the current window to a different buffer, whose name I will type. (Space does name completion.)
- C-x C-b: Show a list of all the buffers (along with some other information like what Emacs mode each one is in, what file is loaded into each one, etc.). Moving the cursor over one and hitting enter loads that buffer into the current window.
Adapted from this tutorial, the Slime Manual, this conversation
It seems nearly impossible to find reasonable documentation for how people actually use Slime! Very frustrating. It's either a huge manual or an isolated snippet. Here's what I've found. Start from a fresh Emacs and follow these steps to learn how to use Slime:
- M-x slime this starts Slime and gives you a REPL
- C-x 2 splits the screen in half
- C-x C-f test.clj creates and opens the file test.clj
- Paste the following code into test.clj (using Shift+insert)
(import ;imports necessary just like in Java
'(java.awt Graphics)
'(javax.swing JPanel JFrame))
(defn render [#^Graphics g] ;"#^" is an optional type hint to the compiler
(doto g ;"doto" lets you call successive functions on an object
(.drawString "Hello World!" 10 20)));draw "Hello World!" on the graphics passed in
(def panel (proxy [JPanel] [] ;proxy creates anonymous subclasses
(paint [g] (render g)))); this line overrides JPanel's paint method
(def frame (doto (new JFrame);doto returns its first argument
(.add panel);add the panel to the frame
(.setBounds 100 100 100 60);set the dimensions of the frame
(.setVisible true)));show the frame - C-c C-k compiles and runs the current buffer, which will pop up a window
- Change "Hello World!" to something else
- C-c C-c compile current top-level form (it blinks!)
- Now resize the java window to trigger a repaint - it paints the new value
- In the Repl (C-x C-o gets you there), enter
(. frame setBounds 0 0 500 500)
You'll see the frame change. - This is the Lisper's notion of "incremental development" or "live coding" - no rebuild is necessary, you can make changes live! Amazing!
- Here's another example of creating a Java GUI:
(doto (JFrame.)
(.add
(doto (JButton. "Click me!")
(.addActionListener
(proxy [ActionListener] []
(actionPerformed [e] (println "Clicked!"))))))
(.setBounds 400 400 200 200)
(.setVisible true)) - Println calls and compile errors go to the buffer *inferior-lisp*, so it's nice to have it open. If you put the cursor at the end it scrolls output for you as it comes.
- C-h b describes all available keybindings (very useful)
- q hides notifications
- C-x C-e evaluates the expression before the cursor (ONLY that expression)
Adapted from Structure and Interpretation of Computer Programs lecture by Hal Abelson
- The essence of a language are its primitives, means of combination, and means of abstraction:
- Basic primitives are numbers: 5 -> 5, 1.5 -> 1.5
- Combination is parentheses-based: (+ 5 6) -> 11
- Definitions are a means of abstraction: (def a 5), a -> 5
- Functions are another means of abstraction:
(defn square [x] (* x x))
(square 5) -> 25 - Functions can also be defined like this (fn is like lambda in Lisp):
(def square (fn [x] (* x x)))
defn... is "syntactic sugar" for def...fn... (they mean the same exact thing) - Conditional execution using "if" works as follows:
(defn abs [x] (if (< x 0) (- x) x))
Conditional execution using "cond" works as follows (cond works with an arbitrary number of conditional-result pairs):
(defn abs [x] (cond (< x 0) (- x) (= x 0) 0 (> x 0) x))
important atoms: true, false, nil Strings: "hello"- Lists: (list 1 2 3) is equivalent to '(1 2 3)
- Keywords - like variables but with no bindings: :a :b :foo
- Addition: (+ 3 3 3)
Vectors (like lists): [1 2 3] or (vector 1 2 3)- Maps (dictionaries): {"a" 1, "b" 2, "c" 3}
- Map access: (get {"a" 1, "b" 2, "c" 3} "b") evaluates to 2 (commas are whitespace - they'rs not necessary but help readability)
- Map access: ({"a" 1, "b" 2, "c" 3} "b") evaluates to 2
- Definition (assignment): (def x 5) is like int x=5; in Java
- Definition (assignment): (def my-list '(1 2 3)) is like int[] myList={1,2,3}; in Java
- Defining functions: (defn election-year? [year] (zero? (rem year 4))) is like boolean electionYear(int year){return year%4==0;} in Java
- Lambdas: (fn [x] (+ x 1)) creates a function that increments x
- Lambdas: ((fn [x] (+ x 1)) 9) evaluates to 10
- Documentation: (doc first) prints documentation for the function "first"
- Documentation: (defn plus-one "Returns x+1" [x](+ x 1)) gives plus-one "Returns x+1" as a documentation string.
- String contatenation: (str "Hello," " world!") evaluates to "Hello, world!"
- If: (if (= 1 1) "yes" "no") is like 1==1?"yes":"no", and evaluates to "yes"
(println "Hello.") then (+ 2 2) and evaluates to 4. This is how you can do sequences of stuff.Do: (do (println "Hello.") (+ 2 2)) executes - When (a conditional version of do): (when true (println "Hello, world") "Yes") executes (println "Hello, world") and evaluates to "Yes"
- Let: (let [x 2, y 8] (+ x y)) evaluates to 10. The let form creates a temporary var (x and y in this case), that can only be used inside the body of the let expression.
- Java integration: (. (new java.util.Date) (toString)) evaluates to "Thu Mar 26 20:41:12 EST 2009"
- import: (import '(java.io FileReader))
- Constructor invocation: (new FileReader "source.txt")
Syntactic sugar f: (FileReader. "source.txt") - For loop: (loop [i 0](when (<>
- For loop: (dorun (for [i (range 0 5)] (println i)))
- For loop: (doseq i (range 0 5) (println i))
- Sequences (Very important concept, read more here):
(seq [1 2 3]) creates a sequence from the vector [1 2 3]
The following functions act on sequences: first, rest, cons - first (like car): (first '("one" "two" "three")) evaluates to "one"
- rest (like cdr): (rest '("one" "two" "three")) evaluates to ("two" three")
- cons: (cons 1 [2 3]) evaluates to (1 2 3)
Here's an illustrative Java GUI example, taken from here:
(import '(javax.swing JFrame JLabel JTextField JButton)
'(java.awt.event ActionListener)
'(java.awt GridLayout))
(defn celsius []
(let [frame (JFrame. "Celsius Converter")
temp-text (JTextField.)
celsius-label (JLabel. "Celsius")
convert-button (JButton. "Convert")
fahrenheit-label (JLabel. "Fahrenheit")]
(.addActionListener convert-button
(proxy [ActionListener] []
(actionPerformed [evt]
(let [c (Double/parseDouble (.getText temp-text))]
(.setText fahrenheit-label
(str (+ 32 (* 1.8 c)) " Fahrenheit"))))))
(doto frame
(.setLayout (GridLayout. 2 2 3 3))
(.add temp-text)
(.add celsius-label)
(.add convert-button)
(.add fahrenheit-label)
(.setSize 300 80)
(.setVisible true))))
(celsius)
Conclusion
Well, I guess I'm on the road to Lisp. So far I'm sold - there are lots of great ideas in the Lisp paradigm, and Clojure seems very elegant and usable. Livecoding was totally alien to me before, and it seems like a much better - and more fun! - way of doing things than the conventional edit-compile-run cycle.
It's still a mystery how object orientation and multithreading are accomplished in Clojure, but it seems like those things are also doable. Macros are also still a mystery to me - people seem to think they are some kind of holy grail. So, though I've made some progress, there's still lots to look forward to!
Clojure
Clojure with Emacs and Slime/Swank on Ubuntu
Clojure Wikibook - Programming/Getting Started
Emacs for vi users
Emacs replace with Newline
Slime Tutorial
Slime Manual (PDF)
Clojure Tutorial for Non-Lispers
Clojure Web Server (in less than 100 lines)
20 Days of Clojure
concurrency talk by Rich Hickey - great overview of the hard concurrency problems that Clojure solves.
Saturday, February 28, 2009
Getting Started with JPA
Ingredients:
Ubuntu Linux 8.10
Glassfish 2.1 (how to install)
Eclipse Ganymede (Java EE version)
MySQL 5 (install with sudo apt-get install mysql-server mysql-client)
Steps:
Create a new project:
In Eclipse: New -> Project -> Dynamic Web Project -> name: "JPA_Test", Target Runtime: "GlassFish v2 Java EE 5" (if Glassfish is not listed, click New->Download additional Server Adapters->choose Glassfish ...) -> Finish
Create the following classes:
package test;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Customer {
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
andpackage test;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.transaction.UserTransaction;
@WebService
public class Test {
@PersistenceUnit
private EntityManagerFactory emf;
@Resource
private UserTransaction utx;
public boolean putCustomer(String name, int id) {
EntityManager em = emf.createEntityManager();
try {
utx.begin();
Customer c = new Customer();
c.setId(id);
c.setName(name);
em.persist(c);
utx.commit();
em.close();
} catch (Exception e) {
em.close();
e.printStackTrace();
return false;
}
return true;
}
public String getCustomerName(int id) {
EntityManager em = emf.createEntityManager();
Customer c = em.find(Customer.class, id);
return c.getName();
}
}
Under src/META-INF, put a file called persistence.xml with the following contents:<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="pu1" transaction-type="RESOURCE_LOCAL">
<class>test.Customer</class>
<properties>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
<property name="toplink.jdbc.user" value="root"/>
<property name="toplink.jdbc.password" value="root"/>
<property name="toplink.logging.level" value="INFO"/>
<property name="toplink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
Create the MySQL database to use:
#Start the MySQL Terminal:
mysql -u root -p
#create a database called test
mysql> CREATE DATABASE test;
Launch it:
In Eclipse: Right click on project -> Run As -> Run on Server -> Choose Glassfish as the server -> Finish
Test it:
Go to http://localhost:4848/ -> log in -> Web Services -> choose the "Test" web service -> click the "Test" button -> Enter some test info, like "Jack" as arg0 and "0" as arg2 -> click the "putCustomer" button -> see "True" if success, False or an exception if not.
If it doesn't work, the Glassfish Log Viewer tab in Eclipse is very useful.
Good luck!
Common Errors:
javax.xml.ws.soap.SOAPFaultException: Object: .... is not a known entity type. at ...
This means that you tried to use a class with JPA that you didn't declare in your persistence.xml. Sometimes this happens even if you did declare the type, and often a restart of the server will fix it (I hate server bugs like that).
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near...
This may mean that you are using a SQL keyword as a class or property name. Avoid all SQL keywords, like "value" or "column".
Sources:
Great tutorial by Sahoo
MySQL tips
JPA tutorial for NetBeans
Persistence example from Glassfish
Wednesday, January 21, 2009
Installing GlassFish
I put all these commands in a shell script, which can be executed with:
wget http://bitbucket.org/curran/ubuntuautomation/raw/21ad83206eca/install_glassfish_v2_1.sh && sh ./install_glassfish_v2_1.sh
Installing Glassfish:
(mkdir ~/opt)
cd ~/opt
# download glassfish
wget http://java.net/download/javaee5/v2ur2/promoted/Linux/glassfish-installer-v2ur2-b04-linux.jar
# unzip glassfish
java -Xmx256m -jar glassfish-installer-v2ur2-b04-linux.jar
cd glassfish/
# give the bin directory execute permissions
chmod -R +x lib/ant/bin
# run the setup
lib/ant/bin/ant -f setup.xml
# add the glassfish bin directory to the PATH environment veriable
echo "PATH=\$PATH:$HOME/opt/glassfish/bin export PATH" >> ~/.bashrc
Using Glassfish
# to start the server, restart the terminal (for PATH to update) then run
asadmin start-domain domain1
# to verify glassfish is working, go to http://localhost:8080/
# the admin GUI, which we'll use later, is at http://localhost:4848/
# user: admin pass: adminadmin
# to stop the server
asadmin stop-domain domain1
#To deploy a WAR file, put it in the autodeploy directory.
mv yourwarfile.war ~/opt/glassfish/domains/domain1/autodeploy/
#To view the last 50 lines of the log file:
tail -n 50 ~/opt/glassfish/domains/domain1/logs/server.log
Notes on MySQL and Flash access
# if you want MySQL support, put the lib in the right place:
wget http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.7.zip/from/http://mysql.mirror.redwire.net/
unzip mysql-connector-java-5.1.7.zip
mv mysql-connector-java-5.1.7/mysql-connector-java-5.1.7-bin.jar ~/opt/glassfish/lib/
# if you want to access a web service through a flash-based client, you need a permissive crossdomain.xml file placed in the domain root that looks something like this:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*"/>
<site-control permitted-cross-domain-policies="all" />
<allow-http-request-headers-from domain="*" headers="SOAPAction"/>
</cross-domain-policy>
Using the Ubuntu Package
On second thought I went back and tried using the Ubuntu package. Here are some tidbits of insight, though I eventually gave up on it.
This useful command finds all files and directories with "glassfish" in them:
sudo find / -name '*glassfish*'
Here are the important locations:
asadmin: /usr/share/glassfishv2/bin/asadmin
autodeploy directory: /var/lib/glassfishv2/domains/domain1/autodeploy
log file : /var/lib/glassfishv2/domains/domain1/logs
To (try to) deploy a WAR file, put it in the autodeploy directory.
To view the last 100 lines of the log file:
tail -n 100 /var/lib/glassfishv2/domains/domain1/logs/server.log
Again I gave up on the Ubuntu package. There is just too much wrong with it:
- The asadmin command doesn't work!
- The directories are exploded into two locations, I don't get that at all.
- Root permissions seems necessary to manipulate glassfish, this seems wrong.
- Somehow when I deployed a WAR with a web service in it, the web service doesn't actually deploy. Very frustrating.
Enjoy!
Flex Builder in Linux
(mkdir ~/opt)
cd ~/opt
mkdir flex
cd flex
# download eclipse (3.3 because newer versions of Eclipse break Flex Builder)
http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/europa/winter/eclipse-java-europa-winter-linux-gtk.tar.gz
# install eclipse
gunzip < eclipse-java-europa-winter-linux-gtk.tar.gz | tar xvf -
# create a "flexbuilder" launcher that points to this Eclipse
sudo sh -c 'echo "#!/bin/sh \n export MOZILLA_FIVE_HOME=\"/usr/lib/mozilla/\"
\n export ECLIPSE_HOME=\"\$HOME/opt/flex/eclipse\" \n \$ECLIPSE_HOME/eclipse \$*" > /bin/flexbuilder'
sudo chmod +x /bin/flexbuilder
#to increase memory (sometimes this is a problem), add the following to the eclipse command in the launch script:
#-vmargs -Xms128m -Xmx1024m -XX:MaxPermSize=128m
#!/bin/sh
export MOZILLA_FIVE_HOME="/usr/lib/mozilla/"
export ECLIPSE_HOME="$HOME/opt/flex/eclipse"
$ECLIPSE_HOME/eclipse -vmargs -Xms128m -Xmx1024m -XX:MaxPermSize=128m$*
# download flex builder
wget http://download.macromedia.com/pub/labs/flex/flexbuilder_linux/flexbuilder_linux_install_a4_081408.bin
# install flex builder
chmod +x flexbuilder_linux_install_a4_081408.bin
./flexbuilder_linux_install_a4_081408.bin
# under "Where Would You Like Flex Builder Installed?", set it to
/home/yourusername/opt/flex/flexbuilder
# under "Please Choose an Existing Eclipse Folder" set it to
/home/yourusername/opt/flex/eclipse
Alt+F2 -> type "flexbuilder" to launch.
I would advise to keep separate workspaces for Flex and Java projects, because I've seen some funky behavior that indicates the Flex Builder plugin interferes with some Java features.
Lets try it out:
In Eclipse -> New -> Flex Project -> give a name -> Finish
Paste the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text="Hello Flex in Linux!"/>
</mx:Application>
F11 to run, it should pop up in Firefox.Enjoy!
Monday, January 19, 2009
Flex, WebServices, Glassfish, Eclipse
I was able to get a Flex client to invoke my first Web Service. I found that on the server side, a Web Service is trivial to code and deploy in a GlassFish server from Eclipse - a welcome relief from the complex BlazeDS configurations we've been dealing with. To make an existing class into a Web Service, only a @WebService annotation is needed. On the client side, the invoking code is pretty straightforward - just setting up a few listeners for response and faults. I observed that the Web Service call time (from a client on the same local network as the server, but a different machine) consistently has a pretty even distribution between 15 and 65 milliseconds.
This guide details steps in Ubuntu Linux for creating an end to end system with a Flex web GUI which invokes a Web Service in a Glassfish server. The steps are as follows, assuming a fresh Ubuntu:
- Install OpenJDK, Eclipse, and GlassFish
- Configure Eclipse for GlassFish
- Write, deploy, and test an "Echo" Web Service
- Install FlexBuilder Linux Alpha
- Write the "Echo" client
Install OpenJDK and Eclipse
Install GlassFish
Configure Eclipse for GlassFish
In Eclipse:
New -> Project -> Web -> Dynamic Web Project -> Next ->
under "Target Runtime" -> New... -> click "download additional server adapters" ->
select "GlassFish Java EE 5 Server" -> Next -> accept the terms, Finish -> OK -> Yes, restart now
New -> Dynamic Web Project -> Next ->
Name:EchoService
Make sure "Target Runtime" is set to "GlassFish v2 Java EE 5"
-> Finish
Right click EchoService/WebContent/index.jsp -> Run As -> Run on Server -> localhost GlassFish should be automatically selected, Finish
In the console, you'll be prompted for the admin username and password - enter user: admin, pass:adminadmin
If all goes well you should see an emphatic Hello World!
Write, deploy, and test an "Echo" Web Service
In the EchoService project -> New -> Class -> Name:Echo, Package:echo -> Finish
Paste the following:
package echo;
import javax.jws.WebService;
@WebService
public class Echo {
public String echo(String input) {
return input;
}
}
The only thing you need to do to write a web service is to add the @WebService annotation.Right click Echo.java -> Run As -> Run on Server -> Finish
Eclipse will display an error page at "http://localhost:8080/EchoService/WEB-INF/classes/echo/Echo.java", but thats fine, because that's not what we're trying to accomplish.
To see the service, use the GlassFish admin GUI
Go to http://localhost:4848/ user: admin pass: adminadmin
On the left panel, click "Web Services" -> Echo -> Test ->
follow the http link (http://localhost:8080//EchoService/EchoService?Tester)
Enter "Hello World", then you should see the SOAP messages:
SOAP Request:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns2:echo xmlns:ns2="http://echo/">
<arg0>Hello World!</arg0>
</ns2:echo>
</S:Body>
</S:Envelope>
SOAP Response:<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:echoResponse xmlns:ns2="http://echo/">
<return>Hello World!</return>
</ns2:echoResponse>
</S:Body>
</S:Envelope>
Install Flex Builder
Write the "Echo" client
Create an EchoService Flex Client (sources: here and here and here (source code), Flex docs were also useful)
The URL of your WSDL file is at http://localhost:8080//EchoService/EchoService?WSDL
The following MXML code defines a simple GUI which calls the EchoService
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
private var startTime:int;
private var endTime:int;
private function button_click():void {
webService.echo.send(textInput.text);
startTime = getTimer();
timeLabel.text = "";
}
private function echo_result(evt:ResultEvent):void {
resultLabel.text = "Result: "+evt.result.toString()
calcTime();
}
private function echo_fault(evt:FaultEvent):void {
Alert.show(evt.type);
calcTime();
}
private function calcTime():void {
endTime = getTimer();
timeLabel.text = "Time: " + (endTime - startTime) + "ms";
}
]]>
</mx:Script>
<mx:WebService id="webService"
<!-- replace this ip address with your own -->
wsdl="http://129.63.16.175:8080//EchoService//EchoService?WSDL">
<mx:operation name="echo"
resultFormat="object"
result="echo_result(event);"
fault="echo_fault(event);">
</mx:operation>
</mx:WebService>
<mx:Button id="button" label="Call service" click="button_click();" />
<mx:Label text="input:" />
<mx:TextInput id="textInput" text="Hello Flex!"/>
<mx:Label id="timeLabel" />
<mx:Label id="resultLabel" />
</mx:Application>
Replace the ip of the web service with "localhost" or your server ip, which you can find by executing
ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' |cut -d: -f2 | awk '{ print $1}'
Alternatively, you could set up the web service in ActionScript as opposed to MXML:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.rpc.soap.WebService;
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
private var startTime:int;
private var endTime:int;
private var webService:WebService;
private function init():void{
webService = new WebService();
//replace this ip address with your own
webService.wsdl = "http://129.63.16.175:8080//EchoService//EchoService?WSDL"
webService.echo.resultFormat = "object"
webService.echo.addEventListener("result", echo_result);
webService.echo.addEventListener("fault", echo_fault);
webService.loadWSDL();
}
private function button_click():void {
webService.echo.send(textInput.text);
startTime = getTimer();
timeLabel.text = "";
}
private function echo_result(evt:ResultEvent):void {
resultLabel.text = "Result: "+evt.result.toString()
calcTime();
}
private function echo_fault(evt:FaultEvent):void {
Alert.show(evt.type);
calcTime();
}
private function calcTime():void {
endTime = getTimer();
timeLabel.text = "Time: " + (endTime - startTime) + "ms";
}
]]>
</mx:Script>
<mx:Button id="button" label="Call service" click="button_click();" />
<mx:Label text="input:" />
<mx:TextInput id="textInput" text="Hello Flex!"/>
<mx:Label id="timeLabel" />
<mx:Label id="resultLabel" />
</mx:Application>
Notes:
Build Failing due to Constructor issue
I was confused for a while about this error:
CLI171 Command deploydir failed : Deploying application in domain failed; Deployment Error -- Exception occured in the wsgen process javax.xml.ws.WebServiceException: Unable to create JAXBContext
BUILD FAILED
/home/curran/workspace/.metadata/.plugins/org.eclipse.jst.server.generic.core/serverdef/sunappsrv-ant.xml:203: The following error occurred while executing this line:
/home/curran/workspace/.metadata/.plugins/org.eclipse.jst.server.generic.core/serverdef/sunappsrv-ant.xml:119: exec returned: 1
I realized by reading the log file and reading this that the reason is because the exception type my service threw didn't have a no-argument constructor, which is apparently a requisite property of objects you send over the wire FROM a seb service.
Tracing Server-side Exceptions
they are appended to the log file at ~/opt/glassfish/domains/domain1/logs/server.log
To see the latest exceptions:
cat ~/opt/glassfish/domains/domain1/logs/server.log
Adding JARS to the server code dependency
put the jars you need into WebContent/WEB_INF/lib of your project
Enjoy!
Sunday, January 18, 2009
SOA in Eclipse Links
Here's some raw incoherent notes for setup of Eclipse, OpenDJK, and Tomcat in Ubuntu 8.10.
Install OpenJDK and Eclipse
# Install Tomcat manually. Don't use the Ubuntu tomcat6 package, because it spreads tomcat across the filesystem, making it difficult to configure Eclipse.
# Download tomcat
cd ~/opt
wget http://www.ip97.com/apache.org/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz
tar -zxvf apache-tomcat-6.0.18.tar.gz
# Start the server
~/opt/apache-tomcat-6.0.18/bin/startup.sh
#Go to http://localhost:8080/ to test
#This is the command to shutdown
~/opt/apache-tomcat-6.0.18/bin/shutdown.sh
Configure the Tomcat runtime in Eclipse:
In Eclipse, at Window -> Preferences -> Server -> Runtime Environment -> Add -> Apache Tomcat v6.0 -> Next -> set "Tomcat Installation Directory" to /opt -> Finish -> OK
Download Apache MyFaces libraries
cd ~/opt
wget http://mirror.its.uidaho.edu/pub/apache/myfaces/binaries/myfaces-core-1.2.5-bin.zip
unzip myfaces-core-1.2.5-bin.zip
# we need jet another jar that nobody mentioned
cd myfaces-core-1.2.5-bin/lib
wget http://download.java.net/maven/1/jstl/jars/jstl-1.2.jar
In Eclipse:
Project -> Properties -> Project Facets -> check "JavaServerFaces"
in the configuration, add ALL the jars in myfaces-core-1.2.5-bin/lib
Links:
Symbolic Links Advice
Tomcat in Ubuntu: apt-get vs manual install
Ubuntu Linux
Ubuntu Linux is a complete free operating system - a competitor to Windows and Mac build with a philosophy of openness rather than a proprietary model. Linux alone (the "kernel") provides the bare essentials of an operating system, so people package it into readily usable forms - together with many open source applications and components. These are called distributions. Presently, Ubuntu is the most popular Linux distribution. It makes Linux simple for anyone to set up and use.
Getting Started
To install Ubuntu, download the latest version, burn it to a CD, and boot to the CD. You can try it out without installing or risking anything. This gives you an impression of the look and feel, and lets you try preinstalled applications, but is much slower than normal because it's running directly off the CD. You can install Ubuntu alongside an existing Windows installation, as a "dual boot" setup where you can choose when you start the computer which system to use. This is the default setting in the installer.
Once you have it installed, you can figure out what everything is by clicking or right clicking on it. You can customize the panels as much as you want - delete things, add things by dragging and dropping.
Installing Programs
One of the most different things from Windows is the way in which software is installed and managed. In Ubuntu, there is an entire body of software dedicated to installing, updating, and uninstalling applications in the form of "packages". This is called a package manager. Ubuntu's package manager is APT - Advanced Packaging Tool.
Ubuntu maintains a huge list of applications that can be automatically installed by the package manager. To install or remove programs, you can go to Applications -> Add/Remove, which lets you browse and search packages. To install or uninstall something, check or uncheck the box next to the package, then hit "Apply Changes." After a program is installed, it will appear in the "Applications" menu, filed in the right place.
Another program besides Ubuntu's "Add/Remove Programs" which lets you graphically manage packages is Synaptic - it also uses APT under the hood.
Standard Tools
Ubuntu comes preinstalled with open source alternatives for most tools most people use already:
- Office -> OpenOffice
- Photoshop -> GIMP
- Internet Explorer, Safari -> Firefox
- AIM (or any IM client) -> Pidgin
- Skype -> Egika Softphone
- Outlook -> Evolution Mail and Calendar
Keyboard Shortcuts
There are numerous standard keyboard shortcuts which make working in Ubuntu very efficient:
- Alt+tab - switch between windows
- Control+alt+ left/right arrow keys - switch between desktops
- Alt+F4 - close the current window
- F11 - fullscreen mode
- F2 - rename a file
The Terminal
The terminal is very powerful. It allows you to enter commands to the operating system directly. Most stuff that you can do in Ubuntu with menus, windows, and buttons can probably also be done by entering a command in the terminal. It can be found under Applications -> Accessories -> Terminal.
One common use for the terminal is to install programs. For example, to install Wine, a system which lets you run most Windows programs in Linux, can be installed with one command:
sudo apt-get install wine
"sudo" gives you the power to change system files (you must manually enter your password - this is one reason why Linux is so secure)
"apt-get install" is the command to access the installation mechanism of Ubuntu's package manager APT (Advanced Packaging Tool)
"wine" is the name of the Ubuntu package you want APT to install. There are thousands of Ubuntu packages available.
You could also install any package from Applications -> Add/Remove (in fact, that program uses the apt-get install command), but once you know the package names of the programs you use often, you'll find it's faster to use the terminal.
Graphics Drivers
Ubuntu can readily install proprietary graphics drivers for you (NVidia, ATI), but you need to explicitly do it: System -> Administration -> Hardware Drivers -> click the one you want -> Activate (restart probably required). These drivers are not automatically installed because they are not open source - they are packages containing propreitary software.
Desktop The Infamous Desktop Cube
If you have a decent graphics card, and drivers installed, then some desktop effects should be enabled by default:
- Window key+ e - show all desktops
- Shift+alt+up arrow - show all windows
- Window key+n - invert the colors of the current window
sudo apt-get install compizconfig-settings-manager
Now open System -> Preferences -> CompizConfig Settings Manager. There, under "Desktop" check the box next to "Desktop Cube" (click yes, disable Desktop Wall) and also check "Rotate Cube" (Effects -> 3D Windows is cool too). Now try control+alt+arrows to switch between desktops. Control+alt+drag mouse lets you rotate the cube.
I hope you enjoy Ubuntu!
Please comment on this post if you have questions (such as "how do I do xyz that's really easy in Windows?"), comments, or suggestions for this introduction.
Eclipse Java development in Ubuntu
In Ubuntu 8.10, here's how I got set up for Java EE development using Eclipse and OpenJDK.
Install Java:
sudo apt-get install openjdk-6-jdk -y
Install Eclipse
I don't recommend apt-get install eclipse, it installs an old version doesn't work for me. Install eclipse manually instead(taken from this guide):
# Download the latest eclipse archive
mkdir ~/opt
cd ~/opt
wget http://mirrors.ibiblio.org/pub/mirrors/eclipse/technology/epp/downloads/release/ganymede/SR2/eclipse-jee-ganymede-SR2-linux-gtk.tar.gz
tar xzvf eclipse-jee-ganymede-SR2-linux-gtk.tar.gz
# create the launcher script and give it execute permissions
sudo sh -c 'echo "#!/bin/sh \n export ECLIPSE_HOME=\"\$HOME/opt/eclipse\" \n \$ECLIPSE_HOME/eclipse \$*" > /bin/eclipse'
sudo chmod +x /bin/eclipse
Now you can run eclipse by hitting alt+f2 and typing "eclipse"
Script
I created a shell script of these instructions, and it can be executed with:
wget http://bitbucket.org/curran/ubuntuautomation/raw/aa93f53ada5a/install_eclipse.sh && sh ./install_eclipse.sh
Enjoy!
Links:
Ubuntu Eclipse guide
A nice installation tutorial
Another good Ubuntu tutorial
Saturday, January 17, 2009
WSAS IDE Broken
Download WSAS v2.3
unzip to C:\
in C:\wso2wsas-2.3\bin execute install.bat (JAVA_HOME must be set first)
choose 1) Eclipse WTP Plugin Installation
at "Please enter Eclipse WTP Home :", enter C:\Program Files\eclipse (or wherever yours is)
success!
Open Eclipse
Window -> Preferences -> Web Services -> WSAS Preferences -> set "WSAS Runtime" to "C:\wso2wsas-2.3" -> OK
New -> Project -> Web -> Dynamic Web Project -> Next -> under "Target Runtime" hit "New..." -> WSO2 -> WSO2 WSAS -> Finish -> ProjectName: "TestService"
I ran into a bug and got really frustrated, so I posted this to the WSAS Forum:
Hello, I am trying to get started with WSAS IDE, but constantly having the same problem. I followed this guide to get started. I am using Eclipse Ganymede for Java EE version 3.4.1, and WSAS 2.3. I'd like to use the beta, but it doesn't contain the WSAS IDE installer (or does it? am I missing it?).
Here's the bug: In both Windows XP and Ubuntu Hardy, when I go New -> Project -> Web -> Dynamic Web Project -> set Target Runtime to WSO WSAS, I get the error message "Runtime "WSO2 WSAS" is invalid. Missing classpath entry \serverRootDirectory\lib"
The problem is documented by others here and here. The only solution I have seen is to unjar org.wso2.wsf.ide.server.wsas-2.2.jar, edit the file wsas.serverdef, setting the "default" field to point to your WSAS directory, rejar the file, and replace the old jar.
This is ridiculous. I really want to use WSAS IDE in my group, but I'll have a hard time convincing the group to adopt it when it requires something this silly to get working at all.
This bug is a deal breaker.
Does anyone know if this will be fixed in 3.0? Is there a recommended older version that doesn't have this problem?
Thanks very much, any help is greatly appreciated!
Links:
WSO Tutorial from 2007
IBM Tutorial from 2008 (really good!)
WSAS Documentation
WSAS IDE Instructions
Forum Thread on classpath error
Tuesday, December 9, 2008
Why isn't it easy in python to create an array of all zeros?
I am very frustrated that this seems nearly impossible. This should be trivial, but I see no built in Python function to do this.
Java -> int[] a = new int[n];
Python -> a = []; for i in range(0,5): a.append(0)
There must be a better way! Why is this so hard to find? I came across this page who said "just use zeros(n)" .. well ..
zeros(n) results in "NameError: name 'zeros' is not defined" ... oh, you need "import numpy"? thanks for leaving that detail out completely...
I need to import something to create an array of a given size containing all zeros? what? ...but wait,
import numpy; results in "ImportError: No module named numpy" Woah, NumPy is not there by default? I need to install an extra package, which other machines aren't guaranteed to have, meaning my code has an extra dependency just because it creates an zeroed array in one line?
Why isn't this easy? Python has been good to me most of the time, but this is so frustrating - why force the programmer to iterate through an array of [1,2,3,4,5] adding 5 zeros, either that or install an extra package? This is nuts.
I'd like to think that I am the one missing something, and there is a better way. Do you know of one?
**update**
Found it:
Python: a=[0]*n
Java: int[] a = new int[n]
much better.
jeez that took way too long to find. Here are some search beacons for people who have the same issue:
how to create a n array of length in in python
python predetermined size array
python zero function missing
Monday, November 17, 2008
Global String Replace in all PHP files in a given directory tree
To fix this, I needed to replace all instances of the hard-coded table name 'wp_email_list' in all the PHP files (all in the ./temp directory) with something else, say 'wp_email_list_2', before running the install script. I figured out how to do this with one line of Unix:
find ./temp -name '*.php' | xargs sed -i 's/wp_email_list/wp_email_list_2/g'
Here's where it's used
Friday, November 14, 2008
Interfacing to R from Java
It seems there are basically two options: JRI and Rserve. JRI interfaces directly with R using JNI, whereas Rserve allows communication to R through TCP/IP. From a little reading, it seems that JRI requires a bunch of funky setup, and based on the examples the code ends up ugly (lots of unnecessary details). Rserve is actually an R package that you can install with one command, the client is just one jar, and the Java invocation code looks very elegant in comparison with the JRI code (code from the Rserve site):
Rconnection c = new Rconnection();
double d[]=c.eval("rnorm(10)").asDoubleArray();
This is exactly what I need - acces to R's eval function! I chose to go the Rserve route. Here's how I did it in Ubuntu Linux and Eclipse:#install R
sudo apt-get install r-base
#install rserve
sudo apt-get install r-cran-rserve
#start Rserve (it looks crazy, but it works)
R CMD Rserve
#In Eclipse, make a new Java project called RTest
#download the Java client library into the project directory
cd ~/workspace/RTest/
wget http://stats.math.uni-augsburg.de/Rserve/dist/JRclient-RF503.jar
#In Eclipse, right click the jar -> build path -> add to build path
#make class:
package test;
import org.rosuda.JRclient.RSrvException;
import org.rosuda.JRclient.Rconnection;
public class RTest {
public static void main(String[] args) {
Rconnection c;
try {
c = new Rconnection();
double d[]=c.eval("rnorm(10)").asDoubleArray();
for(double n:d)
System.out.println(n);
} catch (RSrvException e) {
e.printStackTrace();
}
}
}
Run and be merry!I also figured out how to start Rserve from within Java. Here's the code:
public static void main(String[] args) {
Rconnection c = getLocalRconnection();
if (c != null) {
try {
double[] d = c.eval("rnorm(10)").asDoubleArray();
for (double n : d)
System.out.println(n);
} catch (RSrvException e) {
e.printStackTrace();
}
}
}
private static Rconnection getLocalRconnection() {
try {
return new Rconnection();
} catch (RSrvException e) {
//If we get this kind of error, it may be because Rserve is not running
if (e.getMessage().equals("Cannot connect: Connection refused")) {
try {
String rserveStartCommand = "R CMD Rserve --vanilla";
//do a blocking call to the shell command for starting Rserve
int exitValue = Runtime.getRuntime().exec(rserveStartCommand).waitFor();
//if it returned success, try connecting again
if (exitValue == 0)
return new Rconnection();
//otherwise, Rserve is probably not installed
else
System.err.println("Could not start Rserve - is it installed properly? Shell command \""+rserveStartCommand+"\" exited with exit value "+exitValue+".");
} catch (Exception e1) {
e1.printStackTrace();
}
}
else
e.printStackTrace();
}
return null;
}
Enjoy!
Links:
JRI site
RServe Java Client site
Thursday, November 13, 2008
First Stab: JAX-WS Web Services in Ubuntu
From a fresh Ubuntu 8.10 install:
sudo apt-get install openjdk-6-jdk glassfishv2 -y
Now the server is installed and started - go to http://localhost:8080/ to see.
I guess install-dir is /usr/share/glassfishv2
..from QuickStart...
Add path to PATH:
echo "PATH=\$PATH:/usr/share/glassfishv2/bin
export PATH" >> ~/.bashrc
restart terminal
After some hunting, I found from the config file (asenv.conf) from the line:
AS_DEF_DOMAINS_PATH="/var/lib/glassfishv2/domains"
that the "domains" directory is here (different from the outdated QuickStart):
/var/lib/glassfishv2/domains
Deploy a test:
wget http://glassfish.dev.java.net/downloads/quickstart/hello.war
mv hello.war /var/lib/glassfishv2/domains/domain1/autodeploy/
It worked! go to http://localhost:8080/hello/
- War files can be deployed in GlassFish by putting them in autodeploy.
Go to http://localhost:4848/ user: admin pass: adminadmin
sweet!
...from Building a JAX-WS Application in the Metro Environment...
wget https://metro.dev.java.net/getting-started/wsit-jaxws-fromjava.zip
unzip wsit-jaxws-fromjava.zip
rm wsit-jaxws-fromjava.zip
cd wsit-jaxws-fromjava/
AS_HOME=/usr/share/glassfishv2/bin
export AS_HOME
ant server
it breaks because it's expecting domains/domain1 to be under /usr/share/glassfishv2/bin, but instead it's under /var/lib/glassfishv2/.
comment out line 235 of build.xml
try again:
ant server
Now there is a war, which we can move into autodeploy:
sudo mv ./build/war/wsit-jaxws-fromjava.war /var/lib/glassfishv2/domains/domain1/autodeploy/
Verify that it's working:
http://localhost:8080/wsit-jaxws-fromjava/addnumbers?wsdl
building the client:
and ///arrgh - persueing another path, this ant execution is all messed up
...using Developing Metro in Eclipse...
Eclipse can't access the domain. solution [seems like a hack - why is is like this in the first place? is it normal for the root to own the default domain?]:
sudo chmod -R 777 /var/lib/glassfishv2
..after following instructions...
it works!!
..Addendum..
to start glassfish, execute
/usr/share/glassfishv2/bin/asadmin start-domain domain1
user: admin
pass: adminadmin
Links:
Glassfish: getting started
Getting Started with Metro
Some guy's installation notes
Developing Metro in Eclipse
Wednesday, November 12, 2008
Recursive Word Count
wc -l `find . -name *.java`
Ahh, beautiful!
Wednesday, October 29, 2008
Wordpress Email Notifications
In your wordpress directory (the one which contains wp-content):
wget http://www.watershedstudio.com/files/email_notification_v2.3.1.zip
unzip email_notification_v2.3.1.zip -d ./temp
#The following line is a hack to use a different table name than the default (to keep two installations in the same database distinct)
#find ./temp -name '*.*' | xargs sed -i 's/wp_email_list/wp_email_list_2/g'
cp -r temp/maillist/ ./maillist/
cp -r temp/wordpress/wp-content/plugins/wp-email-notification/ ./wp-content/plugins/wp-email-notification/
chmod 666 maillist/wpemn_config.php
rm -r ./temp
rm email_notification_v2.3.1.zip
open in a browser yoursite.com/maillist/install.php
In the installer, be sure to set: Default Notification Value: Yes - this triggers sending notifications for new posts.
After finishing that, remove the installer:
rm maillist/install.php
Go to yoursite.com/wp-admin/plugins.php and click "activate" next to the entry WordPress Email Notification Plugin v2.3.1
Now you should have an admin GUI under Manage -> Email Notification
The last thing is to add a text box somewhere for the user to subscribe to the mailing list. We need get our hands dirty and edit some PHP to do this. I wanted to add it to the sidebar, so I added
<li><h3>Email Notifications</h3>
<form method="post" action="maillist/index.php">Enter your e-mail address here to receive notifications of new posts<br />
<input type="text" name="email" size="12" maxlength="50" />
<input type="submit" name="submit" value="Sign me up!" />
</form>
</li>
to the file wp-content/themes/aeros/sidebar.php (I'm using the aeros theme, this will be whatever theme you are using, and the placement may be different), right before the end - before these lines</ul>
</div><!-- end sidebar -->
It works!!!
Email Notification Plugin - Instructions taken mostly from the install.txt in this download.
Monday, October 27, 2008
Algorithms in LaTeX
If you're using texlive, you can install the clrscode package by installing the following Ubuntu package:
sudo apt-get install texlive-science
Tuesday, September 30, 2008
Using Vim for LaTeX
The puzzle I solved and want to share with the world is how to add the feature that ctrl+F11 maps to the action of compiling the currently open document and clearing the terminal when no errors occurred, using one console command. Here it is:
echo 'map
Enjoy!
Compiling LaTeX within vim
Wednesday, September 24, 2008
Installing a WordPress Blog
# ssh into the server:
ssh username@host.name
# Create the directory for the blog:
cd public_html
mkdir blogdirectory
# Download and unzip WordPress there
cd blogdirectory
wget http://wordpress.org/latest.zip
unzip wordpress-2.6.3.zip
mv wordpress/* ./
rm wordpress-2.6.3.zip
rm -r wordpress
# Edit wp-config.php
mv wp-config-sample.php wp-config.php
# Edit the database details of wp-config.php
#Install to the Database
Navigate in a web browser to the location of the blog, this will start an install process which asks for a blog title and your email. That's it!
Editing Themes
I wanted the posts to show the author. It turns out there is no GUI for this, you need to edit a PHP file. It turned out to be very easy - just change line 11 in blog/wp-content/themes/default/index.php from
<small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>
to<small><?php the_time('F jS, Y') ?> by <?php the_author() ?> </small>
Also, you could give write permissions to all the theme files, so you could use the WordPress Theme Editor GUI for editing the PHP files:
cd blog
chmod -R 777 wp-content
Password Protecting the Directory
cd blog
# Create the password file
htpasswd -c .htpasswd username
# Create the .htaccess file, changing /full/path/to/.htpasswd to the path to the blog directory, and "Password Protected Site"" to the message you want displayed to users as the password is being asked for
echo "AuthUserFile /full/path/to/.htpasswd
AuthType Basic
AuthName \"Password Protected Site\"
Require valid-user" > .htaccess
I moved the blog directory without following the instructions, so I had to do some rearranging which involved creating a symlink from the old directory to the new one (where newlocation and oldlocation are the full paths to your new and old locations on the same server)
ln -s newlocation oldlocation
Then I changed the URL in the WordPress admin GUI to the new one (accessed from the old location through the symlink) Then I removed the symlink
unlink oldlocation
Installing a Theme
I picked the Aero theme from here
cd wp-content/themes/
wget http://wordpress.org/extend/themes/download/aeros.1.0.4.zip
unzip aeros.1.0.4.zip
rm aeros.1.0.4.zip
Now you can navigate to the themes page of the GUI and select the new theme.
Changing the Maximum Upload Size
I tried to upload media from the posts page, and it told me "This file is too big. Your php.ini upload_max_filesize is 2M" I found this post, and their method worked - adding some stuff to .htaccess. Here's what I did:
cd blog
echo "php_value upload_max_filesize 30M
php_value post_max_size 30M
php_value memory_limit 128M
php_value max_execution_time 3600" >> .htaccess
Using LaTeX
Here is the site of the LaTeX Wordpress plugin. Here's how to install it:
cd blog/wp-content/plugins
wget http://downloads.wordpress.org/plugin/latex.zip
unzip latex.zip
rm latex.zip
cd ../../wp-content
mkdir cache
chmod 777 cache
Now go to the plugins page from the WordPress GUI, and click "Activate" next to "Latex for WordPress" to enable the plugin. Now, text surrounded by $$...$$ will appear as beautiful rendered image of LaTeX. This plugin uses the WordPress.com LaTeX service. Try this for example:
$$\Theta = \Omega(\delta)$$
Appears as
You can also add email notifications of posts.
Enjoy!
Links:
Official Install Page
move instructions
LaTeX plugin
Tuesday, September 23, 2008
Monday, September 22, 2008
Setting Up Tomcat
#Install OpenJDK
sudo apt-get install openjdk-6-jre openjdk-6-jdk -y
sudo update-java-alternatives -s java-6-openjdk
#Install Tomcat
sudo apt-get install tomcat5.5 -y
We can see it's running by executing
sudo /etc/init.d/tomcat5.5 status
stop it with
sudo /etc/init.d/tomcat5.5 stop
start it with
sudo /etc/init.d/tomcat5.5 start
Links:
Nice Setup guide
Password Protecting a Folder
Monday, September 8, 2008
Starting to Learn Flex
#install the Flash plugin
sudo apt-get install flashplugin-nonfree
# Install Sun's Java
sudo apt-get install sun-java6-jdk
the "java" command still points to the old version. We can change that with
sudo update-java-alternatives -s java-6-sun
# Install the Flex SDK (I chose the most recent fully Open Source version from the download page)
wget http://flexorg.wip3.adobe.com/flexsdk/3.1.0.2710/flex_sdk_3.1.0.2710_mpl.zip
sudo unzip -d /opt/flex_sdk_3 flex_sdk_3.1.0.2710_mpl.zip
sudo chmod +x /opt/flex_sdk_3/bin/mxmlc
rm flex_sdk_3.1.0.2710_mpl.zip
# Add the Flex compiler to your path
echo "# Flex stuff
PATH=\$PATH:/opt/flex_sdk_3/bin
export PATH" >> ~/.bashrc
# restart the terminal for the changes to take effect.
# test if it worked by typing "mxmlc"
I got the error:
bash: /opt/flex_sdk_3/bin/mxmlc: /bin/sh^M: bad interpreter: No such file or directory
What?! The dos newlines are causing errors in the shell script? Arrgh
sudo apt-get install tofrodos
sudo dos2unix /opt/flex_sdk_3/bin/mxmlc
# Compile and Run an Example (taken from Here)
# Put the following text in button.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="center" verticalAlign="center"
>
<mx:Button id="myButton" label="I'm a button!" />
</mx:Application>
# Compile it into an SWFmxmlc button.mxml
# Run it in firefox
firefox button.swf
Hooray!!!
..more to come
Links:
Installation Tips
Wikipedia: Flash, Flex, ActionScript
Adobe Flex Open Source download page
Older guide to installinf Flex in Ubuntu
Blog about learning Flash
Linux Flex Tutorial
Adobe Flex - Getting Started
FLEX and BlazeDS
Friday, September 5, 2008
Setting the Background with a Command
wget http://farm2.static.flickr.com/1121/1383497195_9baa091855_o.jpg -O ~/background.jpg
# Set the background
gconftool-2 -t string -s ~/background.jpg
Tuesday, September 2, 2008
Setting Up Synergy
Setting Up
On both computers, install Synergy (green commands can be pasted into the terminal with ctrl+insert)
sudo apt-get install synergy -y
We'll need the host names of the two computers to use in the config files. Go to the computer on the left and execute the command hostname. Here's a sample output:
$hostname
awesomedesktop
Now do the same for the machine on the right:
$hostname
awesomelaptop
One of them is going to be the server, lets say the one on the left - awesomedesktop. In the computer at the left, execute the following commands, but replace "awesomelaptop" with the hostname of the computer on the right.
screen1=`hostname`
screen2=awesomelaptop
Or, it the server is on the right, swap 1 and 2:
screen2=`hostname`
screen1=awesomelaptop
Paste all of this at once into the terminal:
echo "section: screens
$screen1:
$screen2:
end
section: links
$screen1:
right = $screen2
$screen2:
left = $screen1
end" > ~/.synergy.conf
To see the contents of the new file, execute
cat .synergy.conf
Getting it Going
On the computer on the left, start the synergy server by executing
synergys -f
On the computer on the right, start the client by executing
synergyc -f server-ip
where server-ip is replaced by the IP address of the server, which can be obtained by executing (on the server)
ifconfig
or to get only the IP address:
ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' |cut -d: -f2 | awk '{ print $1}'
Starting it Automatically
Automatically starting things go in ~/.profile, so we'll put our commands there.
On the server, execute:
echo synergys >> ~/.profile
On the client (again replacing server-ip):
echo synergyc server-ip >> ~/.profile
Enjoy!
Links:
Synergy documentation
Ubuntu Synergy Documentation
Assigning a Static IP address in Ubuntu
To find out your own IP and MAC address:
ifconfig
IP address is labeled "inet addr", and MAC address is labeled "HWaddr"
To manually assign your computer a static IP address given to you in the command line:
Temporarily
Permanently
Or use the GUI:
System -> Administration -> Network
Here you need to hit "Unlock" at the bottom. I missed this fact and thought the GUI was useless for a while.
I tried setting all the information from the command line, but it didn't work until I just opened and closed the GUI, so I guess I was missing some kind of initialization or reset command.
It was suggested that I need to change my link speed from 100 to 10, and duplex mode from full to half. To see your current configuration, use
sudo ethtool eth0
To set the link speed to 100, and set half duplex, execute
sudo ethtool -s eth0 speed 10 duplex half
To get assigned an IP address (or at least attempt to), execute
sudo dhclient eth0
You should see "bound to 169.168...." or something. If the address begins with 196.254...., then it was not assigned by the DHCP server, it was self-assigned, meaning it cannot connect to the internet.
Sunday, August 31, 2008
muParser
#Install the muParser library and headers
sudo apt-get install libmuparser0 libmuparser-dev -y
I was appalled to see that the sample code didn't work ("pi" was used but not defined)! The lines in red are the changed I had to make to get it to work. Paste this into test.cpp:
#include "muParser/muParser.h"
#include <math.h>
// Function callback
double MyFunction(double a_fVal)
{
return a_fVal*a_fVal;
}
// main program
int main(int argc, char* argv[])
{
using namespace mu;
try
{
double fVal = 1;
Parser p;
p.DefineConst("pi", M_PI);
p.DefineVar("a", &fVal);
p.DefineFun("MyFunc", MyFunction);
p.SetExpr("MyFunc(a)*pi+min(10,a)");
std::cout << p.Eval() << "\n";
}
catch (Parser::exception_type &e)
{
std::cout << e.GetMsg() << "\n";
}
return 0;
}
Compile and run it withg++ test.cpp -lmuparser && ./a.out
Here's an example which takes an expression, and generates a table if input and output values:
#include "muParser/muParser.h"
#include <math.h>
using namespace mu;
using namespace std;
int main(int argc, char* argv[])
{
Parser p;
double x = 0;
char input[80];
p.DefineConst("pi", M_PI);
p.DefineConst("e", M_E);
p.DefineVar("x", &x);
cin >> input;
p.SetExpr(input);
try
{
for(x = -10; x <= 10;x++)
cout << "X = " << x << "\t" << input << " = " << p.Eval() << "\n";
}
catch (Parser::exception_type &e)
{
std::cout << e.GetMsg() << "\n";
}
return 0;
}
If you save it as table.cpp, compile and run withg++ table.cpp -lmuparser && ./a.out
Enter expressions into the console like this:
sin(x^2)
and you'll get this:X = -10 sin(x^2) = -0.506366
X = -9 sin(x^2) = -0.629888
X = -8 sin(x^2) = 0.920026
X = -7 sin(x^2) = -0.953753
X = -6 sin(x^2) = -0.991779
X = -5 sin(x^2) = -0.132352
X = -4 sin(x^2) = -0.287903
X = -3 sin(x^2) = 0.412118
X = -2 sin(x^2) = -0.756802
X = -1 sin(x^2) = 0.841471
X = 0 sin(x^2) = 0
X = 1 sin(x^2) = 0.841471
X = 2 sin(x^2) = -0.756802
X = 3 sin(x^2) = 0.412118
X = 4 sin(x^2) = -0.287903
X = 5 sin(x^2) = -0.132352
X = 6 sin(x^2) = -0.991779
X = 7 sin(x^2) = -0.953753
X = 8 sin(x^2) = 0.920026
X = 9 sin(x^2) = -0.629888
X = 10 sin(x^2) = -0.506366
Enjoy!
Links:
muParser web site
Thursday, August 28, 2008
CUDA in Ubuntu, a hack
This guide is written to work with a fresh installation of Ubuntu 8.04 (Hardy Heron).
Green means it is a command. You can paste lines into the console with ctrl+shift.
#install drivers from Ubuntu
sudo apt-get install nvidia-glx-new -y
sudo nvidia-xconfig
#reboot
sudo reboot
#install the toolkit (doesn't work with findcuda.CMake)
wget http://developer.download.nvidia.com/compute/cuda/1_1/Linux/toolkits/NVIDIA_CUDA_Toolkit_1.1_Ubuntu7_x86.run
chmod +x NVIDIA_CUDA_Toolkit_1.1_Ubuntu7_x86.run
sudo ./NVIDIA_CUDA_Toolkit_1.1_Ubuntu7_x86.run auto
rm NVIDIA_CUDA_Toolkit_1.1_Ubuntu7_x86.run
Alternatively, use the beta (works with findcuda.CMake):
wget http://developer.download.nvidia.com/compute/cuda/2.0-Beta2/linux/toolkit/NVIDIA_CUDA_Toolkit_2.0beta2_Ubuntu7.10_x86.run
chmod +x NVIDIA_CUDA_Toolkit_2.0beta2_Ubuntu7.10_x86.run
sudo ./NVIDIA_CUDA_Toolkit_2.0beta2_Ubuntu7.10_x86.run auto
rm NVIDIA_CUDA_Toolkit_2.0beta2_Ubuntu7.10_x86.run
#add environment variables
echo "# CUDA stuff
PATH=\$PATH:/usr/local/cuda/bin
LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/cuda/lib
export PATH
export LD_LIBRARY_PATH" >> ~/.bashrc
#restart the terminal for the changes to take effect
exit
#install the SDK (hit enter at all prompts)
wget http://developer.download.nvidia.com/compute/cuda/1_1/Linux/sdk/NVIDIA_CUDA_SDK_1.1_Linux.run
chmod +x NVIDIA_CUDA_SDK_1.1_Linux.run
./NVIDIA_CUDA_SDK_1.1_Linux.run
#install the libcuda.so file, which the Ubuntu installer doesn't do
wget http://us.download.nvidia.com/XFree86/Linux-x86/169.12/NVIDIA-Linux-x86-169.12-pkg1.run
chmod +x NVIDIA-Linux-x86-169.12-pkg1.run
./NVIDIA-Linux-x86-169.12-pkg1.run --extract-only
sudo mv NVIDIA-Linux-x86-169.12-pkg1/usr/lib/libcuda.so.169.12 /usr/lib/libcuda.so
rm ./NVIDIA-Linux-x86-169.12-pkg1.run
rm rm -r -f NVIDIA-Linux-x86-169.12-pkg1
#install build tools
sudo apt-get install build-essential libglut3-dev gcc-4.1 g++-4.1 -y
#set up gcc and g++ to use version 4.1 (otherwise we get compatibility issues)
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.1 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.1
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.2 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.2
#make the example projects
cd NVIDIA_CUDA_SDK/
make
#Run an example program and be overwhelmed with parallel bliss
~/NVIDIA_CUDA_SDK/bin/linux/release/fluidsGL
Ways to Install NVidia Drivers in Ubuntu
Using Ubuntu's Installer
sudo apt-get install nvidia-glx-new -y
sudo nvidia-xconfig
sudo reboot
Using EnvyNG
sudo apt-get install envyng-gtk -y
envyng -t
# type "1" to install NVidia drivers
# then "y" to restart
Using NVidia's Installer
#from http://www.nvidia.com/object/cuda_get.html -> Linux 32 bit
wget http://developer.download.nvidia.com/compute/cuda/2_0/linux/driver/NVIDIA-Linux-x86-177.67-pkg1.run
chmod +x ./NVIDIA-Linux-x86-177.67-pkg1.run
sudo /etc/init.d/gdm stop
sudo ./NVIDIA-Linux-x86-177.67-pkg1.run
rm ./NVIDIA-Linux-x86-177.67-pkg1.run
sudo /etc/init.d/gdm start
# this next step resolves a driver conflict.
# if we don't do this, the machine will start in low-graphics mode on reboot
sudo gedit /etc/default/linux-restricted-modules-common
# add 'nv' to DISABLED_MODULES ('DISABLED_MODULES="nv"')
sudo reboot
Failed CUDA Install Attempts
Using EnvyNG
# Install the NVidia drivers with EnvyNG
sudo apt-get update
sudo apt-get install envyng-gtk -y
envyng -t
# type "1" to install NVidia drivers
# then "y" to restart
# Install the CUDA Toolkit
wget http://developer.download.nvidia.com/compute/cuda/2_0/linux/toolkit/NVIDIA_CUDA_Toolkit_2.0_ubuntu7.10_x86.run
chmod +x NVIDIA_CUDA_Toolkit_2.0_ubuntu7.10_x86.run
sudo ./NVIDIA_CUDA_Toolkit_2.0_ubuntu7.10_x86.run auto
rm NVIDIA_CUDA_Toolkit_2.0_ubuntu7.10_x86.run
# add environment variables
echo "# CUDA stuff
PATH=\$PATH:/usr/local/cuda/bin
LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/cuda/lib
export PATH
export LD_LIBRARY_PATH" >> ~/.bashrc
# Install the CUDA SDK
wget http://developer.download.nvidia.com/compute/cuda/2_0/linux/sdk/NVIDIA_CUDA_SDK_2.02.0807.1535_linux.run
chmod +x ./NVIDIA_CUDA_SDK_2.02.0807.1535_linux.run
./NVIDIA_CUDA_SDK_2.02.0807.1535_linux.run
# press enter at both prompts
rm ./NVIDIA_CUDA_SDK_2.02.0807.1535_linux.run
# Install the build tools we need
sudo apt-get install build-essential libglut3-dev -y
# compile and run an example
cd NVIDIA_CUDA_SDK/
make
~/NVIDIA_CUDA_SDK/bin/linux/release/fluidsGL
FluidsGL runs but fails with:
cufft: ERROR: CUFFT_EXEC_FAILED
cufft: ERROR: /root/cuda-stuff/sw/rel/gpgpu/toolkit/r2.0/cufft/src/cufft.cu, line 119
cufft: ERROR: CUFFT_EXEC_FAILED
cufft: ERROR: /root/cuda-stuff/sw/rel/gpgpu/toolkit/r2.0/cufft/src/execute.cu, line 1038
cufft: ERROR: CUFFT_EXEC_FAILED
cufft: ERROR: /root/cuda-stuff/sw/rel/gpgpu/toolkit/r2.0/cufft/src/execute.cu, line 284
Using NVidia's Installer for Ubuntu 7.10
# --- Install the NVidia Driver ---
#from http://www.nvidia.com/object/
wget http://developer.download.
chmod +x ./NVIDIA-Linux-x86-177.67-pkg1.run
# Install build tools needed for the installer to compile the drivers
sudo apt-get install build-essential -y
sudo /etc/init.d/gdm stop
sudo ./NVIDIA-Linux-x86-177.67-
rm ./NVIDIA-Linux-x86-177.67-
sudo /etc/init.d/gdm start
#desktop effects are working! Success!
# --- Install the CUDA Toolkit and SDK
wget http://developer.download.
chmod +x NVIDIA_CUDA_Toolkit_2.0_
sudo ./NVIDIA_CUDA_Toolkit_2.0_
sudo apt-get install libglut3-dev -y
rm NVIDIA_CUDA_Toolkit_2.0_
wget http://developer.download.
chmod +x ./NVIDIA_CUDA_SDK_2.02.0807.
./NVIDIA_CUDA_SDK_2.02.0807.
#add environment variables
echo "# CUDA stuff
PATH=\$PATH:/usr/local/cuda/
LD_LIBRARY_PATH=\$LD_LIBRARY_
export PATH
export LD_LIBRARY_PATH" >> ~/.bashrc
rm ./NVIDIA_CUDA_SDK_2.02.0807.
Works great! until reboot, then the machine starts in low graphics mode. Any ideas on how to fix this?
FIXED! Solution: add 'nv' to DISABLED_MODULES in /etc/default/linux-restricted-modules-common,full instructions here
Thursday, August 14, 2008
OpenGL example: Rendering Cylinders and Spheres, with Point-Cylinder Inside Test
If you copy it into the file example.c, compile and run it with the command
gcc -lglut -lGL example.c && ./a.out
//This code is in the public domain.
#include <GL/glut.h>
#include <GL/gl.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define ESCAPE_KEY 27
float window;
float t = 0.0f;
int pointIsInsideCylinder(float x1, float y1, float z1, float dx,float dy, float dz, float lengthSquared,float radiusSquared ,float xTest,float yTest,float zTest)
{
float pdx = xTest - x1;
float pdy = yTest - y1;
float pdz = zTest - z1;
float dot = pdx * dx + pdy * dy + pdz * dz;
int pointIsInside = 0;
if( dot > 0 && dot < lengthSquared )
pointIsInside = pdx*pdx + pdy*pdy + pdz*pdz - dot*dot/lengthSquared < radiusSquared;
return pointIsInside;
}
int pointIsInsideCylinder_convenient( float x1, float y1, float z1, float x2,float y2, float z2, float radius, float xTest,float yTest,float zTest)
{
//these things need only to be computed once for a cylinder, and reused for each test point
float dx = x2 - x1;
float dy = y2 - y1;
float dz = z2 - z1;
float lengthSquared = pow(x2-x1,2)+pow(y2-y1,2)+pow(z2-z1,2);
float radiusSquared=radius*radius;
return pointIsInsideCylinder(x1,y1,z1,dx,dy,dz,lengthSquared,radiusSquared,xTest,yTest,zTest);
}
void renderCylinder(float x1, float y1, float z1, float x2,float y2, float z2, float radius,int subdivisions,GLUquadricObj *quadric)
{
float vx = x2-x1;
float vy = y2-y1;
float vz = z2-z1;
//handle the degenerate case of z1 == z2 with an approximation
if(vz == 0)
vz = .00000001;
float v = sqrt( vx*vx + vy*vy + vz*vz );
float ax = 57.2957795*acos( vz/v );
if ( vz < 0.0 )
ax = -ax;
float rx = -vy*vz;
float ry = vx*vz;
glPushMatrix();
//draw the cylinder body
glTranslatef( x1,y1,z1 );
glRotatef(ax, rx, ry, 0.0);
gluQuadricOrientation(quadric,GLU_OUTSIDE);
gluCylinder(quadric, radius, radius, v, subdivisions, 1);
//draw the first cap
gluQuadricOrientation(quadric,GLU_INSIDE);
gluDisk( quadric, 0.0, radius, subdivisions, 1);
glTranslatef( 0,0,v );
//draw the second cap
gluQuadricOrientation(quadric,GLU_OUTSIDE);
gluDisk( quadric, 0.0, radius, subdivisions, 1);
glPopMatrix();
}
void renderCylinder_convenient(float x1, float y1, float z1, float x2,float y2, float z2, float radius,int subdivisions)
{
//the same quadric can be re-used for drawing many cylinders
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
renderCylinder(x1,y1,z1,x2,y2,z2,radius,subdivisions,quadric);
gluDeleteQuadric(quadric);
}
void renderSphere(float x, float y, float z, float radius,int subdivisions,GLUquadricObj *quadric)
{
glPushMatrix();
glTranslatef( x,y,z );
gluSphere(quadric, radius, subdivisions,subdivisions);
glPopMatrix();
}
void renderSphere_convenient(float x, float y, float z, float radius,int subdivisions)
{
//the same quadric can be re-used for drawing many spheres
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
renderSphere(x,y,z,radius,subdivisions,quadric);
gluDeleteQuadric(quadric);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0,0,-7);
//define the cylinder
float x1 = sin(t);
float y1 = sin(t/2);
float z1 = cos(t*1.1);
float x2 = -sin(t*1.3);
float y2 = 0;
float z2 = -cos(t);
float radius = 0.03+(sin(t)/2+0.5)/3;
//render the cylinder
renderCylinder_convenient(x1,y1,z1,x2,y2,z2,radius,32);
//render spheres in a grid which are inside the cylinder
float gridSize = 20;
float xTest,yTest,zTest;
int x,y,z;
for(x = 0; x < gridSize,xTest = (float)x/gridSize*2-1; x++)
for(y = 0; y < gridSize,yTest = (float)y/gridSize*2-1; y++)
for(z = 0; z < gridSize,zTest = (float)z/gridSize*2-1; z++)
if(pointIsInsideCylinder_convenient(x1,y1,z1,x2,y2,z2,radius,xTest,yTest,zTest))
renderSphere_convenient(xTest,yTest,zTest,0.07,8);
t+=0.001;
glutSwapBuffers();
}
void InitGL(int Width, int Height)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING);
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
glEnable(GL_LIGHT1);
}
void keyPressed(unsigned char key, int x, int y)
{
if(key == ESCAPE_KEY)
{
glutDestroyWindow(window);
exit(1);
}
}
int main( int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(640, 480);
window = glutCreateWindow("");
glutDisplayFunc(&display);
glutKeyboardFunc(&keyPressed);
glutFullScreen();
glutIdleFunc(&display);
InitGL(640, 480);
glutMainLoop();
return 1;
}
Enjoy!
Wednesday, August 13, 2008
Rendering a Sphere in OpenGL
void renderSphere(float x, float y, float z, float radius,int subdivisions,GLUquadricObj *quadric)
{
glPushMatrix();
glTranslatef( x,y,z );
gluSphere(quadric, radius, subdivisions,subdivisions);
glPopMatrix();
}
void renderSphere_convenient(float x, float y, float z, float radius,int subdivisions)
{
//the same quadric can be re-used for drawing many spheres
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
renderSphere(x,y,z,radius,subdivisions,quadric);
gluDeleteQuadric(quadric);
}
A complete OpenGL example using this function can be found here.
Code to HTML
Point Cylinder Inside Test
void renderCylinder(float x1, float y1, float z1, float x2,float y2, float z2, float radius,int subdivisions,GLUquadricObj *quadric)
{
float vx = x2-x1;
float vy = y2-y1;
float vz = z2-z1;
//handle the degenerate case of z1 == z2 with an approximation
if(vz == 0)
vz = .00000001;
float v = sqrt( vx*vx + vy*vy + vz*vz );
float ax = 57.2957795*acos( vz/v );
if ( vz < 0.0 )
ax = -ax;
float rx = -vy*vz;
float ry = vx*vz;
glPushMatrix();
//draw the cylinder body
glTranslatef( x1,y1,z1 );
glRotatef(ax, rx, ry, 0.0);
gluQuadricOrientation(quadric,GLU_OUTSIDE);
gluCylinder(quadric, radius, radius, v, subdivisions, 1);
//draw the first cap
gluQuadricOrientation(quadric,GLU_INSIDE);
gluDisk( quadric, 0.0, radius, subdivisions, 1);
glTranslatef( 0,0,v );
//draw the second cap
gluQuadricOrientation(quadric,GLU_OUTSIDE);
gluDisk( quadric, 0.0, radius, subdivisions, 1);
glPopMatrix();
}
void renderCylinder_convenient(float x1, float y1, float z1, float x2,float y2, float z2, float radius,int subdivisions)
{
//the same quadric can be re-used for drawing many cylinders
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
renderCylinder(x1,y1,z1,x2,y2,z2,radius,subdivisions,quadric);
gluDeleteQuadric(quadric);
}
A complete OpenGL example using this function can be found here.Links:
Original Implementation
Tuesday, August 12, 2008
Blog to Book
I want to create a program which will read an RSS feed (of blog posts) and translate it into a (book-formatted) LaTeX document, including all the pictures.
My first step was to discover how to access the whole history of a blogger blog as a feed, which I found here - just add a "max-results" argument, like this:
http://lifeofahuman.blogspot.com/feeds/posts/default?max-results=500
We could write a feed reader from scratch using minidom like this guy, but there is a nice Python library for reading feeds called feedparser. To install it:
wget http://feedparser.googlecode.com/files/feedparser-4.1.zip
unzip feedparser-4.1.zip
sudo python setup.py install
To extract the title of the blog, and the titles and contents of the first 5 entries:
import feedparser
d = feedparser.parse("http://lifeofahuman.blogspot.com/feeds/posts/default?max-results=5")
print "Title: " + d.feed.title
print "Entries:"
for entry in d.entries:
print entry.title
print entry.content
If you copy this into readfeed.py, run it withpython readfeed.py
Here's, so now we need to translate the HTML into Latex...coming soon!
Links:
feedparser
tip about feed sizes from blogger
