Logotipo Dicas-L, por Ricardo Burile

Busca

Visite também: UnderLinux ·  VivaOLinux ·  LinuxSecurity ·  NoticiasLinux ·  BR-Linux ·  SoftwareLivre.org ·  [mais]   
 

Você está aqui: Home  → Arquivo Dicas-L

 

Mão na Massa - Programação Shell

Assine a Lista Dicas-L

Receba diariamente por email as dicas
de informática publicadas neste site
Para se descadastrar, clique aqui.

Tratando as exceções da nova regra para o Horário de Verão

Colaboração: Miguel Angelo Rozsas

Data de Publicação: 20 de September de 2008

A partir de 2008 os dias em que começam e terminam o horário de verão no Brasil serão fixos, válido pelo menos até quando o "Grande Colisor de Hádrons" produza um buraco negro que saia do controle e "engula" o planeta ou talvez até o inicio do mandato do próximo presidente, o que ocorrer primeiro.

Segundo publicado no diário oficial da União, o horário de verão começará sempre no terceiro domingo de Outubro e terminará no terceiro domingo de fevereiro, exceto se tal domingo, for o domingo de carnaval. Nesse caso, termina no quarto domingo.

As datas fixas facilitam um pouco, pois é possivel uma configuração também fixa. Não levando em conta a exceção, o arquivo de timezone ficaria assim:

  #Rule   NAME  FROM  TO    TYPE  IN   ON         AT    SAVE      LETTER/S
  Rule    BR    2008  only   -    Feb  17         0:00  0:00      S
  Rule    BR    2008  MAX    -    Oct  Sun>=15    0:00  1:00      D
  Rule    BR    2009  MAX    -    Feb  Sun>=15    0:00  0:00      S
  
  #Zone   NAME            GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
  Zone    Brazil/East      -3:00   BR             BR%s

e a compilação do arquivo e uma rápida verificação retornaria:

  [root@babylon5 ~]# zic -v /tmp/Brazil_East.zic
  [root@babylon5 ~]# zdump -v -c 2016 Brazil/East
  Brazil/East  Fri Dec 13 20:45:52 1901 UTC = Fri Dec 13 17:45:52 1901 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sat Dec 14 20:45:52 1901 UTC = Sat Dec 14 17:45:52 1901 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 19 02:59:59 2008 UTC = Sat Oct 18 23:59:59 2008 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 19 03:00:00 2008 UTC = Sun Oct 19 01:00:00 2008 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 15 01:59:59 2009 UTC = Sat Feb 14 23:59:59 2009 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 15 02:00:00 2009 UTC = Sat Feb 14 23:00:00 2009 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 18 02:59:59 2009 UTC = Sat Oct 17 23:59:59 2009 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 18 03:00:00 2009 UTC = Sun Oct 18 01:00:00 2009 BRD isdst=1 gmtoff=-7200
  ...

Como podem ver, em 2008, o horário de verão começaria em 19 de Outubro e terminaria em 15 de fevereiro.

Mas a tal exceção me deixou intrigado. A exceção tirou a beleza de uma configuração fixa, o que me fez coçar os neurônios.

Já conhecia a man page do zic(1) há tempos. Lá fala de uma função yearistype que é chamada para cada ano, e se retornar verdadeiro (true) a respectiva linha no time zone é aplicada.

Humm...então essa função poderia então ser usada para tratar a exceção da regra do "Horário de Verão Brasileiro a partir de 2008". Para tanto, "basta" saber se o domingo que antecede o carnaval cai no terceiro domingo do mês. Se cair, aplica-se a regra do quarto domingo do mês. Simples não ?

Humm...o problema é que o carnaval, uma festa pagã, é data móvel, determinada pela data em que cai outro feriado, a páscoa, um feriado sagrado da igreja Católica Romana, outra data móvel, que é determinada, segundo regras estabelecidas pelo concilio de Nicea no longiguo ano de 325, como sendo o primeiro domingo depois da primeira lua cheia depois do equinócio vernal (equinócio da primavera no hemisfério norte).

Humm...complicado heim ?

Bem, como Google é pai e wikipedia é mãe, acabei encontrando o algoritmo elaborado por "Meeus/Jones/Butcher" válido para quem usa o calendário gregoriano (somos nós ! - Os católicos ortodoxos orientais usam o calendário Juliano) (http://en.wikipedia.org/wiki/Computus#Algorithms)

Humm...então basta eu implementar esse algoritmo para descobrir a data da páscoa de um determinado ano, obter dai a data do carnaval e testar se domingo que o antecede é o terceiro domingo e se for, aplica-se a exceção! Está ficando simples....

Implementei o algoritmo de "Meeus/Jones/Butcher" em dc(1). (Salve os comandos dc abaixo em /usr/local/lib/easter.dc)

  # y=year from cmd line
  sy
  0 k
  # a=y mod 19
  ly 19 % sa
  # b=y/100
  ly 100 / sb
  # c=y mod 100
  ly 100 % sc
  # d=b/4
  lb 4 / sd
  # e=b mod 4
  lb 4 % se
  # f=(b+8)/25
  lb 8 + 25 / sf
  # g = (b - f + 1) / 3
  lb lf - 1 + 3 / sg
  # h = (19 × a + b - d - g + 15) mod 30
  19 la * lb + ld - lg - 15 + 30 % sh
  # i = c / 4
  lc 4 / si
  # k = c mod 4
  lc 4 % sk
  # L = (32 + 2 × e + 2 × i - h - k) mod 7
  32 le 2 * + li 2 * + lh - lk - 7 % sl
  # m = (a + 11 × h + 22 × L) / 451
  la 11 lh * + 22 ll * + 451 / sm
  # n=(h + L - 7 × m + 114)
  lh ll + 7 lm * - 114 + sn
  # month= n/31
  ln 31 /
  4 k
  100 /
  # day=(n mod 31)+1
  0 k
  ln 31 % 1 +
  4 k
  10000 / + ly +
  p

...e use-o como:

  [miguel@babylon5 ~]$ dc -e 2008 -f /usr/local/lib/easter.dc
  2008.0323
  [miguel@babylon5 ~]$ dc -e 2009 -f /usr/local/lib/easter.dc
  2009.0412
  [miguel@babylon5 ~]$ dc -e 2010 -f /usr/local/lib/easter.dc
  2010.0404
  [miguel@babylon5 ~]$

(as datas da páscoa dos anos passados na CLI são retornadas no formato yyyy.mmdd)

humm...agora é necessário descobrir a data do carnaval. O tal conselho de Nicea decidiu que deve se haver pelo menos 40 dias entre o final do carnaval e a sexta-feira santa que antecede a páscoa, a fim de que os fieis se preparem e jejuem adequadamente depois daquela esbórnia da festa pagã em homenagem ao deus "Sol" Trocando em miúdos, entre a terça-feira do carnaval e o domingo de páscoa devem haver exatos 47 dias. Mas eu quero saber não quando é a terça feira de carnaval, mas sim, quando é o domingo que antecede tal terça-feira - ora, trivial, são 49 dias.

humm...como subtrair de uma data (a data da páscoa), um determinado número de dias (47) ? :scratch:

Os leitores talvez possam sugerir outras alternativas. Eu usei os comandos jday e j2d do pacote jday do fedora 9 (jday-2.4-3.fc9.i386) (http://sourceforge.net/projects/jday/)

"basta" então converter uma data (a data da páscoa) para um número Juliano (usando o comando jday), subtrair 49 (usando expr) e converter esse outro número juliano para uma data do calendário gregoriano (usando j2d) !

Usando o código abaixo vcs podem verificar que o domingo que antecede o carnaval no ano de 2009 sera o dia 22 de fevereiro, "simples" não ?

  year="2009"
  easter=$(dc -e $year -f /usr/local/lib/easter.dc | sed -e 's/\./-/; s/-\([0-9]\{2\}\)/-\1-/')
  jday=$(jday -d $easter 0:0:0 | cut -d. -f 1)
  
  # The sunday before carnival is 49 dias before easter (48, in jday account)
  jcar=$(expr $jday - 48)
  
  carnival=$(j2d $jcar | cut -d' ' -f 1)
  echo "Sunday of carnival is on $carnival"

Voilá...então se o tal dia for maior ou igual a 15 e menor que 22, então é o terceiro domingo ! Fim da coceira nos neuronios.

Então já temos tudo para o compilador de zonas criar um arquivo binário com todas a regra do "Horario Brasileiro de Verão", incluindo as exceções.

O arquivo de zonas fica assim:

  #Rule   NAME  FROM  TO    TYPE          IN   ON         AT    SAVE      LETTER/S
  Rule    BR    2008  MAX    -            Oct  Sun>=15    0:00  1:00      D
  Rule    BR    2008  MAX    regular      Feb  Sun>=15    0:00  0:00      S
  Rule    BR    2008  MAX    carnOn3rdSun Feb  Sun>=22    0:00  0:00      S
  
  
  #Zone   NAME            GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
  Zone    Brazil/East      -3:00   BR             BR%s

O arquivo acima faz menção a dois tipos de anos: "regular" é o ano onde o horário de verão começa no terceiro domingo. "carnOn3rdSun" é o ano onde o horário de verão começa no quarto domingo porque o domingo que antecede o carnaval cai no terceiro domingo.

O programa zic(1) irá chamar o programa yearistype passando como primeiro argumento um ano, e como segundo argumento o conteúdo do campo TYPE ("regular" ou carnOn3rdSun)

humm...(é o último, eu prometo), mas cadê o tal programa yearistype? Basicamente é o código imediatamente acima, em "bash", com o valor de retorno correto. Não fiz a critica sobre os argumentos de entrada, uma vez que esse código é para ser chamado pelo zic, sempre da mesma maneira. Mas quem quiser, fique a vontade para fazer o tratamento dos argumentos de entrada.

Salve o código abaixo em /usr/local/bin ou outro lugar que o zic (como root) possa chamar o programa. Verifique se o seu programa zic aceita a especificação do path do comando yearistype. No Fedora 9 é possivel usar a chave -y para indicar o path do comando yearistype (zic -y ~miguel/bin/yearistype zone_file.zic)

  #!/bin/bash
  
  #
  # Usage: yearistype year type
  #
  
  year=$1
  type=$2
  
  function check3rdSun() {
         easter=$(dc -e $year -f /usr/local/lib/easter.dc | sed -e 's/\./-/; s/-\([0-9]\{2\}\)/-\1-/')
         jday=$(jday -d $easter 0:0:0 | cut -d. -f 1)
  
         # The sunday before carnival is 48 dias before easter
         jcar=$(expr $jday - 48)
  
         carnival=$(j2d $jcar | cut -d' ' -f 1)
         #echo "Sunday of carnival is on $carnival"
  
         # I want only the day of month
         carday=$(echo $carnival | cut -d- -f3)
  
         # return 0 if it is the 3rd Sunday, 1 otherwise
         [ "$carday" -ge "15" ] && [ "$carday" -lt "22" ] && return 0 || return 1
  }
  
  check3rdSun $year
  rc=$?
  
  case $type in
         carnOn3rdSun)
                 #echo "carnOn3rdSun: $carnival $rc"
                 exit $rc
                 ;;
         *)
                 #echo "regular: $carnival $rc"
                 [ "$rc" = "0" ] && exit 1 || exit 0
  esac

O próximo passo é a compilação do arquivo de zonas e teste:

  [root@babylon5 ~]# zic -v -y ~miguel/bin/yearistype ~miguel/src/Brazil_East.zic
  [root@babylon5 ~]# zdump -v -c 2016 Brazil/East
  ...
  Brazil/East  Sun Feb 17 01:59:59 2008 UTC = Sat Feb 16 23:59:59 2008 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 17 02:00:00 2008 UTC = Sat Feb 16 23:00:00 2008 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 19 02:59:59 2008 UTC = Sat Oct 18 23:59:59 2008 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 19 03:00:00 2008 UTC = Sun Oct 19 01:00:00 2008 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 15 01:59:59 2009 UTC = Sat Feb 14 23:59:59 2009 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 15 02:00:00 2009 UTC = Sat Feb 14 23:00:00 2009 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 18 02:59:59 2009 UTC = Sat Oct 17 23:59:59 2009 BRS isdst=0 gmtoff=-10800
  Brazil/East  Sun Oct 18 03:00:00 2009 UTC = Sun Oct 18 01:00:00 2009 BRD isdst=1 gmtoff=-7200
  ...
  Brazil/East  Sun Feb 26 01:59:59 2012 UTC = Sat Feb 25 23:59:59 2012 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 26 02:00:00 2012 UTC = Sat Feb 25 23:00:00 2012 BRS isdst=0 gmtoff=-10800
  ...
  Brazil/East  Sun Feb 22 01:59:59 2015 UTC = Sat Feb 21 23:59:59 2015 BRD isdst=1 gmtoff=-7200
  Brazil/East  Sun Feb 22 02:00:00 2015 UTC = Sat Feb 21 23:00:00 2015 BRS isdst=0 gmtoff=-10800
  ...

Em 2009 o horário de verão termina às 0:00hs do dia 15 (voltando a ser 23:00hs do dia 14), seguindo a regra "regular". Já em 2012 ocorre uma das exceções: O horário de verão termina em 26 de fevereiro, que é o quarto domingo, porque o carnaval em 2012 ocorre em 21, sendo o domingo que o antecede, o terceiro domingo do mês. Outra excessão ocorre em 2015, com o horário de verão terminando no quarto domingo, dia 22.

Para ver todas as excessões, edite o arquivo yearistype des-comentando os dois comandos echo que existem dentro do case (echo ``carnOn3rdSun: $carnival $rc) e (echo ``regular: $carnival $rc).

Depois disso, execute o comando dentro de um laço for do bash:

  [miguel@babylon5 ~]$ for y in $(seq 2008 2100 ) ; do ~/bin/yearistype $y carnOn3rdSun; done
  carnOn3rdSun: 2008-02-03 1
  carnOn3rdSun: 2009-02-22 1
  carnOn3rdSun: 2010-02-14 1
  carnOn3rdSun: 2011-03-06 1
  carnOn3rdSun: 2012-02-19 0
  carnOn3rdSun: 2013-02-10 1
  carnOn3rdSun: 2014-03-02 1
  carnOn3rdSun: 2015-02-15 0
  ...

Todas as linhas que terminam com 0 indicam os anos cujo domingo de carnaval cai no terceiro domingo do mes. São as excessões da regra geral.

Vocè pode até compilar o arquivo de zonas com o zic deixando o arquivo yearistype com os echos des-comentados. Você irá ver a invocação, pelo zic, do comando yearistype e a respectiva saida. Experimente !

Há espaço para otimizações.

Eu suspeito que o uso do comando jday/j2c pode ser eliminado, calculando-se diretamente a data do carnaval, não a data da pascóa.

Para isso, é necessário adaptar o algoritmo de "Meeus/Jones/Butcher" para obter uma data (47+2) dias antes, mas é preciso investigar o algoritmo para verificar se isso é realmente possivel e mais fácil do que usar j2c/jday. Fica a sugestão para os mais aventurosos.

Foi um dia produtivo. Me diverti resolvendo o problema e depois mais ainda em escrever esse blog que espero ser útil para demonstrar a flexibilidade do unix e o poder dos scripts e utilitários.

  # y=year from cmd line
  sy
  0 k
  # a=y mod 19
  ly 19 % sa
  # b=y/100
  ly 100 / sb
  # c=y mod 100
  ly 100 % sc
  # d=b/4
  lb 4 / sd
  # e=b mod 4
  lb 4 % se
  # f=(b+8)/25
  lb 8 + 25 / sf
  # g = (b - f + 1) / 3
  lb lf - 1 + 3 / sg
  # h = (19 × a + b - d - g + 15) mod 30
  19 la * lb + ld - lg - 15 + 30 % sh
  # i = c / 4
  lc 4 / si
  # k = c mod 4
  lc 4 % sk
  # L = (32 + 2 × e + 2 × i - h - k) mod 7
  32 le 2 * + li 2 * + lh - lk - 7 % sl
  # m = (a + 11 × h + 22 × L) / 451
  la 11 lh * + 22 ll * + 451 / sm
  # n=(h + L - 7 × m + 114)
  lh ll + 7 lm * - 114 + sn
  # month= n/31
  ln 31 /
  4 k
  100 /
  # day=(n mod 31)+1
  0 k
  ln 31 % 1 +
  4 k
  10000 / + ly +
  p
  
  #!/bin/bash
  
  #
  # Usage: yearistype year type
  #
  
  year=$1
  type=$2
  
  function check3rdSun() {
         easter=$(dc -e $year -f /usr/local/lib/easter.dc | sed -e 's/\./-/; s/-\([0-9]\{2\}\)/-\1-/')
         jday=$(jday -d $easter 0:0:0 | cut -d. -f 1)
  
         # The sunday before carnival is 48 dias before easter
         jcar=$(expr $jday - 48)
  
         carnival=$(j2d $jcar | cut -d' ' -f 1)
         #echo "Sunday of carnival is on $carnival"
  
         # I want only the day of month
         carday=$(echo $carnival | cut -d- -f3)
  
         # return 0 if it is the 3rd Sunday, 1 otherwise
         [ "$carday" -ge "15" ] && [ "$carday" -lt "22" ] && return 0 || return 1
  }
  
  check3rdSun $year
  rc=$?
  
  case $type in
         carnOn3rdSun)
                 #echo "carnOn3rdSun: $carnival $rc"
                 exit $rc
                 ;;
         *)
                 #echo "regular: $carnival $rc"
                 [ "$rc" = "0" ] && exit 1 || exit 0
  esac

Veja a relação completa dos artigos de Miguel Angelo Rozsas

Stumble Upon Digg This Del.icio.us Twitter Recomendar este artigo a um amigo Entre em contato Formato PDF
Newsfeed RSS
Formato para impressão
StumbleUpon Digg Del.icio.us Twitter Recomendar Contato PDF RSS Imprimir

Referências Adicionais

Referências adicionais sobre os assuntos abordados neste site podem ser encontradas em nossa Bibliografia.

Avalie esta dica

  • Currently 3.05/5
  • 1
  • 2
  • 3
  • 4
  • 5

Avaliação: 3.0 /5 (349 votos)

Opinião dos Leitores

rahxa
20 Set 2008, 23:21
Excelente dica. Parabéns.
Jose Geraldo
20 Set 2008, 23:14
Caro Miguel

Parabens pelo artigo.

Acho que voce poderia incluir mais um parágrafo para ensinar como apontar o Linux para trabalhar com a zona alterada, copiando o arquivo gerado para /etc/localtime ou fazendo um link simbolico para /usr/share/zoneinfo/Brazil/East.

Abraços
JGeraldo
João Marcos
20 Set 2008, 13:08
Eu sempre leio suas dicas, mas esta me surpreendeu, pela flexibilidade do linux e pelo seu trabalho que envolveu pesquisa e em resolver um problema e compartilhar a solução com todos, voce é um cara 10.
Dorian Bolivar
20 Set 2008, 12:21
Excelente artigo! Aproveitando o espaço para comentários, gostaria de opinar sobre esse decreto do governo para o horário de verão.

Sinceramente, se há uma exceção à regra (for carnaval no domingo), não adiantou nada! Continuarão sendo necessárias atualizações ou intervenções manuais para corrigir o horário de verão... Por que não fizeram um negócio decente e colocaram a data de término do horário de verão em um domingo que certamente nunca será carnaval?
Alvaro Figueiredo
20 Set 2008, 11:10
Perdão, vou colar novamente o código Python, por causa da perda de formatação :(

#!/usr/bin/env python
# yearistype

import mx.DateTime
import sys

year = int(sys.argv[1])
yearType = sys.argv[2]

carnivalSunday = mx.DateTime.Feasts.EasterSunday(year) - 49 * mx.DateTime.oneDay

returnCode = 15 <= carnivalSunday.day < 22
if yearType != 'regular': returnCode = not returnCode
returnCode = int(returnCode)

print carnivalSunday.Format('%Y-%m-%d'), returnCode

sys.exit(returnCode)
Alvaro Figueiredo
20 Set 2008, 11:02
Excelente artigo, parabéns e muito obrigado.

Gostaria de aproveitar a oportunidade e deixar uma contribuição para quem aprecia a linguagem de programação Python.

Se instalar o pacote abaixo da sua distribuição Linux (estou usando o Ubuntu 7.10),

python-egenix-mxdatetime

o programa yearistype pode ficar assim:

#!/usr/bin/env python
# yearistype

import mx.DateTime
import sys

year = int(sys.argv[1])
yearType = sys.argv[2]

carnivalSunday = mx.DateTime.Feasts.EasterSunday(year) - 49 * mx.DateTime.oneDay

returnCode = 15 <= carnivalSunday.day < 22

if yearType != 'regular':
returnCode = not returnCode
returnCode = int(returnCode)

print carnivalSunday.Format('%Y-%m-%d'), returnCode

sys.exit(returnCode)
Bruno V Magaldi
20 Set 2008, 09:10
Parabéns! Muito bom. Não faz parte de meu dia a dia profissional tal tipo de tarefa, que creio estar restrita mais aos administradores mas gostei do desenvolvimento do script. Parabéns cara!
felipe
19 Set 2008, 02:46
Bom artigo. Mas passar o dia só pra acertar o horário da máquina é versatilidade?
josé geraldo
18 Set 2008, 19:26
Os quarenta dias da quaresma iniciam-se na Quarta-feira de Cinzas e terminam 1 domingo antes da Páscoa , ou seja o Domingo de Ramos. É a partir daí que se contam reatroativamente os 40 dias, e não a partir da Páscoa. A Quaresma (40 dias) acabam antes da Semana Santa que culmina no Domingo de Páscoa.
thiagomz
18 Set 2008, 18:13
To de boca aberta ! Parabéns ! Vou mostrar para a turma de TI aqui o que é documentação !!!! ;-)
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script

English for Reading and Listening
Enriqueça o seu vocabulário recebendo diariamente mensagens divertidas em inglês, com áudio em MP3.
Saiba mais

Biblioteca

Desenvolvendo Websites com PHP
Por Juliano Niederauer

O Monge e o Executivo: uma História sobre a Essência da Liderança
Por James C. Hunter

Extreme Programming
Por Vinicius Manhaes Teles

UML: Guia do Usuário
Por Grady Booch, James Rumbaugh e Ivar Jacobson

O Vendedor de Sonhos
Por Augusto Cury

Segurança de Redes em Ambientes Cooperativos
Por Emilio Tissato Nakamura e Paulo Licio de Geus

O Conhecimento em Rede
Por Carlos Nepomuceno e Marcos Cavalcanti

Utilizando UML e Padrões
Por CRAIG LARMAN

Sistema de Banco de Dados
Por Abraham Silberschatz

Hardware PC: Guia de Aprendizagem Rápida
Por Carlos E. Morimoto

Manual Completo do Linux: Guia do Administrador
Por Evi Nemeth, Trent R. Hein, Garth Snyder

Redes de Computadores e a Internet
Por James F. Kurose e Keith W. Ross

O Segredo
Por Rhonda Byrne

Os Segredos da Mente Milionária
Por T. Harv Eker

Construindo Sites com CSS e (X)HTML
Por Mauricio Samy Silva

Use a Cabeça!: JSP & Servlets
Por Brian Bashan, Kathy Sierra, Bert Bates

Expressões Regulares: Uma Abordagem Divertida
Por Aurélio Marinho Jargas

Qualidade de Software
Por Andre Koscianski Michel dos Santos Soares

Descobrindo o Linux: Entenda o Sistema Operacional GNU/Linux
Por Joao Eriberto Mota Filho

Enterprise Javabeans 3.0
Por Bill Burke, Richard Monson