=begin
# Simple script to retrieve all properties files, package them in the target directory,
# and add a comment to the top and bottom informing developers #to place entries at the bottom
# requires rubyzip (http://rubyzip.sourceforge.net/)
=end
require 'date'
require 'zip/zip'
class Properties_Packager
DECORATION = "#============================================="
HEADER_COMMENT =
DECORATION +
"\n#Please place all new additions at the bottom of the file\n" +
DECORATION
FOOTER_COMMENT =
DECORATION +
"\n#Packaged and processed on " + (Time.now.to_s ) + ". Please place all new entries after this section\n" +
DECORATION
@prop_files
attr_reader :prop_files, :HEADER_COMMENT
def initialize
@prop_files = []
@header_comment
end
private
def legit_file file
! (file.index("env.") != nil ||
file.index("junit") != nil ||
file.index("project.") != nil ||
file.index("#") != nil)
end
public
def obtain_properties_files(directory)
current_dir = Dir.open(directory)
for file in current_dir
next if(file == "." ||
file==".." ||
file=="target")
path = current_dir.path + "/" + file
if File.directory?(path)
obtain_properties_files(path)
else
if (legit_file file and file.index("properties") != nil)
puts "Adding " + path
@prop_files << path
end
end
@prop_files
end
@prop_files
end
def add_comments files
files.each do |file|
contents_buffer = []
current_lines = IO.readlines(file.to_s)
possible_header = current_lines[0]
if(! possible_header.strip.eql? DECORATION)
contents_buffer << HEADER_COMMENT
end
contents_buffer << IO.readlines(file.to_s).to_s
contents_buffer << FOOTER_COMMENT
open_file = File.open(file,"r+")
open_file.puts(contents_buffer)
open_file.close
end
end
def put_files_in_zip files, out_file_name
#if the file exists, erase it
if File.exists?(out_file_name)
File.delete(out_file_name)
puts "DELETED old zip file"
end
zipfile = Zip::ZipFile.new out_file_name, true
files.each do |file|
puts "zipping " + file.to_s
zipfile.add file, file.to_s
end
zipfile.close
end
end
zip_file = 'target/packaged_properties.zip'
packager = Properties_Packager.new
props = packager.obtain_properties_files('src/webapp')
packager.add_comments props
packager.put_files_in_zip props, zip_file
puts "Properties package ready for delivery #{zip_file}"
Tuesday, March 28, 2006
Ruby is just so beautiful
Thursday, March 23, 2006
Gentoo and Rails 1.0, sqlite3, fastcgi and lighttpd
added USE flags, fcgi lighttpd
emerged ruby-fcgi lighttpd
uncommented "mod_fastcgi" and "mod_redirect" in /etc/lighttpd.conf
emerged rails
yankes and configured lserver and lighttpd.conf per http://www.bigbold.com/snippets/posts/show/303
executed "rails todoapp"
copied lighttpd.config to todoapp/config and lserver to todoapp/script
updated config/database.yaml---
development:
adapter: sqlite3
database: db/database_dev.db
test:
adapter: sqlite3
database: db/database_test.db
production:
adapter: sqlite3
database: db/database_prod.db
---
executed "script/generate migration InitialSetup"
updated db/migrate/001_initial_setup.rb---
class InitialSetup < text ="">"some new task", :date =>"11-21-1978", :done =>0
end
def self.down
drop_Table :todos
end
end
execute "rake migrate", and for some reason this hangs the first time, ctrl-c kills but it ran successfully...
execute "script/generate model Todo"
install ajax_scaffold-2.2.1.gem
execute "script/generate ajax_scaffold Todo"
execute "script/lserver"
point browser to http://localhost:8000/Todos
Wednesday, March 15, 2006
baud rate calcuation
The 32K_9S08GB60_Mon.asm file (AN2140SW1) states, ";baud38400: equ 31 ;sets rate to 38,400-0.9% baud". And we know that SCI2BDH_SBR8 is 31(MC9S08GB60.h). So, SCI2BDLH=SCI2BDH_SBR8
Friday, March 03, 2006
MySQL character inserts
Wednesday, February 15, 2006
Servo HCS08 working
This will not work! Wish I knew why, but it won't. In order to properly affect the duty cycle the code must be in the main for loop. Hope I have time to investigate why the software interrupt doesn't function...
void interrupt Vkeyboard intSWITCH1(){
if(SWITCH1 == DOWN){
TPM2C0V = ZERO;
}
if(SWITCH2 == DOWN){
TPM2C0V = ONE_EIGHTY;
}
if(SWITCH3 == DOWN){
TPM2C0V = TPM2C0V -1;
}
if(SWITCH4 == DOWN){
TPM2C0V = TPM2C0V+1;
}
timer2chnl0 = TPM2C0V;*/
KBI1SC_KBACK = 1;//ack
}
Secondly, the original configuration of flipping the bit on PTDF2, again with an interrupt (timer 2 channel 0) was producing aberrations in the PWM! The aberrations were rhythmic in nature and we blamed them on internal software latency; again, wish I knew more about this, but the fact of the matter is that the code was simply this:
. Perhaps this is related to the fact that LED3 is by default wired to the output of PTDF2, and its operation was hosing with the PWM.
void interrupt VTimer2Chnl0 intTimer2Chnl0(){
PTFD_PTFD2 = ~PTFD_PTFD2;
TPM2C0SC_CH0F = 0;
}
Lastly, the the modulation count was still the same for the direct timer output (which for timer 2 channel 0 is PTD3, see http://www.freescale.com/files/microcontrollers/doc/data_sheet/MC9S08GB60.pdf), so:
#define half_ms_duty_50hz (TPM2MOD - (TPM2MOD/40) -2)
#define ONE_EIGHTY half_ms_duty_50hz
void initICG(){
/*configure Internal Clock Generator [ICG]*/
/*MFD[]={4,6,8,10,12,14,16,18}*/
ICGC2_MFD = 7; /*32KHz crystal, demo board.
For 4MHz crystal (eval board):
ICGC2_MFD = 3
*/
ICGC2_RFD = 0; /* RFD[]={1,2,4,8,16,32,64,128}*/
//ICGC1 = 0b00110000;
ICGC1 = 0b00111000;
/*32KHz crystal, demo board.
For 4MHz crystal (eval board):
ICGC1 = 0b01111000;
*/
while((ICGS1_LOCK==0)||(ICGS1_ERCS==0)){
/*Ensure COP doesn't reset device whilst waiting for clock lock*/
__RESET_WATCHDOG(); /* kicks the dog */
}
ICGC2_LOCRE = 1; /*enable reset if clock fails*/
}
void initTimer2Chnl0_50hz(){
TPM2C0SC_CH0IE = 1; //enable channel
TPM2SC_CLKSA = 1;/*Select BUS clock*/
TPM2SC_CLKSB = 0;
TPM2SC_PS = PRESCALAR;/*clock source divided by prescalar*/
TPM2MOD = 1475;/*counter value, counts up to*/
TPM2SC_CPWMS = 1;
/*configure PWM mode and pulse*/
TPM2C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM2C0SC_ELS0A = 1; /*Select low as true*/
TPM2C0V = ONE_EIGHTY;
}
Once I get the code cleaned up and more presentable, I'll post the entire thing for future replication.
Wednesday, February 08, 2006
Monday, February 06, 2006
Ethereal for OS X 10.4(Tiger) on a G3 iBook
Installed Fink and FinkCommander. From FinkCommander installed
Ethereal, but I was getting errors in execution (/sw/bin/ethereal).
Looked like some library issues. Pulled down the ethereal source and
read the Readme.macos and realized that FinkCommander installed shared
libraries.
Had to install the core libraries, and not the sh ones to get Ethereal
to load, that is
GLib 2.4.0
Pango 1.4.0
GTK+ 2.4.0
ATK 1.6.0
Changed permissions of the bpf (sudo a+r bpf*) devices per
http://wiki.ethereal.com/CaptureSetup/CapturePrivileges
Saturday, February 04, 2006
Servo info
-----
Servos are controlled by sending them a pulse of variable width. The control wire is used to send this pulse. The parameters for this pulse are that it has a minimum pulse, a maximum pulse, and a repetition rate. Given the rotation constraints of the servo, neutral is defined to be the position where the servo has exactly the same amount of potential rotation in the clockwise direction as it does in the counter clockwise direction. It is important to note that different servos will have different constraints on their rotation but they all have a neutral position, and that position is always around 1.5 milliseconds (ms).
The angle is determined by the duration of a pulse that is applied to the control wire. This is called Pulse width Modulation. The servo expects to see a pulse every 20 ms. The length of the pulse will determine how far the motor turns. For example, a 1.5 ms pulse will make the motor turn to the 90 degree position (neutral position).
When these servos are commanded to move they will move to the position and hold that position. If an external force pushes against the servo while the servo is holding a position, the servo will resist from moving out of that position. The maximum amount of force the servo can exert is the torque rating of the servo. Servos will not hold their position forever though; the position pulse must be repeated to instruct the servo to stay in position.
-----
So the goal for using the HCS08 board is to control the servo operation programatically via a timer. So how to find the duty cycle of a given period that equates to the required PWM?
According to this site the servo expects to see a pulse every 20ms, in which case that would equate to 1/.02 = 50hz. So once the timer is configured for the appropriate frequency, the duty cycle can then be adjusted as needed to control the servo. A pulse with a duty cycle of 5% @ .02s would be 1ms, which would then move the servo in the counter clockwise position, according to the first site, at 0 degrees. Whereas if the duty cycle were 10%, 2ms, the servo would rotate the shaft to 180 degrees. Adjusting the duty to 7.5%, 1.5ms, would return the shaft to neutral position.
Monday, January 30, 2006
74HCT32 Quad 2 input OR Gate
http://jameco.com/wcsstore/Jameco/Products/ProdDS/246457TI.pdf
Product link:
http://jameco.com/webapp/wcs/stores/servlet/ProductDisplay?langId=-1&storeId=10001&catalogId=10001&productId=246457
Monday, January 23, 2006
Two timers and a fade
---------------------
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "M68DEMO908gb60.h"
#define PRESCALAR 7
//#define MODULUS 32768
//#define MODULUS 16384
//#define MODULUS 8192
//#define MODULUS 4096
#define MODULUS 2048
#define DUTY75 (MODULUS-(MODULUS/4))
#define DUTY25 (MODULUS/4)
#define DUTY50 (MODULUS/2)
long cntr=0;
long cntr2=0;
int goUp = 0;
int goUp2 = 0;
long cntr3 = 0;
long timer2chnl0 = 0;
long pulseMod = 25;
int fadeTime = 4;
void MCU_init(void); /* Device initialization function declaration */
void speedUpOrSlowDown(){
if(SWITCH3==DOWN){
TPM1C0V = TPM1C0V/2;
} else if(SWITCH4 == DOWN){
if(TPM1C0V <= (MODULUS/2))
TPM1C0V = TPM1C0V*2;
}
}
void interrupt VTimer1Chnl1 intTimer1Chnl1(){//for every period of zone out on LED5, this intterupt is set 500 times
if(cntr3 %pulseMod ==0 )
LED1 = ~LED1 ;
cntr3++;
TPM1C1SC_CH1F = 0; //reset interrupt
}
void initTimer1Chnl1(){
/*configure PWM mode and pulse*/
TPM1C1SC = 1;
TPM1C1SC_MS1B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM1C1SC_ELS1A = 1; /*Select low as true*/
TPM1SC_PS1 = PRESCALAR;/*clock source divided by prescalar*/
TPM1C1V = DUTY50;
TPM1C1SC_CH1IE = 1;//turn on interrupt
}
void initTimer1Chnl0(){//LED5
/*Initialize timer TPM1 channel, assumes not touched since reset!*/
TPM1SC_CLKSA = 1;/*Select BUS clock*/
TPM1SC_CLKSB = 0;
TPM1SC_PS0 = PRESCALAR;/*clock source divided by prescalar*/
TPM1MOD = MODULUS;/*counter value, counts up to*/
TPM1SC_CPWMS = 1;
/*configure PWM mode and pulse*/
TPM1C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM1C0SC_ELS0A = 1; /*Select low as true*/
//TPM1C0V = DUTY75;/*select final divider (duty cycle)*/
TPM1C0V = 16;/*select final divider (duty cycle)*/
}
void interrupt VTimer2Chnl0 intTimer2Chnl0(){
if(timer2chnl0 % pulseMod ==0)
LED3 = ~LED3;
timer2chnl0++;
TPM2C0SC_CH0F = 0;
}
void initTimer2Chnl0(){
TPM2C0SC_CH0IE = 1; //enable channel
TPM2SC_CLKSA = 1;/*Select BUS clock*/
TPM2SC_CLKSB = 0;
TPM2SC_PS = PRESCALAR;/*clock source divided by prescalar*/
TPM2MOD = 8192;/*counter value, counts up to*/
TPM2SC_CPWMS = 1;
/*configure PWM mode and pulse*/
TPM2C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM2C0SC_ELS0A = 1; /*Select low as true*/
TPM2C0V = TPM2MOD/2;/*select final divider (duty cycle)*/
}
void initICG(){
/*configure Internal Clock Generator [ICG]*/
/*MFD[]={4,6,8,10,12,14,16,18}*/
ICGC2_MFD = 7; /*32KHz crystal, demo board.
For 4MHz crystal (eval board):
ICGC2_MFD = 3
*/
ICGC2_RFD = 0; /* RFD[]={1,2,4,8,16,32,64,128}*/
//ICGC1 = 0b00110000;
ICGC1 = 0b00111000;
/*32KHz crystal, demo board.
For 4MHz crystal (eval board):
ICGC1 = 0b01111000;
*/
while((ICGS1_LOCK==0)||(ICGS1_ERCS==0)){
/*Ensure COP doesn't reset device whilst waiting for clock lock*/
__RESET_WATCHDOG(); /* kicks the dog */
}
ICGC2_LOCRE = 1; /*enable reset if clock fails*/
}
void initKeyboardInterrupt(){
KBI1SC_KBIE = 1; //KBIE =>Keyboard Interrupt Enable
KBI1PE_KBIPE4 = 1; //Keyboard Interrupt Port Enable 4 (switch1)
KBI1PE_KBIPE5 = 1; //Keyboard Interrupt Port Enable 5 (switch2)
KBI1PE_KBIPE6 = 1; //Keyboard Interrupt Port Enable 6 (switch3)
KBI1PE_KBIPE7 = 1; //Keyboard Interrupt Port Enable 7 (switch4)
}
void interrupt Vkeyboard intSWITCH1(){
if(SWITCH1 == DOWN){
pulseMod +=2;
}
if(SWITCH2 == DOWN){
pulseMod -=2;
}
KBI1SC_KBACK = 1;//ack
}
void main(void) {
/* Uncomment this function call after using Device Initialization
to use the generated code */
/* MCU_init(); */
EnableInterrupts; /* enable interrupts */
PTADD = 0; //initialize as input (Data Direction Register)
PTAPE = 0xf0; //Pullups on upper 4 bits
/*initialize bits 0-3 of Port F as outputs (connected to led's)*/
PTFDD = 0x0f;
LED1 = OFF;
LED2 = OFF;
LED3 = OFF;
LED4 = OFF;
LED5 = OFF;
initICG();
initKeyboardInterrupt();
initTimer1Chnl0();//LED5
initTimer1Chnl1();//LED1
initTimer2Chnl0();//LED3
for(;;) {
__RESET_WATCHDOG(); /* feeds the dog */
if(goUp==1){
TPM1C0V = TPM1C0V+fadeTime;
cntr=0;
cntr2++;
if(TPM1C0V >= MODULUS){
goUp = 0;
}
} else{
//TPM1C0V = TPM1C0V/2;
TPM1C0V = TPM1C0V-fadeTime;
cntr2=0;
cntr++;
if (TPM1C0V <=0){
goUp =1;
TPM1C0V = fadeTime;
}
}
} /* loop forever */
/* please make sure that you never leave this function */
}
Saturday, January 21, 2006
timer fun
#include "derivative.h" /* include peripheral declarations */
#include "M68DEMO908gb60.h"
#define PRESCALAR 7
//#define MODULUS 32768 //16*2048
//#define MODULUS 16384
//#define MODULUS 8192
//#define MODULUS 4096
#define MODULUS 2048
#define DUTY75 (MODULUS-(MODULUS/4))
#define DUTY25 (MODULUS/4)
#define DUTY50 (MODULUS/2)
long cntr=0;
long cntr2=0;
int goUp = 0;
int goUp2 = 0;
long cntr3 = 0;
void MCU_init(void); /* Device initialization function declaration */
void speedUpOrSlowDown(){
if(SWITCH3==DOWN){
TPM1C0V = TPM1C0V/2;
} else if(SWITCH4 == DOWN){
if(TPM1C0V <= (MODULUS/2))
TPM1C0V = TPM1C0V*2;
}
}
void interrupt VTimer1Chnl1 intTimer1Chnl1(){//for every period of zone out on LED5, this intterupt is set 500 times
if(cntr3 %50 ==0 )
LED1 = ~LED1 ;
cntr3++;
TPM1C1SC_CH1F = 0; //reset interrupt
}
void initTimer1Chnl1(){
/*configure PWM mode and pulse*/
TPM1C1SC = 1;
TPM1C1SC_MS1B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM1C1SC_ELS1A = 1; /*Select low as true*/
TPM1SC_PS1 = PRESCALAR;/*clock source divided by prescalar*/
TPM1C1V = DUTY50;
TPM1C1SC_CH1IE = 1;//turn on interrupt
}
void initTimer1Chnl0(){//LED5
/*Initialize timer TPM1 channel, assumes not touched since reset!*/
TPM1SC_CLKSA = 1;/*Select BUS clock*/
TPM1SC_CLKSB = 0;
TPM1SC_PS0 = PRESCALAR;/*clock source divided by prescalar*/
TPM1MOD = MODULUS;/*counter value, counts up to*/
TPM1SC_CPWMS = 1;
/*configure PWM mode and pulse*/
TPM1C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM1C0SC_ELS0A = 1; /*Select low as true*/
//TPM1C0V = DUTY75;/*select final divider (duty cycle)*/
TPM1C0V = 16;/*select final divider (duty cycle)*/
}
void interrupt VTimer2Chnl0 intTimer2Chnl0(){
LED3 = ~LED3;
TPM2C2SC_CH2F = 0;
}
void initTimer2Chnl0(){
/*Initialize timer TPM1 channel, assumes not touched since reset!*/
TPM2SC_CLKSA = 1;/*Select BUS clock*/
TPM2SC_CLKSB = 0;
TPM2SC_PS = PRESCALAR;/*clock source divided by prescalar*/
TPM2MOD = 32768;/*counter value, counts up to*/
TPM2SC_CPWMS = 1;
/*configure PWM mode and pulse*/
TPM2C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM2C0SC_ELS0A = 1; /*Select low as true*/
TPM2C0V = TPM2MOD/2;/*select final divider (duty cycle)*/
}
void initICG(){
/*configure Internal Clock Generator [ICG]*/
/*MFD[]={4,6,8,10,12,14,16,18}*/
ICGC2_MFD = 7; /*32KHz crystal, demo board.
For 4MHz crystal (eval board):
ICGC2_MFD = 3
*/
ICGC2_RFD = 0; /* RFD[]={1,2,4,8,16,32,64,128}*/
//ICGC1 = 0b00110000;
ICGC1 = 0b00111000;
/*32KHz crystal, demo board.
For 4MHz crystal (eval board):
ICGC1 = 0b01111000;
*/
while((ICGS1_LOCK==0)||(ICGS1_ERCS==0)){
/*Ensure COP doesn't reset device whilst waiting for clock lock*/
__RESET_WATCHDOG(); /* kicks the dog */
}
ICGC2_LOCRE = 1; /*enable reset if clock fails*/
}
void main(void) {
/* Uncomment this function call after using Device Initialization
to use the generated code */
/* MCU_init(); */
EnableInterrupts; /* enable interrupts */
PTADD = 0; //initialize as input (Data Direction Register)
PTAPE = 0xf0; //Pullups on upper 4 bits
/*initialize bits 0-3 of Port F as outputs (connected to led's)*/
PTFDD = 0x0f;
LED1 = OFF;
LED2 = OFF;
LED3 = OFF;
LED4 = OFF;
LED5 = OFF;
initICG();
initTimer1Chnl0();//LED5
initTimer1Chnl1();//LED1
initTimer2Chnl0();//LED3
for(;;) {
__RESET_WATCHDOG(); /* feeds the dog */
if(goUp==1){
TPM1C0V = TPM1C0V+8;
cntr=0;
cntr2++;
if(TPM1C0V >= MODULUS){
goUp = 0;
}
} else{
//TPM1C0V = TPM1C0V/2;
TPM1C0V = TPM1C0V-8;
cntr2=0;
cntr++;
if (TPM1C0V <=0){
goUp =1;
TPM1C0V = 8;
}
}
if(goUp2==1){
TPM2C0V = TPM2C0V+32;
if(TPM2C0V >= MODULUS){
goUp2 = 0;
}
} else{
TPM2C0V = TPM2C0V-32;
if (TPM2C0V <=0){
goUp2 =1;
TPM2C0V = 32;
}
}
} /* loop forever */
/* please make sure that you never leave this function */
}
cvs creation string
where "drproj/project" is now the name to check out, and proj is the directory of the files to place into the new CVS project.
Monday, January 16, 2006
Interrupts, timer, LED code
-------------------------------
/* File: M68DEMO908GB60.h*/
/* include peripheral declarations */
#include <MC9S08GB60.h>
/*define value for led's when on and off*/
#define ON 0
#define OFF 1
/*define value for switches when up (not pressed) and down (pressed)*/
#define UP 1
#define DOWN 0
/*define led's*/
#define LED1 PTFD_PTFD0
#define LED2 PTFD_PTFD1
#define LED3 PTFD_PTFD2
#define LED4 PTFD_PTFD3
#define LED5 PTDD_PTDD0
/*define switches*/
#define SWITCH1 PTAD_PTAD4
#define SWITCH2 PTAD_PTAD5
#define SWITCH3 PTAD_PTAD6
#define SWITCH4 PTAD_PTAD7
#define Vspi 15
#define Vkeyboard 22
//define Timer1 interrupts
#define VTimer1Overflow 8
#define VTimer1Chnl2 7
#define VTimer1Chnl1 6
#define VTimer1Chnl0 5
//define Timer2 interrupts
#define VTimer2Overflow 14
#define VTimer2Chnl4 13
#define VTimer2Chnl3 12
#define VTimer2Chnl2 11
#define VTimer2Chnl1 10
#define VTimer2Chnl0 9
#define Vatd 23
#define Viic 24
-------------------------------
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "M68DEMO908GB60.h"
#define PRESCALAR 7
#define MODULUS 32768
#define DUTY75 (MODULUS-(MODULUS/4))
#define DUTY25 (MODULUS/4)
int sequenceNumber = 0;
void resetLEDs(){
LED1 = OFF;
LED2 = OFF;
LED3 = OFF;
LED4 = OFF;
LED5 = OFF;
}
void interrupt Vkeyboard intSWITCH1(){
resetLEDs();
if(SWITCH1 == DOWN){
sequenceNumber = 1;
}else if(SWITCH2 == DOWN){
sequenceNumber = 2;
}else if(SWITCH3 == DOWN){
sequenceNumber = 3;
}else if(SWITCH4 == DOWN){
sequenceNumber = 0;
}
KBI1SC_KBACK = 1;//ack
}
/*
* Reset all LEDs
*/
int ledsAreReset(){
return ((LED1 == OFF) && (LED2 == OFF)&&(LED3 == OFF)&&(LED4 == OFF)&&(LED5 == OFF));
}
/*
* Light up the LEDs in sequence
*/
void ledLightInSeq(){
if(((LED1 == OFF) && (LED5 == ON)) || (ledsAreReset())){
resetLEDs();
LED1 = ON;
}else if((LED2 == OFF) && (LED1 == ON)){
resetLEDs();
LED2 = ON;
}else if((LED3 == OFF) && (LED2 == ON)){
resetLEDs();
LED3 = ON;
}else if((LED4 == OFF) && (LED3 == ON)){
resetLEDs();
LED4 = ON;
}else if((LED5 == OFF) && (LED4 == ON)){
resetLEDs();
LED5 = ON;
}
}
/*
* Light up the LEDs in reverse sequence
*/
void ledLightRevSeq(){
if(((LED5 == OFF) && (LED1 == ON)) || (ledsAreReset())){
resetLEDs();
LED5 = ON;
}else if((LED4 == OFF) && (LED5 == ON)){
resetLEDs();
LED4 = ON;
}else if((LED3 == OFF) && (LED4 == ON)){
resetLEDs();
LED3 = ON;
}else if((LED2 == OFF) && (LED3 == ON)){
resetLEDs();
LED2 = ON;
}else if((LED1 == OFF) && (LED2 == ON)){
resetLEDs();
LED1 = ON;
}
}
/*
* Light LEDs from middle going out
*/
void ledLightMidOut(){
if(((LED5 == ON) && (LED1 == ON)) || (ledsAreReset())){
resetLEDs();
LED3 = ON;
}else if((LED3 == ON)){
resetLEDs();
LED2 = ON;
LED4 = ON;
}else if((LED2 == ON) && (LED4 == ON)){
resetLEDs();
LED1 = ON;
LED5 = ON;
}
}
/*
* Interrupt handler for controlling light sequence based on Timer2 clock overflow
*/
void interrupt VTimer2Overflow intTimer2Ovf(){
if(sequenceNumber ==1 ){
ledLightInSeq();
} else if(sequenceNumber == 2){
ledLightRevSeq();
} else if(sequenceNumber == 3){
ledLightMidOut();
} else {
LED1 = ~LED1;
LED5 = ~LED5;
}
TPM2SC_TOF = 0;//ack, change overflow bit
}
/*
* Initialize TPM2
*/
void initTimer2(){
TPM2SC_TOIE = 1;
/*Initialize timer TPM1 channel, assumes not touched since reset!*/
TPM2SC_CLKSA = 1;/*Select BUS clock*/
TPM2SC_CLKSB = 0;
TPM2SC_PS = PRESCALAR;/*clock source divided by prescalar*/
TPM2MOD = MODULUS;/*set Counter modulus*/
/*configure PWM mode and pulse*/
TPM2C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
TPM2C0SC_ELS0A = 1; /*Select low as true*/
TPM2C0V = DUTY75;//sets number that if matched by counter, will set channel flag
}
void initLedStuff(){
PTADD = 0; //initialize as input (Data Direction Register)
PTAPE = 0xf0; //Pullups on upper 4 bits
/*initialize bits 0-3 of Port D&F as outputs (connected to led's)*/
PTFDD = 0x0f;
PTDDD = 0x0f;
resetLEDs();
}
void initKeyboardInterrupt(){
KBI1SC_KBIE = 1; //KBIE =>Keyboard Interrupt Enable
KBI1PE_KBIPE4 = 1; //Keyboard Interrupt Port Enable 4 (switch1)
KBI1PE_KBIPE5 = 1; //Keyboard Interrupt Port Enable 5 (switch2)
KBI1PE_KBIPE6 = 1; //Keyboard Interrupt Port Enable 6 (switch3)
KBI1PE_KBIPE7 = 1; //Keyboard Interrupt Port Enable 7 (switch4)
}
/*
* Sample code from docs
*/
void manageDuty(){
if(SWITCH3==DOWN){
/*Switch pressed*/
if(SWITCH4==DOWN){/**/
TPM1C0V = DUTY75;/**/
LED3 = ON;/**/
LED4 = OFF;/**/
}else{
TPM1C0V = DUTY25;/**/
LED3 = OFF;/**/
LED4 = ON;/**/
}
}
}
void MCU_init(void); /* Device initialization function declaration */
void main(void) {
/* Uncomment this function call after using Device Initialization
to use the generated code */
/* MCU_init(); */
EnableInterrupts; /* enable interrupts */
initLedStuff();
initTimer2();
initKeyboardInterrupt();
for(;;) {
__RESET_WATCHDOG(); /* feeds the dog */
} /* loop forever */
}
Thursday, January 12, 2006
Freescale HCS908
Referencing the AN2616_Getting_Started_With_HCS08_and_CodeWarrior references (p4)AN2616SW.zip, which also does not exist with the bundled software. Sheesh.
So the HCS908 is debuggable, out of box, using the db9 serial connector with SCI1.
New project creation:
By selecting "P&E Full Chip Simulation", "P&E Hardware Debugging" and "Motorola Serial Monitor", it will be possible to use either simulation, the serial monitor within the HCS08 FLASH, or BDM to debug code.There is no code overhead as a result of choosing multiple connection methods.
To enable serial monitor connection press switch 4 and switch the power on, set the target to be "Monitor". Once the debugger appears a couple modal dialogs should quickly appear and disappear showing that the FLASH is being erased. If this doesn't happen then there is likely a communications problem and the simulator will then run the program.
Here's the first go at LED manipulation:
#include <hidef.h> /* for EnableInterrupts macro */
#include <MC9S08GB60.h> /* include peripheral declarations */
#define ON 0
#define OFF 1
#define UP 1
#define DOWN 0
#define LED1 PTFD_PTFD0
#define LED2 PTFD_PTFD1
#define LED3 PTFD_PTFD2
#define LED4 PTFD_PTFD3
#define LED5 PTFD_PTFD4
#define SWITCH1 PTAD_PTAD4
#define SWITCH2 PTAD_PTAD5
#define SWITCH3 PTAD_PTAD6
#define SWITCH4 PTAD_PTAD7
long approxTwoSeconds = 100000;
void delay(long millis){
long cnt=0;
for(cnt=0; cnt<millis; cnt++){
//wait
}
}
static void pulse(long flashTime){
LED1 = ON;
LED2 = ON;
LED3 = ON;
LED4 = ON;
LED5 = ON;
delay(flashTime);
LED1 = OFF;
LED2 = OFF;
LED3 = OFF;
LED4 = OFF;
LED5 = OFF;
delay(flashTime);
LED1 = ON;
LED2 = ON;
LED3 = ON;
LED4 = ON;
LED5 = ON;
delay(flashTime);
LED1 = OFF;
LED2 = OFF;
LED3 = OFF;
LED4 = OFF;
LED5 = OFF;
delay(flashTime);
}
static void simpleSequence(long delayBetweenLights){
LED1 = ON;
delay(delayBetweenLights);
LED1 = OFF;
LED2 = ON;
delay(delayBetweenLights);
LED2 = OFF;
LED3 = ON;
delay(delayBetweenLights);
LED3 = OFF;
LED4 = ON;
delay(delayBetweenLights);
LED4 = OFF;
LED5 = ON;
delay(delayBetweenLights);
LED5 = OFF;
}
void main(void) {
int cnt = 0;
EnableInterrupts; /* enable interrupts */
/* include your code here */
PTADD = 0;//initialize input
PTAPE=0xF0;//Pullups on upper 4 bits
PTFDD=0x0F; //initializes ports 0,1,2,3 of Port F as outputs (which are connected to the LEDs)
LED1=OFF;
LED2=OFF;
LED3=OFF;
LED4=OFF;
LED5=OFF;
for(;;) {
__RESET_WATCHDOG(); /* feeds the dog */
simpleSequence(approxTwoSeconds);
pulse(10000);
}
}
Thursday, January 05, 2006
Nullable fields in a unique constraint, BAD
Can't have a unique constraint with a nullable field and treat that nullable as a "unique" value.
(Oracle) http://www.adp-gmbh.ch/ora/misc/integrity_constraints.html ,
http://www.techonthenet.com/oracle/unique.php
(Postgresql)http://www.postgresql.org/docs/8.1/interactive/indexes-unique.html
(MySQL5) http://dev.mysql.com/doc/refman/5.0/en/create-table.html
A UNIQUE index is one in which all values in the index must be distinct. An error occurs if you try to add a new row with a key that matches an existing row. The exception to this is that if a column in the index is allowed to contain NULL values, it can contain multiple NULL values. This exception does not apply to BDB tables, for which an indexed column allows only a single NULL.
Wednesday, December 14, 2005
Eliminating session persistence on Tomcat shutdown
<Manager pathname=""/>
to the DefaultContext will disable Tomcat's default behavior of saving the session upon shutdown.
UPDATE
lousy, this didn't work.
Friday, November 11, 2005
SQL TIMESTAMP headache
At this point the question becomes, "So, how does this work with internationally replicated/distributed databases servicing multiple international JVMs?" It doesn't work, and after several days of testing, we're feeling confident enough to conclude this: the millis are (sometimes) being adjusted by the JDBC drivers to show you what it thinks you expect--so if you're really expecting UTC, then all the boxes' timezones should be GMT/UTC! That's sort of an issue if you plan on using servers in multiple places throughout the world to handle multiple web applications--which is exactly what we cannot assume.
So, the solution is simple:store the milliseconds as a long. Since Java (and most other sane languages) calculates date based upon the Unix Epoch, it makes sense. Furthermore, there's no guess work as to db timezone, connection timezone, driver millisecond manipulation--it's not a concern anymore.
When does the format of a date being storing in the database really matter? Depends on the need for precision, depends on the need of the application and it also depends on the requirement driving it in the first place. When the requirement dictates international interaction, the first thing that should come to mind is to store the date in a common time: GMT. Other consideration should be given to viewers and manipulators, what do they expect to see the time as? Locally or universal? If the answer for all of these questions point to an international need, the above solution is a simplistic and intuitive approach to resolving the design decision.
-------------begin Hibernate UserType-------------
package org.lds.sql;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.TimeZone;
import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.UserType;
import org.lds.env.utils.DateUtils;
/**
* Custom Hibernate type for precise UTC millisecond persistance and retrieval using a Timestamp.
* All values represent the given time from the Unix Epoch, 1 Jan 1970 00:00:00.000
* See http://en.wikipedia.org/wiki/Unix_epoch for more info.
* Credit: Rob @ "http://www.hibernate.org/100.html
*
*/
public class UtcTimestamp extends Timestamp implements UserType {
/**
* Gets the value of SQL_TYPES
*
* @return the value of SQL_TYPES
*/
public static int[] getSQL_TYPES() {
return UtcTimestamp.SQL_TYPES;
}
/**
* SQL type.
*/
private static final int[] SQL_TYPES = { Types.BIGINT };
/**
* Creates a newUtcTimestampinstance at this moment.
*
*/
public UtcTimestamp(){
super(System.currentTimeMillis());
}
/**
* With the given milliseconds.
*
* @param utcMillis alongvalue
*/
public UtcTimestamp(long utcMillis){
super(utcMillis);
}
/**
* Make a copy of the Timestamp.
* @see UserType#deepCopy(java.lang.Object)
*/
public Object deepCopy(Object obj) throws HibernateException {
return (obj == null) ? null : new Timestamp(((Timestamp)obj).getTime());
}
/**
* Compare via {@link Object#equals(java.lang.Object)}.
* @see UserType#equals(java.lang.Object, java.lang.Object)
*/
public boolean equals(Object x, Object y) {
return (x == null) ? (y == null) : x.equals(y);
}
/**
* Timestamps are mutable.
* @see net.sf.hibernate.UserType#isMutable()
*/
public boolean isMutable() {
return true;
}
/**
* Return an instance of the Timestamp or null if no value is specified.
* @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
*/
public Object nullSafeGet(ResultSet rs, String[] columns, Object owner)
throws HibernateException, SQLException {
long value = rs.getLong(columns[0]);
Timestamp timestamp;
if(rs.wasNull()) {
timestamp = null;
} else {
timestamp = new UtcTimestamp(value);
}
return timestamp;
}
/**
* Set an instance of the Timestamp into the database field.
* @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
*/
public void nullSafeSet(PreparedStatement statement, Object value, int index)
throws HibernateException, SQLException {
if(value == null) {
statement.setNull(index, Types.BIGINT);
} else {
Timestamp timestamp = (Timestamp)value;
statement.setLong(index, timestamp.getTime());
}
}
/**
* Return the {@link Timestamp} class.
* @see net.sf.hibernate.UserType#returnedClass()
*/
public Class returnedClass() {
return org.lds.sql.UtcTimestamp.class;
}
/**
* Return the supported SQL types.
* @see net.sf.hibernate.UserType#sqlTypes()
*/
public int[] sqlTypes() {
return SQL_TYPES;
}
/**
* All dates return their value in GMT time.
*
* @return aStringvalue
*/
public String toString(){
SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtils.DATE_FORMAT);
dateFormat.setTimeZone(DateUtils.GMT);
return dateFormat.format(this);
}
/**
* Obtain a UtcTimestamp from a Date.
*
* @param date ajava.util.Datevalue
* @return anUtcTimestampvalue
*/
public static UtcTimestamp valueOf(java.util.Date date){
UtcTimestamp utcTimestamp = new UtcTimestamp(date.getTime());
return utcTimestamp;
}
}
-------------end Hibernate UserType-------------
External firewire dvd burner
Emerged the latest k3b, reboot, modprobe sbp2 and modprobe sr_mod.
Plugged in the burner and watched /var/log/messages recognize it.
Added a device in k3b as /dev/sr0
Burned 4G in 20 minutes.
Once the burning was complete I mounted the drive as "mount /dev/sr0 /mnt/dvdrw" and verified the disc has my files!
Wednesday, November 09, 2005
Vonage, how easy
Secondly, Melissa has been talking to family in Idaho while I'm downloading two Sun apps @ 245KBps! Wow.
Further confirmation all dates are UTC millis, regardless of db timezone settings
(08:36:51) jamisbuck: sure
(08:36:57) Russ: do you use Mysql much?
(08:37:02) Russ: or Oracle?
(08:37:05) jamisbuck: mysql
(08:37:07) jamisbuck: I used oracle at byu
(08:37:17) Russ: great; done much with timestamps in mysql?
(08:37:22) jamisbuck: no, I avoid them
(08:37:26) jamisbuck: they don't act very intuitively
(08:37:36) Russ: intuitively...meaning?
(08:38:00) jamisbuck: updating the row automatically updates the timestamp, even if it was not explicitly requested
(08:38:03) jamisbuck: which goes counter to my way of thinking
(08:38:12) Russ: ah, right, only for the first column though ;)
(08:38:19) Russ: so, that aside
(08:38:45) Russ: do you explicitly set the timezone of your Mysql server to something other than the default SYSTEM?
(08:38:51) jamisbuck: no
(08:39:15) jamisbuck: we always store the times as utc, and explicitly transform them ourselves to the customer's time zone on display
(08:39:25) Russ: okay, that's exactly what I wanted to chat with you about
(08:39:30) Russ: the concept of storing them as UTC
(08:39:52) Russ: isn't *any* timestamp (or date/datetime for that matter) stored in UTC as millis from the epoch?
(08:40:26) jamisbuck: I have no idea :( but I'm pretty sure mysql dates/datetimes aren't limited to the epoch
(08:40:44) Russ: correct, they're not, the negative values work retroactively
(08:41:49) Russ: I'm struggling with storing time as UTC. Given a Calendar object in Java for today 9 Nov 00:00:00.000 GMT, I can store that in the database as my timestamp and verify the millis going in are the millis coming out--which is what I would expect if the date is indeed stored in UTC.
(08:42:07) Russ: The kicker is, any time I view that date via mysql console (or otherwise), the String representation is MST
(08:42:15) Russ: that is, 8 Nov 17:00:00:00.000
(08:42:30) Russ: not such a big deal, except that it can be confusing to convince that the date is correctly stored
(08:42:35) Russ: when not evaluating the millis
(08:42:35) jamisbuck: what is the timezone for your system?
(08:42:39) Russ: MST7MDT
(08:42:43) jamisbuck: yah, ours is utc
(08:42:52) Russ: I even changed that
(08:42:53) jamisbuck: I bet mysql is converting the date to the system's zone on output
(08:42:57) Russ: that's what I'm thinking
(08:43:10) Russ: I changed everything I could find, *except* my local timezone, and I get the same result
(08:43:20) Russ: even remote connections, from a different time zone
(08:43:36) Russ: which again points to the mysql server on my box "translating" the appropriate time
(08:43:49) jamisbuck: right
(08:43:50) Russ: so, theoretically, if I change my system timezone to UTC, I'll see the String I expect?
(08:44:01) jamisbuck: let me check something quick
(08:44:18) Russ: thanks for your input on this, I've been about on the verge of insanity of verification of this
(08:45:16) Russ: and the only remaining reason is that my system timezone is involved in the String representation
(08:45:31) jamisbuck: ok, I take it back, our servers have CST as the time zone, and mysql is configured to use SYSTEM as the time zone
(08:45:41) jamisbuck: but when I select a date via the mysql console, it doesn't show me any TZ information
(08:45:46) Russ: correct
(08:45:50) jamisbuck: 2004-04-11 07:07:37
(08:46:06) Russ: which if you get the millis, and view the UTC representation, will be the offset of CST
(08:46:22) jamisbuck: k, well, it has never bitten us in our rails apps
(08:46:29) jamisbuck: the times go in and come out correctly
(08:46:32) Russ: exactly
(08:46:41) Russ: as long as you use the millis, and not the string reported, that should be the case
(08:46:52) jamisbuck: to be honest, I use script/console more than I use mysql
(08:47:14) Russ: don't follow...you mean the console mysql executable?
(08:47:34) jamisbuck: I use my rails' app's script/console, istead of the mysql client program
(08:47:37) Russ: gotcha
(08:48:15) Russ: well thanks a bunch for your confirmation--my expectation is that whatever driver is managing the connection and result sets returns the millis any time a date/time/timestamp is retrieved
(08:48:37) Russ: the String representation is the secondary, because of the TZ offset calculations
(08:48:47) jamisbuck: alright, glad I could help
(08:48:48) Russ: which brings me around to, why set the timezone on a database?
(08:49:25) jamisbuck: I seem to remember that you can set some properties on the client connection. Maybe some of those specify how to deal with time zones
(08:49:38) jamisbuck: but it doesn't seem like it would help much if you are dealing with dates in multiple time zones
(08:49:44) Russ: exactly
(08:50:00) Russ: in Java you can muck with the millis going in if you provide the connection timezone
(08:50:18) Russ: and the JDBC driver will essentially "translate" the GMT millis to represent the timezone equivalent
(08:50:20) Russ: if that makes sense
(08:50:24) jamisbuck: yah
(08:50:29) Russ: anyhow, thanks again
(08:50:38) Russ: I wondered how Ruby dealt with it
(08:50:50) Russ: and it you've definitely confirmed my expectation
(08:50:52) Russ: have a good one!
(08:50:57) jamisbuck: you too!
GMT time and my headache
Regardless of my posts earlier about storing GMT dates in the database, I'm not so conviced that we *weren't* doing that in the first place. Fact is, using the Calendar in the PreparedStatement really only hoses with the millis being stored and my verification that "the right timestamp" was being stored was purely based on the String representation. In all actuality, if millis going in == millis coming out, then the date that is being stored at the moment indicated by the millis is very much indeed being stored in GTM.
But what about the settings for getting Oracle (alter database time_zone=xyz) or Mysql (mysqld_safe --default-time-zone=xyz)? I dunno what bearing that actually has. What I do know is that regardless of the time zone that Mysql is initiaiized with, the String representation of any date always appears as MST. For example, I have a date representing today (9 Nov 00:00:00.000 GMT). I persist this via JDBC and then immediately request back the value of the timestamp. Both sets of millis are identical. However, the date shown from toString() shows 8 Nov 17:00:00.000 since Java knows that JVM's timezone is MST7MDT. Likewise, if I access that same record and look at the date through the mysql command console, I see the same date!
What does this mean? I can explain the Java representation since it's using the timezone of my box (and Bryan and I tested it when he set his Apple to Tokyo time and we verified millis were correct, but String was appropriate for the Tokyo timezone), but I cannot explain the mysql console. Furthermore, why can't I just see millis? Something is translating those millis into MST7MDT. Still need to test this on Oracle. But, for the time being, I'm quite confused about the notion of storing timestamps in GMT when it appears that the Oracle/Mysql are doing exactly that anyway (as indicated by my tests, which I should post).
Tuesday, November 08, 2005
Oracle 9i GMT dates
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.TimeZone;
import java.sql.ResultSet;
public class TestOracleDate{
public static void main(String[] args){
SQLException exception = null;
Connection con = null;
String connectionString = "jdbc:oracle:thin:@testbox:imstest";
String user = "testuser";
String password = "testpassword";
String database = "testdb";
String uuid="c93d4654-40c2-11da";
String identifier="hoser date test";
String driverClassName="oracle.jdbc.driver.OracleDriver";
try{
Class.forName(driverClassName).newInstance();
}catch(Exception ex){ex.printStackTrace();}
try{
con = DriverManager.getConnection(connectionString,user,password);
String insertString = "INSERT INTO TEST_TABLE (cmn_rswd_identifier,cmn_rswd_statusid,cmn_rswd_mdate,cmn_rswd_cdate,cmn_rswd_uuid) VALUES ('"+identifier+"',1,?,?,'"+uuid+"')";
String deleteString = "DELETE FROM CMN_RESERVED_WORD where cmn_rswd_identifier='"+identifier+"'";
//insert = con.createStatement();
final PreparedStatement insert = con.prepareStatement(insertString);
final PreparedStatement delete = con.prepareStatement(deleteString);
System.out.println("executing: " + deleteString);
delete.executeUpdate();
System.out.println("executing: " + insertString);
TimeZone GMT = TimeZone.getTimeZone("GMT-00:00");
TimeZone MST = TimeZone.getTimeZone("MST7MDT");
System.out.println("First timestamp param, using :" + GMT.getID());
System.out.println("First timestamp param, using :" + MST.getID());
insert.setTimestamp(1,new Timestamp(System.currentTimeMillis()),Calendar.getInstance(GMT));
insert.setTimestamp(2,new Timestamp(System.currentTimeMillis()),Calendar.getInstance(MST));
insert.executeUpdate();
String queryString = "SELECT * FROM CMN_RESERVED_WORD where cmn_rswd_uuid='"+uuid+"'";
Statement query = con.createStatement();
ResultSet rs = query.executeQuery(queryString);
while(rs.next()){
//System.out.println(rs);
System.out.println("-----------------");
System.out.println("cmn_rswd_mdate (positional param 1) " + rs.getTimestamp("cmn_rswd_mdate"));
System.out.println("cmn_rswd_cdate (positional param 2) " + rs.getTimestamp("cmn_rswd_cdate"));
System.out.println("-----------------");
}
}
catch(SQLException ex){
ex.printStackTrace();
}
catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
finally{
try{
if(con != null) con.close();
}catch(Exception ex){ex.printStackTrace();}
}
}
}
Sources:
http://www.oracle.com/technology/products/oracle9i/htdocs/9iober2/obe9ir2/obe-nls/html/datetime/datetime.htm
http://www.dbasupport.com/oracle/ora9i/TimeZone.shtml
GMT dates for Mysql (MST7MDT) via JDBC, success
mysql 4.1.3-beta-standard
Connector/J:3.1.11-bin OR 3.2.0-alpha-bin
url:
jdbc:mysql://localhost:3306/unity?useUnicode=true&characterEncoding=utf8&useTimezone=true&serverTimezone=MST7MDT
mysql executable: /usr/local/mysql/bin/mysqld_safe --user=root --default-time-zone=MST7MDT &
Prepared statement (Hibernate)code:
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException{
Timestamp timestamp;
if(value instanceof Timestamp){
timestamp = (Timestamp) value;
}
else{
timestamp = (Timestamp) new LocalizedTimestamp();
}
Calendar gmtCal = Calendar.getInstance(GMT);
//where GMT = TimeZone.getTimeZone("GMT-00:00");
st.setTimestamp(index, timestamp,gmtCal);
}
The catch is that this code will be called on all of our TIMESTAMP types, since we're overriding the existing Hibernate TIMESTAMP type (as LocalizedTimestamp). However, this could be easily resolved by the generated DAOs setting some flag on the LocalizedTimestamp object. As it is, some of us are of the mindset that all the timestamps we store should be GMT, so this still works.
-----------
Update
The alternative, producing the same result, is as follows:
/usr/local/mysql/bin/mysqld_safe --user=root --default-time-zone=UTC &
jdbc:mysql://localhost:3306/unity?useUnicode=true&characterEncoding=utf8&useTimezone=true&serverTimezone=UTC
st.setTimestamp(index, timestamp);
Monday, November 07, 2005
mysql 5 and localized dates
3.0.9
Cannot convert value '2004-08-16 12:00:00' from column 4(2004-08-16 12:00:00 ) to TIMESTAMP.
3.1.11
java.sql.SQLException: Invalid value for getInt() - '^A' in column 7
3.2.0 alpha
Caused by: java.sql.SQLException: Unknown type '16 in column 6 of 21 in binary-encoded result set.
with the following code:
st.setTimestamp(index, timestamp,gmtCal);
where st is a PreparedStatement and the gmtCal is a Calendar instance set at GMT.
Also, the URL connection string was:
jdbc:mysql://localhost:3306/unity?useUnicode=true&characterEncoding=utf8&useTimezone=true&serverTimezone=MST7MDT
Tuesday, October 25, 2005
Tuesday, October 18, 2005
UTF-8, Java, XML and my linux kernel
-----------
I've searched and searched for my problem, and this is my last hope.Apache Maven 1.x uses Dom4j for various xml processing and provides a Jelly tag for parsing XML into a DefaultDocument. I'm experiencing Unicode characters being translated into "?" and the hooks are definitely not what I need.
I've replaced the 1.4 version shipped with Maven to 1.6.1 and have
created a simple test goal in order to replicate the behavior. I've
tried to two different ways of parsing the file, one through using a StringReader that's opened a file in UTF-8, and the other using the default xml:parse tag in Jelly. Both with the same results. So, my question is, has anyone else experienced anything similar? Should I be posting my question on the Maven list? Any ideas?
Thanks in advance,
-RR-
UPDATE
Pretty much after I sent my post I realized that this could be a
JVM/System issue. Further testing, and loading NLS into my kernel
resolved the problem. The System.out issue was resolved by setting my LC_ALL="en_US.utf8" and then I proceeded with my kernel modification.
Friday, October 14, 2005
Ruby FileFinder now toast, gse-locate.el is in
First thing is to create a "locate" database. I wanted to index everything in /ext, so the command was "slocate -U /ext -o ext.files.db". I modified gse-locate to work in linux and the final code is:
;; gse-locate.el
;; Summary: Emacs front-end to 'locate'.
;; Author: Scott Evans
;; Home: http://www.antisleep.com/elisp
;; Time-stamp: <2004.12.22 23:20:59 gse>
;;
;; Commentary:
;; A handy Emacs interface to 'locate'. Having this interface
;; around is great -- it gives you a one-step way to get around a
;; filesystem, and spend a lot less time navigating directory trees.
;;
;; I lifted a lot of the major mode code from Steve Molitor's
;; rec-files.el (or at least from my modified version).
;;
;; I spend most of my time in Windows now, and porting slocate to
;; Cygwin didn't go real well so I wrote my own simple 'locate'
;; replacement for Cygwin (see http://www.antisleep.com/software/loc).
;;
;; Written for/using XEmacs on Windows. Changes are welcome.
;;
;; Installation:
;; (require 'gse-locate)
;; and if you like:
;; (global-set-key '[f10] 'gse-locate)
;;
;;---------------------------------------------------------------------------
;; Change Log
;; ----------
;; 2005.10.11 Modified to use locate and work in Linux -RR
;; 2004.01.18 Actually, -c is bad.
;; 2004.01.18 Use loc -c, take out backslash replacing.
;; 2004.01.18 Add gse-locate-execute-file.
;; 2004.01.18 Change to major mode with keybindings. Add some customization.
;; 2002.04.08 Created.
;;---------------------------------------------------------------------------
;; Unix (and native Cygwin) users can probably just set this
;; to "locate".
(defvar gse-locate-command "locate"
"*\"locate\" shell command. This will be used as an argument to
shell-command, with the search pattern concatenated to it.
This specified program should take a string (or regular expression, if
you intend to use them) as a parameter, and return a list of files to
stdout, one per line.")
(defvar gse-locate-hooks nil
"List of functions to call when entering gse-locate-mode")
(defvar gse-locate-regexp-list
(list "\\.elc"
"\\.class"
"/CVS"
"/target/classes"
"#"
"~"
".cvsignore"
)
"A list of regular expressions that match \"uninteresting\" filenames.
These will be stripped from the locate list before it is displayed.")
;;---------------------------------------------------------------------------
(defvar gse-locate-prev-wconfig nil)
(defvar gse-locate-buf nil)
(defvar gse-locate-history nil)
;;---------------------------------------------------------------------------
(defun gse-locate (pattern)
"Lightweight interface to locate. PATTERN is the string or regexp
that will be passed to locate (see gse-locate-command).
If exactly one file matches, it will be opened. Otherwise a list
of files will be presented (see gse-locate-mode)."
(interactive
(list
(read-from-minibuffer "locate pattern: " nil nil nil
'gse-locate-history)))
(set-buffer (get-buffer-create "*locate*"))
(setq buffer-read-only nil)
(erase-buffer)
(shell-command (concat gse-locate-command " -d /ext/ext.files.db " pattern) t)
;; Clean up stuff we don't want to see.
(let* ((i 0))
(while (< i (length gse-locate-regexp-list))
(let ((cur-regexp (nth i gse-locate-regexp-list)))
(goto-char (point-min))
(delete-matching-lines cur-regexp))
(setq i (+ i 1))))
(let ((number-matches (count-lines (point-min) (point-max))))
(cond
((= number-matches 0)
(message "No matches."))
((= number-matches 1)
;; One match. Open the file.
(find-file (buffer-substring
(point-min)
(progn
(goto-char (point-min))
(end-of-line)
(point))))
)
(t
;; Multiple matches.
(setq gse-locate-prev-wconfig (current-window-configuration))
(goto-char (point-min))
(switch-to-buffer (current-buffer))
(setq gse-locate-buf (current-buffer))
(gse-locate-mode))
))
)
;;---------------------------------------------------------------------------
(defvar gse-locate-mode-map nil
"Keymap for gse-locate-mode.")
(if gse-locate-mode-map
()
(setq gse-locate-mode-map (make-sparse-keymap))
(define-key gse-locate-mode-map "v" 'gse-locate-select-this-window)
(define-key gse-locate-mode-map "\C-m" 'gse-locate-select-this-window)
(define-key gse-locate-mode-map "o" 'gse-locate-select-other-window)
(define-key gse-locate-mode-map " " 'next-line)
(define-key gse-locate-mode-map "n" 'next-line)
(define-key gse-locate-mode-map "p" 'previous-line)
(define-key gse-locate-mode-map "q" 'gse-locate-quit)
(define-key gse-locate-mode-map "1" 'gse-locate-select-1-window)
(define-key gse-locate-mode-map "?" 'describe-mode)
(when (functionp 'mswindows-shell-execute)
(define-key gse-locate-mode-map "X" 'gse-locate-execute-file))
)
;;---------------------------------------------------------------------------
(defun gse-locate-mode ()
"Lightweight major mode to select a file from \"locate\" output.
Special keys:
\\{gse-locate-mode-map}"
(interactive)
(kill-all-local-variables)
(setq major-mode 'gse-locate-mode)
(setq mode-name "Locate")
(use-local-map gse-locate-mode-map)
(setq truncate-lines t)
(setq buffer-read-only t)
(run-hooks 'gse-locate-hooks))
;;---------------------------------------------------------------------------
(defun gse-locate-current-file ()
(save-excursion
(beginning-of-line)
(buffer-substring
(point)
(search-forward-regexp "$"))))
;;---------------------------------------------------------------------------
(defun gse-locate-find-file (file-name &optional find-function)
"Open file if it exists."
(when (not find-function)
(setq find-function 'find-file))
(if (file-exists-p file-name)
(funcall find-function file-name)
(error "%s%s%s" "File '" file-name "' does not exist!")))
;;---------------------------------------------------------------------------
(defun gse-locate-select-this-window ()
"Select this line's file in this window."
(interactive)
(gse-locate-find-file (gse-locate-current-file)))
;;---------------------------------------------------------------------------
(defun gse-locate-select-other-window ()
"Select this line's file in this window."
(interactive)
(gse-locate-find-file (gse-locate-current-file) 'find-file-other-window))
;;---------------------------------------------------------------------------
(defun gse-locate-select-1-window ()
"Select this line's buffer, alone, in full frame."
(interactive)
(gse-locate-find-file (gse-locate-current-file))
(bury-buffer (other-buffer))
(delete-other-windows))
;;---------------------------------------------------------------------------
(defun gse-locate-quit ()
"Close gse-locate buffer."
(interactive)
(let ((buf (get-buffer gse-locate-buf)))
(and buf (bury-buffer buf)))
(set-window-configuration gse-locate-prev-wconfig))
;;---------------------------------------------------------------------------
(defun gse-locate-execute-file ()
"Launch this line's file. Currently windows-only (and probably
XEmacs-only)."
(interactive)
(let ((file-name (gse-locate-current-file)))
(if (file-exists-p file-name)
(mswindows-shell-execute nil file-name)
(error "%s%s%s" "File '" file-name "' does not exist!"))))
;;---------------------------------------------------------------------------
(provide 'gse-locate)
Monday, October 10, 2005
jde-usages, this is great
Friday, October 07, 2005
Beagle 0.1.1 in Gentoo
Then "ebuild /usr/portage/app-misc/beagle/beagle-0.1.1.ebuild digest".
Lastly, my /etc/portage/package.unmask:
dev-lan/mono
and /etc/portage/package.keywords:
sys-apps/dbus ~x86
app-misc/beagle ~x86
dev-lang/mono ~x86
dev-dotnet/libgdiplus ~x86
dev-dotnet/gecko-sharp ~x86
dev-dotnet/gtk-sharp ~x86
dev-libs/gmime ~x86
dev-dotnet/gnome-sharp ~x86
dev-dotnet/art-sharp ~x86
dev-dotnet/gnomevfs-sharp ~x86
dev-dotnet/glade-sharp ~x86
dev-dotnet/gconf-sharp ~x86
media-libs/libexif ~x86
Finally, "emerge -av app-misc/beagle" and selecting "yes".
I haven't upgraded my kernel, with the inotify stuff.
UPDATE
Here's my make.conf:
USE="x86 oss apm arts avi berkdb crypt cups encode foomaticdb gdbm gif gpm gtk gtk2 imlib
jpeg kde gnome libg++ libwww mad mikmod motif mpeg ncurses nls oggvorbis
opengl pam pdflib png python qt quicktime readline sdl slang spell ssl
svga tcpd truetype X xml2 xmms xv zlib gtkhtml svg objc
ruby mono dbus eds"
I tried adding "webservices", but it hosed the build.
Tuesday, September 27, 2005
Location equivalency headaches
To define how multiple Location subordinates are equivalent, consider the following. The Location (country) USA has "states", "commonwealths", and a "district". It's neighbor to the north, Canada, has "provinces" and "territories". Likewise, the UK has "counties" or "post towns". On a formal level, these could all be called, "level 1 subordinates". If you have a Location table that defines a location by its type (and an id), then you could have the following:
Location
---------
id type name
-- ---- ----
1 country USA
2 country Canada
3 country UK
4 level1 Alabama
5 level1 Manitoba
6 level1 Southhampton
7 level1 Puerto Rico
8 level1 District of Columbia
9 country Mexico
LocationType
------------
id type
-- ----
1 country
2 level1
3 level2
4 level3
5 level4
Note, "level*" indicates a level of subordination. Using a LocationAssociation table you can build a hierarchy of locations and their subordinates.
For address creation, how could you equate like levels and provide an appropriate naming scheme in the context of the country? Here's one possible set of tables providing a solution:
First is a Subordinate Types table that defines the types you will use to identify subordinates (any level). This table could have a translatable counterpart that provided localized identifiers (I18n) per row, thus enabling translations for a single word, in multiple languages. (This is beneficial in the following model because it constrains translation to a single word and the context is derived based on equivalency relation.)
Subordinate Types
-----------------
id type
-- ----
1 state
2 province
3 territory
4 county
5 district
6 commonwealth
The Subordinate Equivalence table will relate a location, a locationType, specify if the row is a default (more on this in a moment), subordinateType, and a pointer to a localized string used to identify that component in the native country (locationId). This table realizes the equivalent nature of LocationTypes and SubordinateTypes in context of the owning location (usually country).
Subordinate Equivalence
-----------------------
id locationId locationType defaultBit subordinateType defaultLocalizedStringId
-- ---------- ------------ ---------- --------------- ------------------------
1 1 level1 1 state ->"State"
2 1 level1 0 district ->"District"
3 1 level1 0 commonwealth ->"Commonwealth"
4 2 level1 1 province ->"Province"
5 2 level1 0 territory ->"Territory"
6 3 level1 1 county ->"County"
7 3 level1 0 posttown ->"Post Town"
8 1 level2 1 county ->"County"
9 1 level3 1 city ->"City"
10 2 level3 1 city ->"City"
11 3 level4 1 city ->"City"
12 9 level1 1 state ->"Estado"
13 9 level3 1 city ->"Ciudad"
Thus, this table relates that "level3" is common across USA, Canada, UK, and Mexico. But, "level2" has no associated alternatives *in those countries*. Likewise, the word "county" is used twice, once to show a "county" is "level2" locationType in the USA. BUT, it also shows that it is a "level1" for the UK. So, the UK "county" could be considered equivalent to a USA "state" and Canadian "province" and "territory". This is quite helpful to know in address construction and UI presentation. The "defaultBit" shows which is the default subordinate type for that level, to display to the user.
I18n Benefits:
With the use of the FK to the Subordinate Types table, the i18n value of the subordinate type can be easily fetched. This is most helpful for countries that support multiple languages (ie. Canada or Switzerland).
Likewise, if a user in the USA wants to know what an "Estado" is, we can determine the equivalent through this table and provide an appropriate translation.
Monday, September 26, 2005
Lexmark printing
as root:
emerge deb2targz
execute deb2targz on the driver
execute the shell script located in usr/local/lexmark/setup.lexprint
execute lexprint to setup the printer
At this point the CUPS entry is created (once the printer is added) and you can print from anywhere that supports CUPS.
Oracle settings
#oracle stuff
ORACLE_BASE=/home/russ/apps/oracle
ORACLE_HOME=$ORACLE_BASE/10
TNS_ADMIN=$ORACLE_HOME/tnsnames
export ORACLE_HOME TNS_ADMIN ORACLE_BASE
LD_LIBRARY_PATH=$ORACLE_HOME/basic-client:$ORACLE_HOME/sql-client
export LD_LIBRARY_PATH
SQLPLUS=$ORACLE_HOME/sql-client/sqlplus
Wednesday, September 21, 2005
Opera Adblock. thanks to the wiki
Here's how I finally got "AdBlock" functionality working in Opera.
In my opera6.ini under "[Image Link Popup Menu]" and "[Image Popup Menu]:
Item, "Destroy image python" = Copy image address & Execute program,"/home/russ/.opera/adblock.py","%c" & Select user CSS file,1 & Deselect user CSS file, 1 & Select user CSS file,1 & Deselect user CSS file, 1
Where adblock.py (universally executable) is:
#!/usr/bin/python
import sys, os
BLOCK_CSS_FILE="/home/russ/.opera/adblock.css"
# read current CSS
try:
cssFile=open(BLOCK_CSS_FILE,"r")
except:
cssStr="\n"
else:
cssStr=cssFile.read()
cssFile.close()
# write new CSS
cssFile=open(BLOCK_CSS_FILE,"w")
if len(sys.argv)==2:
cssFile.writelines('img[src="'+sys.argv[1]+'"]')
elif len(sys.argv)==3:
cssFile.writelines(sys.argv[2]+'"'+sys.argv[1]+'"]')
elif len(sys.argv)==5:
cssFile.writelines(sys.argv[2]+'['+sys.argv[3]+sys.argv[4]+'"'+sys.argv[1]+'"]')
elif len(sys.argv)==4:
cssFile.writelines(sys.argv[2]+'['+sys.argv[3]+'='+'"'+sys.argv[1]+'"]')
if (cssStr=="\n")|(cssStr==""):
cssFile.writelines('\n{display:none !important;}')
else:
cssFile.writelines(',\n')
cssFile.writelines(cssStr)
cssFile.close()
And now that Opera is free without the ad banner, imports FireFox bookmarks, and can now block images this may be a long-term relationship. It's fast and so far I like it.
Forgot that this is also present in opera6.ini:
[Author Display Mode]
Author Font and Colors=1
User Font and Colors=0
User Link Settings=1
Author CSS=1
User CSS=1
[User Display Mode]
User CSS=1
User Link Settings=1
Author CSS=1
Author Font and Colors=1
User Font and Colors=0
[Local CSS Files]
Name 12=Adblock
File 12=adblock.css
Name 13=Overlay
File 13=overlay.css
Active 13=0
Active 12=1
Saturday, September 17, 2005
Divs, Iframes, and Windows rendering
Anyhow, long story short, thanks to this blog from Joe King at MS, it clicked that I was 90% of the way there but was missing only a couple small things. After another hour of tweaking, I have a solution.
Assuming you have a DIV that is your pop-in already placed where you want it to show, it's just a matter of adding the following code and calling "hideOrShowPop" (stupid, yes, I should rename it):
function hideOrShowPop(id){
var popin= document.getElementById(id);
var idToFetch = id + "Active";
var popinActive = document.getElementById(idToFetch);
if(popin.style.visibility=="hidden"){
handlePop(id);
}
else{
popin.style.visibility="hidden";
var clone = document.getElementById("clone"+id);
if(clone != null){
clone.style.visibility="hidden";
clone.removeNode(true);
}
}
}
function handlePop(id){
var popinDiv = document.getElementById(id);
var anchorNode = document.getElementById(id+"Anchor");
popinDiv.style.visibility="visible";
popinDiv.style.display="block";
var cloneDiv = popinDiv.cloneNode(false);
//this is for figuring out how to put the popin ANYWHERE on the screen, currently not working
//var anchorPoint = getLocationPoint(anchorNode);
//popinDiv.style.top = anchorPoint.y;
//popinDiv.style.left = anchorPoint.x;
var width = parseInt(popinDiv.style.width);
var height = parseInt(popinDiv.style.height);
cloneDiv.id = "clone" + id;
try{
cloneDiv.zIndex="3";
cloneDiv.innerHTML = "";
popinDiv.parentNode.appendChild(cloneDiv);
popinDiv.parentNode.appendChild(popinDiv);
} catch(e){
alert("Popin exception caused by id: " + idToFetch + " or " + id);
if(ie)
alert(e.description);
else
alert(e);
}
}
So the code clones the div, then sets the inner node of the cloned div to an iframe. Lastly it's appended to whomever owns the original div, and then the original div is appended after the clone.
Now I can go to bed.
Friday, September 16, 2005
Firefox HTTP sniffer
http://tamperdata.mozdev.org/installation.html
Easily view HTTP traffic from your browser AND edit it before it's sent.
Thursday, September 15, 2005
Tapestry: DatePIcker, SSL, and IE
Here are the posts I wrote along the way (most recent first):
Branding myself a hasty hoser, the previously posted code did not work (my test page was cached with a previous attempt).
So, for real this time, the fix is: commenting out that line of code for generating the IFrame. Of course, if you have a dropdown underneath it then you'll probably want it, but that's a tradeoff explicitly awaiting IE developers. This fix is quick and dirty, but it works for me since we don't have any Selects near DatePickers.
http://support.microsoft.com/default.aspx?scid=kb;en-us;177378
" However, IFRAME tries to draw on top of SELECT because it is last in the order. To prevent this, the value of the SELECT element's z-index must be greater than that of the IFRAME, or the SELECT element must be last in the list to ensure that the element always draws on top of the IFRAME when the z-indexes are the same. Because of this, z-indexing similar content can be difficult."
IFrame security covered here (Dec 04, which explains why the DatePicker was working fine in IE last year at this time):
http://www.microsoft.com/technet/security/bulletin/ms04-040.mspx
Hopefully I'm done with this topic, apologies for the repeated posts,
-RR-
-----------------
Thanks to this thread, http://thread.gmane.org/gmane.comp.java.tapestry.user/13528, I have changed DatePicker.js:
(previous line)
underDiv.innerHTML = "";
(new code)
underDiv.innerHTML = "";
Works wonderfully.
On 9/15/05, RR
>opening the DatePicker window yields a security warning in Internet
>Explorer when using an SSL connection. The message is the infamous "This
>page contains both
secure and nonsecure items. Do you want to display
>the non
secure items?".
http://article.gmane.org/gmane.comp.java.tapestry.user/7271/match=+secure+items
In Tapestry 3 I'm having the same problem as above -- wondering if anyone else has experienced it and found a solution? This thread is old and I haven't found anything else related.
What I've tried (and without resolution):
1)added my cert as a trusted cert
2)changed the component render to place an onclick in the image instead of wrapping it as an anchor
3)explicitly added "https:" in front of the rendered src attribute on the img.
Any other ideas out there?
Java TCP Tunnel analyzer
java -cp soap-2.3.jar org.apache.soap.util.net.TcpTunnelGui 9999 localhost 8080
Where "9999" is the local socket, localhost is the destination host to monitor, "8080" is the port to monitor on the destination host. So, to monitor your communication with Gmail you could execute: java -cp soap-2.3.jar org.apache.soap.util.net.TcpTunnelGui 9999 gmail.google.com 80. Then, in your browser, you'd use the following URL:
http://localhost:9999/
However, this will only work if you don't require an HTTP proxy.
Likewise with https with a local secure link and server:
java -cp soap-2.3.jar org.apache.soap.util.net.TcpTunnelGui 8888 localhost 8443
and
https://localhost:8888/
Wednesday, September 14, 2005
3550 entry
a) Finish my CS degree before I'm 30. Hopefully going to happen in the time frame I'd like. Work, kids, and other responsibilities have outweighed my educational pursuits since I began working full-time in 2000.
b) Obtain a Masters degree in something. While I'd like to think that I'd focus on CS studies once I'm done at UVSC, my wife is pretty sure that we'll be taking a break from school for a while. It'd be all too convient if UVSC offered a Masters program by the time I'm done with my under-grad.
Some interests:
- Linux
- Programming
- Being with my kids
- Software Development
- Soccer
- U.S. History
- Reading (mostly non-fiction right now)
Friday, September 09, 2005
Tapestry render solution
/**
* Simple interface declaring required properties for a protected component to (en/dis)abling a component render and its disable(d) state.
*
*/
public interface IProtectedComponent{
/**
* Flag for allowing component render.
*
* @return aBooleanvalue
*/
public boolean getAllowRender();
}
Then I wrapped all of the default Tapestry components we're using, for example:
/**
* A protected PropertySelection component only rendered if allowedRender is true.
*
*/
public abstract class ProtectedPropertySelection extends PropertySelection implements IProtectedComponent{
protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle){
if(getAllowRender() == true){
super.renderComponent(writer, cycle);
}
}
Did this for:
Any
Button
Checkbox
DatePicker
Insert
DirectLink
LinkSubmit
PageLink
PropertySelection
Submit
TextFiel
ValidField
Then, in the base class pageBeginRender, added the following:
for(Iterator componentIter = components.keySet().iterator(); componentIter.hasNext();){
String componentId = (String)componentIter.next();
IComponent component = getComponent(componentId);
IBinding elementId = component.getBinding(ELEMENT_IDENTIFIER);
if(IProtectedComponent.class.isAssignableFrom(component.getClass())){
IProtectedComponent protectedComponent = (IProtectedComponent)component;
if(elementId != null){
//resolve rights to component
//boolean updateOrExecute = canAccess(elementId, CRUDAction.UPDATE);
boolean updateOrExecute = true;
if(! updateOrExecute){
//boolean canRead = canAccess(elementId, CRUDAction.READ);
boolean canRead = false;
if(!canRead){
//do not render the component
component.setProperty(ELEMENT_ALLOW_RENDER, "false");
component.setProperty(ELEMENT_DISABLE, Boolean.TRUE);
}
else{
//Render the component, but make it disabled
component.setProperty(ELEMENT_ALLOW_RENDER, "true");
component.setProperty(ELEMENT_DISABLE, Boolean.TRUE);
}
}
else{
//Render the component normally
component.setProperty(ELEMENT_ALLOW_RENDER, Boolean.TRUE);
component.setProperty(ELEMENT_DISABLE, Boolean.FALSE);
}
}
}
}
So, I'm basically cycling through all of the components and changing state based upon id attribute and rights to the element. By the time renderComponent is called, the allowRender and disabled properties are set. Thus, this ensures the component is handled properly based upon user rights associated to the id.
Wednesday, September 07, 2005
Tapestry rant
What are the reasons for Tapestry completely hosing the easibility of this process?! This would be cake in XMLC or Wicket!
1. Components must be defined prior to render. Which means, you need to have the "disabled" parameter set to false on *every* single component you want to protect, at build-time. It is a pain to add a "binding" on at run-time and highly discouraged (http://article.gmane.org/gmane.comp.java.tapestry.user/25209).
2. Tapestry is incapable of removing components at render time. You don't have access to the DOM, you can't set a flag, nothing. I should clarify, this is the case for a) all default Tapestry components b) you can sort of work around this by wrapping the component in a Conditional component.
3. Tapestry default components do not allow render flags. In conjunction with issue #2, you can't just set a flag informing Tapestry to NOT render the component.
So, why does this really tick me off? Because I have many pages on which I now need to implement security (aforementioned implementation). I cannot, out-of-the-box, do what I need. I must go through each component and add the "disabled" attribute (only 130+ of them). I must choose to wrap the components in Conditionals if I don't want them rendered. IMO, this is a ton of work and really defeats the purpose of dynamic page generation.
My acceptable is solution is to go through and create wrapper components for each of the Tapestry components we're using. I'll add a default "disabled" attribute that I can hose with at run-time (so the user doesn't have to add it specifically) and a flag that determines whether the component should render. This is going to take more time than I likely have. Wish I knew about this issues months ago, I *may* have reconsidered my choice of web application framework.
One alternative, Java Server Faces, does exactly what I want in its UIComponentBase:
http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIComponentBase.html#UIComponentBase()
In conclusion, the more I work with Tapestry the more I feel like my hand is being held and while it provides some nifty aspects (reusable components, form validation), I can accomplish essentially the same thing in some other frameworks. The more I look into JSF, the more I'm realizing its value....
Wednesday, August 24, 2005
IceWM whips Flux
Smart window placement
faster startup/smaller footprint
ease of customization, configuration files much simpler
good preference tools
invokable menu by key-binding
gaim doesn't crash (compared to flux 0.9.12)
mouse focus more consistent--this drove me nuts in Flux
Tomcat whips JBoss
1. download Tomcat 5.x, http://www.reverse.net/pub/apache/jakarta/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.tar.gz or http://www.reverse.net/pub/apache/jakarta/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.zip
2. [un] tar/zip the Tomcat download.
3. modify this snippet to correctly point to the right properties file:
4. modify "/
5. modify "/
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" debug="0" scheme="https" secure="true"
keystoreFile="${user.home}/.keystore" keystorPass="yourpassword"
clientAuth="false" sslProtocol="SSL" />
6. copy "~/.maven/repository/commons-logging/jar/commons-logging-1.0.4.jar" into "/
7. copy "~/.maven/repository/log4j/jars/1og4j-1.2.8.jar" into "/
8. copy "~/.maven/repository/j2ee/jars/j2ee-1.4.jar" into "/
9. lastly, to run the build/deploy to build the war and copy into "/
10. startup tomcat, "/
Using Tomcat has sped up my build/deploy time from >=160s to <=30s, hooray for Tomcat.
NOTE:
If you're on Linux and downloaded the JDK from Sun, double-check that "javac" has executable permissions.
Tuesday, August 23, 2005
Localized dates the JDBC way
Implementing the above is a great option if you need a blanket solution. Frankly, I agree with Todd that we should be storing everything in GMT anyway. At this point in the game that's not feasible and we need specific GMT/Localizable functionality on only a few specific columns. Future situations may present alternative necessities.
Friday, August 19, 2005
Maven and Emacs, the romance and beauty
Maven JDEE plugin
and
more functionality here
and here.
That last one is especially great because of the ability to run goals with the Maven console. Really speeds up dev time having it open and instantly executing goals--with the ability to click on compile errors and have them immediately opened and focused in the primary Emacs frame. Loving it so far.
Monday, August 15, 2005
VPN
http://oit.uta.edu/cs/network/vpn/linux/vpn_linux.html
copy to /usr/portage/distfiles
emerge cisco-vpnclient-3des
copy .pcf to /etc/opt/cisco-vpnclient/Profiles
then:
vpnclient connect <profile> user <username>