Java Networking e a Classe Proxy

Com o J2SE 5.0 foi lançada uma grande inovação no que toca a trabalhar com Proxys para realizar conexões.

Antes apenas era possível trabalhar com Proxys recorrendo às propriedades do sistema, este mecanismo funciona mas é muito pouco flexível, com o Java 5 o trabalho é muito facilitado embora exista muito pouca documentação sobre está nova API.

Classe Proxy

Esta classe representa a definição de proxy, um tipo normalmente HTTP ou Socks e um endereço.
Esta API dispõe três tipos de proxy

  • DIRECT – Representa a ligação directa ou seja sem proxy.
  • HTTP – Representa uma proxy sob o protocolo HTTP.
  • SOCKS – Representa uma proxy que utiliza quer SOCKS v4 ou v5,

Seguindo os tipos disponíveis para criar um objecto Proxy HTTP basta o seguinte código

Proxy proxy = new Proxy( Proxy.Type.HTTP, new InetSocketAddress("proxyserver.com", 8080) );

O código acima cria um objecto Proxy do tipo HTTP para o servidor proxyserver.com pela porta 8080.
Já temos a nossa Proxy agora vamos ver como utilizar esta proxy. Para isso vamos utilizar o método openConnection() da classe URL, passando o nosso objecto proxy como argumento.

Proxy proxy = new Proxy( Proxy.Type.HTTP, new InetSocketAddress("proxyserver.com", 8080) );

URL url = new URL("https://wmagician.wordpress.com");

URLConnection conn = (URLConnection) url.openConnection(proxy);

Como podemos ver é muito simples basta abrir a conexão dando a proxy como argumento, com isto a ligação feita a https://wmagician.wordpress.com é feita através do servidor proxyserver.com. Ao invés da classe URLConnection podíamos também utilizar a classe HttpURLConnection que é subclasse da referida.

Podemos também forçar a que uma URLConnection utilize proxys do tipo SOCKS para isso basta mudar o tipo. Vamos usar como exemplo uma ligação a um servidor FTP por URLConnection.

Proxy proxy = new Proxy( Proxy.Type.SOCKS, new InetSocketAddress("socks.proxyserver.com", 1080) );

URL url = new URL("ftp://ftp.servidor.pt/magician.gif");

URLConnection conn = (URLConnection) url.openConnection(proxy);

O exemplo acima uma conexão FTP que vai ser forçada a passar por uma proxy SOCKS.

Para além de Conneções atravez das classes URLConnection e HttpURLConnection podemos ainda fazer ligações por proxys utilizando sockets TCP.
A primeira parte de processo é bastante semelhante aos anteriores, criamos um objecto Proxy com o tipo de proxy, endereço e porta. O passo seguinte é criar um objecto Socket em que passamos como argumento a nossa proxy, para terminar executamos o método connect onde damos o destino final da nosso ligação.

Proxy proxy = new Proxy( Proxy.Type.SOCKS, new InetSocketAddress("socks.proxyserver.com", 1080) );

Socket socket = new Socket( proxy );

socket.connect( new InetSocketAddress("server.magic.com", 9000) );

Muito simples como podemos ver o exemplo faz uma ligação por socket ao servidor server.magic.com na porta 9000, passando pela proxy socks.proxyserver.com na porta 1080.

Aqui fica uma pequena explicação desta classe muito útil e simples mas muito pouco documentada, num proximo artigo irei falar sobre ProxySelecter mais um mecanismo muito útil para trabalhar com Proxys.

Por Fábio Correia (White Magician)

Ruby – Números e Ranges

Ranges

Ruby ao contrário de algumas linguagens tem ranges (“Gamas”), um range é um intervalo com um valor inicial e um valor final. Para isso temos operadores de Range e a classe Range.

Podemos criar um Range de duas formas, uma é utilizando a classe Range

rag = Range.new(1,9)

A expressão acima cria um Range com os valores de 1 a 9 inclusive, mas é possivél criar Ranges de forma mais simples utilizando (..) e (…)

rag = (1..9)

Esta expressão faz exactamente o mesmo que a anterior, basta utilizar parênteses e (..) para ter um Range de 1 a 9, caso quisesse-mos nãuo incluir o 9 no nosso Range bastaria trocar o (..) por (…), ou seja com (..) é incluido o ultimo valor e com (…) o ultimo valor é excluído.

O método === determina se um valor está contido nos valores do Range para isso basta por exemplo

(1..25) === 14
=> true

(1..25) === 26
=> false

Ranges permite-nos ainda a sua conversão para um arrays de forma simples, para isso basta utilizar o método to_a e é criado um array com os valores do Range.

(1..9).to_s
=> [1,2,3,4,5,6,7,8,9]

Sobre os Números

Algumas vezes precisamos algumas coisas sobre os números ou as variáveis. Se é inteiro, se é ou não zero, etc…
Vamos começar com coisas simples, por exemplo verificar se um numero é igual ou não a zero.

op = 0

op.zero?
=> true

op = 10

op.zero?
=> false

É ainda possível verificar se um numero é inteiro ou não, a classe Numeric fornece o método integer? que verifica se um numero é inteiro.

12.integer?
=> true

12.0.integer?
=> false

-1.integer?
=> true

-12.integer?
=> true

A classe Float dispõe ainda dos métodos finite? e infinite?, que permite verificar se um numero é ou não infinito ou finito.

0.0.finite?
=> true

(-1.0/0.0).finite?
=> false

(+1.0/0.0).finite?
=> false

0.0.infinite?
=> nil

(-1.0/0.0).infinite?
=> -1

(+1.0/0.0).infinite?
=> 1

O método infinite? permite ter mais algumas informações sobre o numero infinito, por exemplo saber se é um infinito positivo, negativo ou neutro.

É possível ainda executar blocos de código sob números, os blocos de código serão analisados em outro capitulo, mas aqui veres alguns exemplos simples dos métodos para blocos de código existentes nas classes numéricas.
O método times cria uma iteração de 0 até ao valor, neste caso vamos usar o valor 5

5.times{ |i| print i, " "}
=> 0 1 2 3 4

Neste exemplo o bloco de código faz print para cada um dos valores da iteração.

A classe Integer dispõe ainda dois métodos muito úteis, o método downto e o método upto.
O método downto  permite  criar uma iteração  de um valor inicial até um valor final, por exemplo queremos todos os números de 100 até 1.

100.downto(1) { |n| print n}

O método upto faz o mesmo mas de forma inversa ou seja faz a iteração por ordem crescente, neste caso de 1 até 100.

1.upto(100) { |n| print n}

Por Fábio Correia (White Magician)

Ruby – Números e Math Basico

Na maioria das linguagens os números são um tipo primitivo usados por outros objectos, em Ruby tudo ou quase tudo é um objecto até mesmo os números. Vejamos alguns exemplos quem em outras linguagens são considerados primitivos mas quem em Ruby são objectos, vejamos a que classes pertencem.

5.class
5.0.class
5_000_000_000.class

O primeiro exemplo retorna a classe Fixnum, o segundo Float e o terceiro Bignum.
Como se pode ver Ruby transforma quase tudo em um objecto, os underscore no ultimo exemplo são facultativos podem ser ou não usados no momento da execução o interpretador simplesmente ignora-os.

Ruby tem por isso algumas classes e modules dedicados a números, vamos ver os mais importantes.

Numeric – A classe base para todos os numeros.

Integer – A classe base para números inteiros e a base da classe Fixnum.

Float – A classe para números reais e de ponto flutuante.

Fixnum – A classe principal para números inteiros.

Bignum – A classe para números inteiros com tamanho superior ao suportado pela classe Fixnum.

Math – Modulo com contém as principais funções matemáticas.

Precision – Modulo para aproximas a precisão de números reais.

Rational – Uma classe que representa os números fraccionários.

Complex – Classe que representa os números complexos.

Matrix – Classe para criar matrizes matemáticas.
Converter Números

Ruby permite a conversão de números de outros formato para inteiro de forma simples com o método Integer.

Integer(1.4)

Integer("256")

Integer("0b11110010")

Integer(0177)

Integer(0x20)

Integer(?z)

Por ordem o que acontece é o seguinte o primeiro exemplo converte um numero float para inteiro, o segundo converte uma String para inteiro, o terceiro converte um numero binario contido em uma String para inteiro, o quarto exemplo converte um numero octal para inteiro, o quinto converte um hexadecimal para inteiro e o ultimo converte um carácter para inteiro que corresponde ao código do carácter.

Ruby permite ainda converter números para float para evitar casos em que a conversão para inteiro origina a perda de precisão.

Float(167)

Float("77")

Float(?a)

Novamente por ordem o primeiro exemplo converte o inteiro para float, o segundo converte a String para float e o ultimo exemplo converte o carácter para float.
Operações Matemáticas

Operações matemáticas são extremamente simples, vamos ver alguns exemplos básicos.

Soma
7 + 5

=> 12
Subtracção
20 - 8

=> 12
Multiplicação
6 * 2

=> 12
Dividir
144 / 12

=> 12
Exponente
2 ** 4

=> 16
Modulo
12 % 5

=> 2

Ruby permite ainda à semelhança da maioria das linguagens a utilização de operadores unitários de positivo e negativo (+) e (-).

7 + -5
=> 2

-20 + -32
=> -52

20 * -2
=> -40

E como tudo é um objecto podes ainda utilizar métodos para fazer algumas operações como div, modulo, divmod, quo e remainder.

Divisão
24.div 2
=> 12

(25.0).div(2.0)
=> 12

Modulo
12.modulo 5
=> 2

12.modulo(5.0)
=> 2.0

Retorna um array com o quociente e o resto da divisão.
12.divmod 5
=> [2, 2]

12.0.divmod 5.0
=> [2, 2.0]

Retorna o valor total da divisão.
12.quo 5
=> 2.4

Retorna o resto da divisão
12.remainder 5
=> 2

Divisão

A divisão de números contém um pequeno problem, quantdo o resultado da divisão contem uma parte fraccionaria, essa parte é descartada, vejamos alguns exemplos e como os resolver.

24 / 2
=> 12
Não há problema.

25 / 2
=> 12
Problema com o resultado.

25.0 / 2
=> 12.5
Resolve-se usado um ou mais dos números como float.

Igual, Maior que, Menor que

Podemos também fazer comparação de números, para isso dispomos os operadores de igualdade (==), (eql?) ou (<=>).

12 == 24/2
=> true
Verifica se dois números tem o mesmo valor.

24.eql?(12*2)
=> true
Tal como o exemplo anterior compara os dois valores.

12 != 14
=> true
Verifica se dois números tem valor diferente.

12 <=> 12
=> 0
Verifica se dois números tem o mesmo valor e retorna 0 no caso afirmativo.

12 <=> 10
=> 1
Verifica se dois números tem o mesmo valor e retorna 1 caso o primeiro valor seja maior que o segundo.

12 <=> 14
=> -1
Verifica se dois números tem o mesmo valor e retorna -1 caso o primeiro valor seja menor que o segundo.

Para além dos operadores de igualdade estão também disponíveis operadores de comparação
mais flexíveis e simples que o (<=>) visto anteriormente, estes operadores são (<),(>),(<=) e (>=).

12 < 14
=> true
Verifica se o primeiro número é menor que o segundo.

12 < 12
=> false

12 <= 12
=> true
Verifica se o primeiro número é menor ou igual ao segundo.
12.0 > 11.9
=> true
Verifica se o primeiro número é maior que o segundo.

12.0 >= 12
=> true
Verifica se o primeiro número é maior ou igual ao segundo.

Abreviatura de operações

É ainda possível abreviar operaçõe, ou seja reduzir o tamanho de uma expressão. Por exemplo

x = x +1

Esta expressão pode ser reduzida a um simples

x += 1

Ambas as operações fazem exactamente o mesmo, estas simplificações podem ser feitas para todas as operações anteriormente, (+),(-),(*),(/),(**) e (%).
Ao contrario de linguagens Java e C que permitem expressões tipo i++ ou i– em Ruby temos de utilizar expressões tipo x += 1 e x -= 1.
Por Fábio Correia (White Magician)

Ruby – Variáveis

Uma variável é um identificar ou nome que está associados a um valor e esse valor tem ou irá ter um tipo no momento da execução, podemos ver um exemplo simples.

x = 100

A variável x é associada ao valor 100 pelo símbolo igual. Agora a variável local x tem o valor 100.
Então mas e qual é o tipo da variável? Ao contraio da maioria das linguagem como Java, C/C++, D entre outras que são estaticamente tipadas ou seja uma variável tem um tipo associado desde o momento em que a variável é definida.

Por exemplo a declaração de variáveis é feita da seguinte forma.

int x = 10;
int y = 90;

Ruby não tem declaração de tipos apenas atribui um valor a uma variável como o seguinte exemplo

x = 10
y = 90

também não precisamos de um terminador como Java que usa o ‘;’ para terminar uma declaração em Ruby basta passar de linha e a declaração está feita.

As variáveis x e y são ambos do tipo inteiro mas essa atribuição é feita automaticamente pelo Ruby e não pelo programador por isso podemos dizer que Ruby é uma linguagem dinamicamente tipada, embora a variável não tenha um tipo associado esse tipo existe mas varia com o tipo de valor associado à variável.

Vejamos agora como saber de que tipo é a variável e como converter o tipo de uma variável, operação muito úteis quando queremos ter um controlo sobre variáveis.

O métodos kind_of? retorna true ou false dependendo se o tipo da variável corresponde ao tipo testado ou não.

x.kind_of? Integer 

O resultado será true, isto porque o valor de x é uma instância da classe Fixnum que é uma subclasse da classe Integer.

x.class

Como se podemos ver o resultado é Fixnum, esta classe tem também um método muito útil, o método to_f converte um inteiro para um float de forma simples.

x.to_f

Esta expressão irá retornar o valor 10.0 ou seja o valor da variável x convertido de inteiro para float.

Variáveis Locais

Acima foi referido que a variável x era uma variável local, ou seja tem um escopo loca, de contexto, por exemplo uma variável local definida dentro de um método ou um ciclo terá apenas um ciclo de vida limitado ao método ou ciclo, ou seja qualquer variáveis definia dessas condições não poderá ser acedida depois de terminado o método ou ciclo.
As variaveis locais deve começar com letra minúscula ou com underscore (_), por exemplo nome ou _nome.

Variáveis de Instância

Uma variável de instância é uma variável referenciada por uma instância de classe e por isso a variável pertence a um objecto. As variáveis de instância é precedida pelo simbolo (@) da seguinte forma.

@nome = "Magician"

Variáveis de Classe

Uma variável de classe é partilhada por todos os objectos da classe, apenas um copia da variável é criada para a classe e para todos os seus objectos e deve ser inicializada antes de ser usada. Estas variáveis é precedida por (@@).

@@contador = 0

Variáveis Globais

Uma variável global pode ser acedida globalmente por todo o programa, dentro de qualquer estrutura. As variáveis globais são precedidas por ($).

$version = 1

As variáveis globais são difíceis de controlar e por isso devem ser usadas apenas em casos muitos especifico e em ultimo recurso.

Constantes

Uma constante é basicamente uma variável que tem o mesmo valor durante a execução de todo o programa. As constantes são nomeadas com a primeira letra maiúscula ou todas as letras do nome em maiúscula.

PI = 3.14159265

Se uma constante é definida dentro de uma classe ou modulo é possível ter acesso a ela de qualquer parte de classe ou do modulo, se for definida fora de uma classe ou modulo a constante é acessível globalmente.
Ao contrário da maioria das linguagem de programação as constantes são mutáveis ou seja o sei valor pode ser alterado.

Declaração em Paralelo

A declaração em paralelo é um forma de declarar uma serie de variáveis de uma só vez, ao invés do clássico

a = 1
b = 2
c = 5

podemos utilizar um simples

a, b, c = 1, 2, 5

e podemos até utilizar a declaração em paralelo para a declarar uma serie de variáveis de tipo diferentes.

a, b, c = "xy", 2, 5.0

Desta forma termina este capitulo variáveis.

Por Fábio Correia (White Magician)

Ruby – Comentários

Um comentário “esconde” uma ou mais linhas do interpretador de Ruby , sendo assim essas linhas são ignoradas durante a execução do programa, isto permite ao programador inserir informação no código que poderá vir a facilitar futuras alterações a facilitar a interpretação do código por terceiros.

Em Ruby existem dois tipos básicos de comentários, o comentários simples que é usado para comentar uma linha e o comentário em bloco que permite comentar varias linhas.

Comentários Simples

O comentários simples é declarado usando o carácter (#), ele pode ser usado no inicio da linha

# Esta linha é um comentário.

ou depois de uma expressão ou declaração

nome = "Magician" #Comentário após uma declaração.

Com o comentário simples é ainda possível comentar várias linhas

# Isto é um comentário.
# Tal como isto
# e isto
# e por ai fora

o bloco acima pode ser simplificado usando o comentário em bloco como podemos ver a seguir.

Comentários em Bloco

Os comentários em bloco são muito úteis para comentar varias linhas sem ter que usar repetidamente o carácter (#), para isso usamos as tags =begin/=end

=begin
Todo o texto escrito entre
estas duas tags é considerado
como comentário pelo interpretador.
=end

O comentário em bloco permite comentar varias linhas ou apenas uma mas no caso de uma simples linha é aconselhável comentário simples por uma questão de rapidez e simplicidade.

Por Fábio Correia (White Magician)

Shell Script

Shell é a linha de comandos de Linux e Unix, é ela que interpreta todos os comandos inseridos pelo utilizador. Para além de executar comandos do sistema esta também tem comandos de programação tais como IF, FOR, WHILE, variáveis e também funções, permitindo desta forma criar chamadas de comandos mais flexíveis.

Shell Script é basicamente um ficheiro com uma determinada sequência de comandos Shell, estes scripts podem ser executados de diversas formas podemos criar o nosso script e executá-lo usando os comandos “sh” ou “bash”.

sh Script.sh

ou

bash Script.sh

Ambos executam o script, com uma diferença, o “sh” é o interpretador standard de comandos Shell, por sua vez o “bash” é o interpretador de comandos Shell tal como o “sh”, mas com mais algumas funcionalidades, nomeadamente o suporte de variáveis do tipo Array, Select, Read, etc… Por esse motivo vamos usar o “bash”.

Uma outra forma de executar o nosso script é tornando-o executável. Para isso na primeira linha do nosso script colocamos o caminho para o interpretador, por exemplo:

#!/bin/bash

printf “Hello World”

Em seguida executamos o comando

chmod +x Script.sh

para tornar o nosso script executável e depois basta corrê-lo.

Vamos agora passar à prática, começando por ver como definir variáveis para o nosso Shell Script. A declaração de variáveis é bastante simples, basta colocar o “nome=valor” sem espaços. Vamos ver vários exemplos de declaração de variáveis.

#!/bin/bash

Nome=”White Magician”;
NUMERO=70101;
_ID1=1;
_id2=”ABFISOEEQS”;

echo $Nome
echo $NUMERO
echo $_ID1;
echo $_id2;

Como podemos ver as variáveis podem ter nomes com letras de a..z e A..Z, números e “_”. Embora possam conter números estes não podem ser colocados no início, pois variáveis iniciadas com um número estão reservadas para a Shell. O uso de ‘;’ não é obrigatório como podemos ver, mas existem casos em que o seu uso faz parte da sintaxe. Veremos esses casos mais à frente. No exemplo para aceder ao valor guardado numa variável usamos o prefixo ‘$’.

As variáveis podem aí ser de valor constante, ou seja, o seu valor não pode ser alterado, para isso usamos o comando readonly como podemos ver em seguida.

#!/bin/bash

var=1000;
readonly var;
readonly var2=12;
var=9;

Ao executar este script ele irá retornar um erro dizendo que a variável var é apenas de leitura. Podemos declarar a variável e em seguida declará-la como readonly ou então fazer os dois passos de uma vez como podemos ver.

As variáveis podem aí ser eliminadas, ou seja apagadas da lista de variáveis da Shell. Para isso basta usar comando unset, mas este comando apenas funciona em variáveis não declaradas como readonly.

#!/bin/bash

var1=100;
readonly var2=10;
unset var1;
unset var2;

echo $var1;
echo $var2;

Ao executar este script podemos ver duas operações importantes. Primeira, ao fazer echo $var1 não será impresso nenhum valor, visto esta variável já não existir. Segunda, o retorno de um erro devido à tentativa de eliminar uma variável readonly e que ao ser impresso o seu valor foi mantido.

Uma estrutura muito útil para a criação de scripts dinâmicos e mais flexíveis é o array, também disponível na nossa Shell, mas apenas no “bash” e não no “sh”. Os arrays podem ser facilmente usados com a seguinte sintaxe “nome[índice]=valor”. Vamos agora ver o seu funcionamento.

#!/bin/bash

lista[0]=9999;
lista[1]=1111;
lista[10]=333;

echo ${lista[0]};
echo ${lista[1]};
echo ${lista[10]};
echo ${lista[@]};

Aqui podemos ver um pequeno exemplo da utilização de Array em Shell Script. O índice ‘@’ selecciona todos os índices, ou seja, retorna todos os valores guardados no Array.

O próximo exemplo mostra algumas das mais usadas variáveis de ambiente da Shell.

#!/bin/bash

echo $PWD 	#Caminho para a directoria actual.
echo $UID 	#ID do utilizador que iniciou a Shell
echo $SHLVL 	#Numero de sessões Shell abertas.
echo $REPLY 	#Contém o último input recebido pela função read não suportado pelo “SH”
echo $RANDOM 	#Cria um número aleatório entre 0 e 32767 não suportado pelo “SH”
echo $PATH 	#Caminhos de pesquisa para comandos das Shell.
echo $HOME 	#Caminho para a HOME do utilizador actual.

Ainda no âmbito das variáveis é-nos ainda possível aceder a variáveis especiais. Podemos ver uma pequeno exemplo do uso dessas variáveis:

#!/bin/bash

echo $0		#Nome do Script.
echo $1		#Valor do primeiro argumento do Script.
echo $2		#Valor do segundo argumento do Script.
echo $#		#Numero de argumentos do Script.
echo $@		#Todos os valores dado ao Script.
echo $$ 	#Número do processo do Script.
echo $! 	#Número do último comando em  background.

Vamos agora ver uma alternativa ao comando echo para imprimir dados. O comando printf permite, à semelhança do comando echo, imprimir dados com a vantagem de que consegue fazê-lo de forma formatada o seu funcionamento é praticamente igual ao printf da linguagem C/C++. Vamos ver então alguns exemplo do nosso printf.

#!/bin/bash

printf “Olá %s bem vindo a %s\n” $USER $HOME
printf “Basta colocar o texto entre \”\” \n”
printf “E em seguida as variáveis separadas por um espaço!\n”

Como podemos ver é bastante simples usar o comando printf. É de referir que a ordem pela qual as variáveis são colocadas será a mesma na altura da impressão ou seja colocar $USER $HOME tem um resultado diferente de colocar $HOME $USER.

Algo muito importante para o nosso código são os comentários em Shell Script, que podem ser feitos com o símbolo #. Este carácter indica que toda a linha a partir do carácter deve ser ignorada pelo bash. Mas como já devem ter reparado os nossos scripts começam com #!/bin/bash, que é um caso especial esse comentário é usado para indicar qual a shell que deve ser usada para interpretar o script no nosso caso a “bash”, esta linha deve ser a primeira do nosso script caso contrario será interpretada como um comentário e ignorada pelo interpretador. Vamos agora ver alguns exemplos simples de comentários.

#!/bin/bash

#Todo o texto aqui escrito não será impresso.
printf “Podemos ainda comentar ...” # apenas parte da linha

Infelizmente os comentários de Shell Script não permitem o comentário em bloco por isso apenas podemos comentar um linha na totalidade ou parte dela, indicando o início do comentário mas não o seu fim na linha.

Já sabemos como imprimir dados vamos agora ver como pedir dados ao utilizador. Para isso temos o comando read, que permite ler o input do utilizador vejamos um pequeno exemplo prático.

#!/bin/bash

printf “Utilizador : ”;
read usr;
printf “Password : ”;
read pass;

printf “%s a sua password é %s\n” $usr $pass;

Passemos agora a estruturas condicionais, Shell Script dispõe de estruturas como IF e ELSE, existente em praticamente todas as linguagens de programação, bem como o CASE (também conhecido por SWITCH noutras linguagens de programação). Vamos ver um exemplo da sua utilização comecemos pelo CASE.

#!/bin/bash

read USER;

case$USERin
	magician) printf “Magician seja bem vindo.\n”;;
	root) printf “Bem vindo ao painel de Admin.\n”;;
	*) printf “Utilizador não reconhecido\n”;;
esac;

Como podemos ver a utilização do CASE é bastante simples. Damos uma variável e várias opções, dependendo do valor da variável o resultado será diferente. A opção * serve como um default para quando todas as outras falham. Na estrutura IF ELSE iremos usar um outro comando, o TEST. Este comando permite fazer testes booleanos em ficheiros, strings e números. Mas vamos analisar este comando após o IF que vamos ver agora.

#!/bin/bash

read usr;

if test $usr = “magician”; 
        then
	        printf “Bem vindo Magician\n”;
	else
		printf “%s não reconhecido!\n” $usr;
fi

O comando TEST, como podemos ver, realiza testes entre dois valores e tem várias opções. Vamos ver todas as opções que temos, comecemos então pelas opções em ficheiros.

Opções de teste em Ficheiros

-b FILE True se o ficheiro existe e é um ficheiro bloco especial.
-c FILE True se o ficheiro existe e é um ficheiro de caracteres especiais.
-d FILE True se o ficheiro existe e é um directório.
-e FILE True se o ficheiro existe.
-f FILE True se o ficheiro existe e é um ficheiros regular.
-g FILE True se o ficheiro existe e contém o seu SGID.
-h FILE True se o ficheiro existe e é um link simbólico.
-k FILE True se o ficheiro existe e contém "sticky" bit set.
-p FILE True se o ficheiro existe e é um named pipe.
-r FILE True se o ficheiro existe e permite a sua leitura.
-s FILE True se o ficheiro existe e o seu tamanho é maior que zero.
-u FILE True se o ficheiro existe e contém o seu SUID.
-w FILE True se o ficheiro existe e permite ser escrito.
-x FILE True se o ficheiro existe e é executável.
-O FILE True se o ficheiro existe e o seu dono é o utilizar corrente.

Opções de teste em Strings

-z string          True se a String tem tamanho igual a zero.
-n string          True se a String tem tamanho diferente de zero.
string1 = string2  True se as duas Strings são iguais.
string1 != string2 True se as duas Strings são diferentes.

Opções de teste em números.

int1 -eq int2 True se int1 é igual a int2.
int1 -ne int2 True se int1 não é igual a int2.
int1 -lt int2 True se int1 é menor que int2.
int1 -le int2 True se int1 é menor ou igual a int2.
int1 -gt int2 True se int1 é maior que int2.
int1 -ge int2 True se int1 é maior ou igual a int2.

Opções em expressões

! expr         True se expr é false.
expr1 -a expr2 True se expr1 e expr2 são ambas true.
expr1 -o expr2 True se expr1 ou expr2 é true.

Passemos agora aos ciclos Shell Script dispõem, nomeadamente os FOR e WHILE. Comecemos pelo WHILE com um exemplo simples da sua utilização.

#!/bin/bash

x=0;

while [$x -lt 10]
do
	echo $x;
	x=`expr $x + 1`
done

Algo que pode parecer estranho é sem duvida a linha “x=`expr $x + 1`”. Basicamente o que tudo isto faz é incrementar um valor à variável x, ela envia a expressão $x+1 para o comando expr que processa a expressão matemática e retorna uma valor numérico. O comando deve ser colocado entre “ para dizer ao interpretador que deve executar a expressão e aguardar o valor retornado.

Temos agora o FOR. Este ciclo é bastante simples e menos dinâmico que o WHILE, basicamente o FOR percorre uma sequência de valores e coloca cada um dos valores numa variável temporária que muda de valor a cada ciclo.

#!/bin/bash

for i in 1 9 2 4 3 5 7
do
	echo $i
done

Vamos agora ver como criar funções em Shell Script. A declaração de funções é bastante simples, basta colocar o nome da função seguido de () e um bloco limitado por {}, passemos a um exemplo.

#!/bin/bash

mg=“Magician”;

imprime(){
	printf “Olá %s\n” $mg;
}

imprime;

As funções, ao contrário da maioria das linguagens de programação, em Shell Script não são chamadas sob a forma imprime(), mas apenas com o nome da função sem o par de parêntesis.

Para terminar o nosso artigo irei mostrar como redireccionar o Input/Ouput dos nossos scrips com Shell Script. É possível passar prints para ficheiros e o conteúdo de ficheiros para outros ficheiros até mesmo para variáveis do nosso script.

#!/bin/bash

Text1="Este texto será gravado dentro do ficheiro texto1.txt";

echo $Text1 > texto1.txt;

Text2="Este texto será concatenado ao texto já existente no ficheiro texto1.txt";

echo $Text2 >> texto1.txt

Como podemos ver, é possível redireccionar o output de variáveis do nosso script para ficheiro usando um símbolo >, que apaga todo o conteúdo do ficheiro e insere o valor enviado. Também se podem usar os símbolos », que adiciona o valor enviado ao já existente no ficheiro. Em ambos os casos se o ficheiro não existir ele é criado.

Espero que tenham gostado do artigo, a partir deste momento têm o conhecimento básico sobre Shell Script que permite a criação de scrips para as mais diversas tarefas bastando adaptar as bases ás necessidades.

Este artigo foi originalmente escrito por Fábio Correira (magician) para a 12ª Edição da Revista PROGRAMAR

Revista Programar – 12ª Edição Janeiro 2008

Revista PROGRAMAR
Edição 12 – Janeiro de 2008
Com um novo ano chega uma nova edição da revista Programar, ainda que um pouco mais tarde do que o esperado. No entanto, a revista continua em grande e em força na tarefa de levar a todos o melhor da programação em português para portugueses. Nesta edição poderá contar com:

    Programação Orientada a Objectos em C#
    Shell Script
    Grafos – 2ª Parte
    Abstracção de SGDBs em PHP – AdoDB
    Programação Saudável
    Faça o seu media center com o GeexBox

Até Março!

Oração dos Programadores

Oração do programador:

Sistema Operacional que estais na memória,
Compilado seja o vosso programa,
Venha à tela os vossos comandos,
Seja executada a nossa rotina,
Assim na memória como na impressora.

Acerto nosso de cada dia, rodai hoje
Informai os nossos erros,
Assim como nós informamos o que está corrigido,
Não nos deixai entrar em looping,
Mas livrai-nos do Dump,
Amém.

Modificadores de Acesso em Java

Modificadores de Acesso

Modificadores de Acesso controlam a forma como os membros de uma classe são visíveis por outras classes e /ou instâncias de outras classes.

Um membro de uma classe pode ter um ou nenhum modificador de acesso na sua declaração, quando não especificamos um dos três modificadores de acesso dizemos que o membro tem acesso friendly.

  • private
  • O modificador de acesso private e o mais restritivo de todos, variáveis, métodos e construtores com esse modificador são visíveis somente dentro da definição da própria classe, com acesso directo ou através de uma instância da mesma classe.

    O modificador private pode ser usado em variáveis, métodos e construtores. Em classes, seu uso é restrito a classes internas, ou seja, classes declaradas dentro de outras classes.

    Considere os códigos das Figuras 01 e 02:

     1. public class Pilha {
     2.
     3.     private int topo, capacidade, dados[];
     4.
     5.     public Pilha() {
     6.		topo = -1;
     7.		capacidade = 10;
     8.		dados = new int[capacidade];
     9.	    }
    10.
    11.	    public void empilhar(int i) {
    12.		if ( topo+1==capacidade )
    13.		    realocar(capacidade*2);
    14.		dados[++topo] = i;
    15.	    }
    16.
    17.	    public int desempilhar() {
    18.		return dados[topo--];
    19.	    }
    20.
    21.	    public void unir(Pilha p) {
    22.		realocar(capacidade + p.capacidade);
    23.		for (int i=0; i<=p.topo; i++)
    24.		    dados[i+p.topo+1] = p.dados[i];
    25.		topo += p.topo + 1;
    26.	    }
    27.
    28.	    private void realocar(int novaCapacidade) {
    29.		capacidade = novaCapacidade;
    30.		int temp[] = new int[capacidade];
    31.		for (int i=0; i<=topo; i++)
    32.		    temp[i] = dados[i];
    33.		dados = temp;
    34.	    }
    35.	}

    Figura 1: Código da Classe Pilha.java

    1.	public class TestarPilha {
    2.	    public static void main(String args[]) {
    3.		Pilha p1 = new Pilha();
    4.		Pilha p2 = new Pilha();
    5.
    6.		for (int i=0; i<10; i++) {
    7.		    p1.empilhar(i);
    8.		    p2.empilhar(i+10);
    9.		}
    10.		p1.unir(p2);
    11.		p1.realocar();
    		//erro de compilacao (acesso privado)
    12.		System.out.println(p2.topo);
    		//erro de compilacao (acesso privado)
    13.	    }
    14.	}

    Figura 2: Código da Classe TestarPilha.java

    Na linha 22 do código 01 vemos o acesso a uma variável privada através de uma instância da classe Pilha (p.capacidade), esse acesso é permitido já que quando declaramos que uma variável é privada estamos a dizer que essa variável é visível dentro da definição da própria classe, acedida directamente ou por intermédio de instâncias da mesma classe. Declarações semelhantes são usadas nas linhas 23, 24 e 25.

    Nas linhas 11 e 12 do código 02, tentamos aceder ao método privado realocar() e o atributo topo também privado, logo é gerado um erro de compilação, pois os elementos privados de uma classe apenas podem ser acedidos dentro da própria classe. Veja, por exemplo, o acesso aos mesmos elementos realocar() e topo no código 01 nas linhas 13 e 14 respectivamente, esses acessos não causam erros de compilação pois estão dentro da definição da classe Pilha na qual esses elementos são declarados.

    Imagine agora se incluirmos na classe Pilha o método main da classe TestarPilha, conforme podemos ver na Figura 03:

    1.	public class Pilha {
    
    //linhas 2 a 35 idem ao código 01
    
    36.	    public static void main(String args[]) {
    37.		Pilha p1 = new Pilha();
    38.		Pilha p2 = new Pilha();
    39.
    40.		for (int i=0; i<10; i++) {
    41.		    p1.empilhar(i);
    42.		    p2.empilhar(i+10);
    43.		}
    44.		p1.unir(p2);
    45.		p1.realocar();
    		//Nao ha erro de compilacao, estamos dentro da classe Pilha
    46.		System.out.println(p2.topo);
    		//Nao ha erro de compilacao, estamos dentro da classe Pilha
    47.	    }
    48.	}

    Figura 3: Outra versão para a Classe Pilha.java

    O programa vai compilar correctamente, pois o método realocar() e a variável topo estão a ser acedidas internamente na classe Pilha (lembre-se que o método main é um método da classe Pilha) diferente do exemplo anterior.

    Uma relação curiosa ocorre quando herdamos de uma classe que contêm elementos privados, veja da Figura 04, que herda da classe Pilha:

     1.	public class SubPilha extends Pilha {
     2.	    public Pilha(int t, int c) {
     3.		topo = t;	//erro de compilacao
     4.		capacidade = c;	//erro de compilacao
     5.	    }
     6.	}

    Figura 4: Código da Classe SubPilha.java

    Apesar da classe SubPilha conter os atributos topo e capacidade herdados de Pilha, o acesso a essas variáveis nas linhas 3 e 4 não é permitido já que foram declarados privados na classe Pilha.

  • “friendly”
  • O acesso friendly em Java decorre da não especificação de nenhum dos três modificadores de acesso (private, protected, public), na verdade não há nenhuma palavra chave que defina que um determinado elemento terá acesso friendly. O acesso friendly pode ser aplicado a classes, métodos, variáveis e construtores. Outros nomes também usados para designar esse tipo de acesso são: “package” e “default”.

    O efeito de aplicarmos o acesso friendly a um elemento (ou seja, não aplicar nenhum dos três modificadores) e que elementos com esse tipo de acesso podem somente ser acedidos por classes do mesmo pacote.

    1.	class Friendly {
    2.	   int variavelFriendly;
    3.
    4.	   void metodoFriendly () {
    5.	       System.out.println(variavelFriendly);
    6.	   }
    7.	}

    Figura 5: Código da Classe Friendly.java

    No código da Figura 05 podemos ver a definição de uma classe, um método e uma variável com acesso friendly, todos esses elementos são acessíveis de qualquer classe do mesmo pacote, ou seja, qualquer classe que está no mesmo directório.

    É importante lembrar que a não especificação do pacote de uma classe resulta na incorporação dessa classe ao pacote default, portanto, todas as classes onde não é especificado o seu pacote e que contêm elementos com o acesso friendly, tais elementos são visíveis por todas as outras classes que também não foram especificados pacotes, e isso em grande parte das vezes não é o que desejamos.

  • protected
  • O modificador de acesso protected define que variáveis, métodos e construtores com esse modificador podem somente ser acedidos por classes no mesmo pacote ou subclasses da classe onde o elemento foi definido, é importante notar que para os elementos serem acedidos na subclasse não é preciso estar no mesmo pacote da classe pai. O modificador protected pode ser aplicado somente em variáveis, métodos e construtores, o seu uso em classes não é permitido.

    Considere os códigos da Figuras 06, 07 e 08:

    1.	package banco;
    2.
    3.	public class Conta {
    4.
    5.	    public Conta() { }
    6.
    7.	    protected float saldo;
    8.
    9.	    protected void saque(float s) {
    10.	        saldo -= s;
    11.	    }
    12.	}

    Figura 06: Código da Classe Conta.java

    1.	public class Poupanca extends banco.Conta {
    2.	    public void reajuste(float juros) {
    3.	        saldo *= juros;
    4.	    }
    5.	}

    Figura 07: Código da Classe Poupanca.java

    1.	package banco;
    2.
    3.	public class Transferencia {
    4.	    public void transferir(Conta c1, Conta c2, float valor) {
    5.	        c1.saque(valor);
    6.		  c2.saldo += valor;
    7.	    }
    8.	}

    Figura 08: Código da Classe Poupanca.java

    Como a variável saldo é declarada como protected (linha 7 do código 06) o acesso a essa variável na linha 3 do código 07 não causa erro, pois a classe Poupanca é uma subclasse de Conta. Nas linhas 5 e 6 do código 08 podemos ver a outra forma de acesso de membros declarados como protected, apesar da classe Transferencia não ser subclasse de Conta, esta pode aceder a elementos declarados protected, pois pertence ao mesmo pacote de Conta.

    Caso eliminássemos a linha 1 do código 08 o compilador apresentaria um erro informando que não foi possível determinar a variável saldo e o método saque.

  • public
  • O mais abrangente de todos os tipos de acesso, o modificador public declara que elementos com esse modificador são acessíveis de qualquer classe Java. Este modificador é aplicável a variáveis, métodos, construtores e classes.

    Os próximos modificadores que vamos ver não podem ser usado em construtores, para esse efeito apenas podem ser usado os modificares apresentados acima.

    Outros Modificadores

  • final
  • O modificador final pode ser aplicado a variáveis, métodos e classes. O comportamento descrito pelo operador final varia de elemento para elemento, mas tem um conceito em comum, o conceito de imutabilidade, isto é, elementos final não podem ser mudados.

    No caso de uma classe, quando dizemos que está é final, dizemos que ela não pode ser herdada, considere a definição da classe Imutavel no código 10.

    public final class Imutavel {}

    Figura 10: Código da Classe Imutavel.java

    Qualquer tentativa de herança a partir da classe Imutavel irá causar um erro de compilação, como exemplo tente compilar o código 11.

    public class Impossivel extends Imutavel {}	//erro de compilação

    Figura 11: Código da Classe Impossível.java

    O erro devolvido pelo compilador é o seguinte: “cannot inherit from final Imutavel”.

    Há pelo menos dois bons motivos para se declarar classes final, segurança e design. Em relação à segurança você pode querer declarar sua classe final de modo que uma subclasse não possa ser substituída dentro de um sistema, onde essa nova classe poderá ter códigos indesejáveis ao seu sistema. Um exemplo de uma classe final é a classe String, esta classe é vital para a normal operação da Máquina Virtual Java, já que todos os programas Java precisam dela, pois ela é declarada como parâmetro no método main(String args[]).

    O outro motivo é simplesmente uma questão de design, por exemplo, você pode desejar declarar classes que implementam seus algoritmos como classes final.

    Métodos final não podem ser redefinidos, ou seja, caso você herde de uma classe que contenha métodos com esse modificador, esses métodos não podem ser redefinidos na sua subclasse. Os mesmos objectivos que motivam o uso do modificador final em classes também motivam seu uso em métodos.

    1.	public class Transacao {
    2.	    public final boolean verificarSenha() {
    3.	        ...
    4.	    }
    5.	}

    Figura 12: Código da Classe Transacao.java

    1.	public class TransacaoPublica extends Transacao {
    2.	    public final boolean verificarSenha() {  //erro de compilacao
    3.	       ...
    4.	    }
    5.	}

    Figura 13: Código da Classe TransacaoPublica.java

    Na linha 2 do código 13 tentamos redefinir o método verificarSenha(), o compilador proíbe a redefinição e apresenta o seguinte erro: “verificarSenha() in TransacaoPublica cannot override verificarSenha() in Transacao; overridden method is final”.

    O último elemento a que o modificador final pode ser aplicado é a atributos. Atributos final não podem mudar de valor, ou seja, são constantes, a partir do momento que se define o seu valor inicial, esse será o seu valor durante todo o ciclo de vida do objecto.

    Quando trabalhamos com objectos devemos notar que apenas o valor do objecto, ou seja, sua referência, não pode ser mudada, atributos não final de uma instância podem ser mudados conforme podemos ver no código 14.

     1.	public class Carro {
     2.	   public final int numeroDeRodas = 4;
     3.	   public int numeroDePortas = 4;
     4.
     5.	   public static void main(String args[]) {
     6.	       Carro c1, c2;
     7.	       final Carro c3;
     8.
     9.	       c1 = new Carro();
    10.	       c1.numeroDeRodas = 5;  //erro de compilacao
    11.
    12.	       c2 = c3 = c1;
    13.	       c2.numeroDePortas = 2;
    14.	       c3.numeroDePortas = 2;
    15.
    16.	       c3 = c2;  //erro de compilacao
    17.	   }
    18.	}

    Figura 14: Código da Classe Carro.java

    Na linha 10 tentamos atribuir o valor 5 a variável numeroDeRodas, essa atribuição causa um erro de compilação já que estamos a tentar mudar o valor de uma variável final. Na linha 12, atribuímos a c3 a referência para c1, essa atribuição é correta já que é a primeira vez que atribuímos um valor a essa variável, já na linha 16 tentamos novamente mudar o seu valor, o que resulta em um erro de compilação. Na linha 14 mudamos o valor de um atributo de um objecto declarado como final, isso é correto já que não estamos a mudar o valor do objecto (referência), mas sim o valor de um atributo que não é final.

  • abstract
  • O modificador abstract pode ser aplicado somente a classes e métodos. Classes abstratas provem um modo de adiar a implementação de métodos para subclasses. Uma classe abstrata não pode ser instanciada, ou seja, não podemos chamar os seus construtores.

    Veja como exemplo o código 16. A classe Figura pode ser herdada para criar classes tais como, Retangulo, Triangulo, Quadrado, Circulo, entre outros, nesse caso a classe Figura teria atributos comuns entre esses objetos, mas não poderia-mos aplicar o operador new à classe Figura, ou seja, não poderia-mos criar uma instância dessa classe.

    1.	public abstract class Figura {
    2.	    public abstract void desenhar();
    3.
    4.	    public static void main(String args[]) {
    5.	        Figura f;
    6.	        f = new Figura();  //erro de compilacao
    7.	    }
    8.	}

    Figura 16: Código da Classe Carro.java

    Na linha 5 declaramos um objecto do tipo Figura, o qual não causa erro já que a restrição em relação a classes abstractas é que estas não podem ser instanciadas com vemos na linha 6, mas podem sim, ser declaradas.

    Métodos abstractos são métodos em que num determinado nível de programação ainda não sabemos como implementá-los, mas sabemos que eles serão necessários, veja, por exemplo, o método desenhar() na classe Figura. No momento de design da classe não é possível ainda conhecer como desenhar instâncias desses objectos, mas sabemos no momento que criamos uma subclasse, como por exemplo, para definir uma classe Circulo, nesta classe você já tem todas as informações necessárias para implementação desse método.

    Classes devem ser declaradas abstractas quando qualquer uma das três afirmações abaixo forem verdadeiras:

    a) a classe contêm métodos abstractos;

    b) a classe herda de classes abstractas e não define todos os seus métodos abstractos;

    c) a classe implementa um interface, mas não declara todos os seus métodos.

    Estas são condições em que a classe obrigatoriamente deve ser declarada como abstracta, mas uma classe pode não cair em nenhum das três afirmações acima e ainda ser declarada como abstracta.

    De uma forma geral uma classe deve ser declarada abstracta quando sua definição está incompleta.

  • static
  • Este modificador pode ser aplicado a variáveis, métodos e a uma porção de código que não está dentro de nenhum método, geralmente referenciado como bloco estático.

    A ideia geral sobre o modificador static é que elementos com esse modificador estão associados com a classe e não com instâncias dessa classe.

    Uma variável estática é compartilhada por todas as instâncias de uma classe, ou seja, ao invés de cada instância da classe ter uma cópia dessa variável ela é uma única variável compartilhada por todos as instâncias. Para a existência de uma variável estática não é preciso nem mesmo a criação de uma instância da classe que contenha a variável, é necessário somente que a classe seja carregada na Máquina Virtual Java, já que está é criada e inicializada no momento de carga da classe.

    Em relação a métodos as mesmas explicações são verdadeiras, ou seja, métodos podem ser chamados mesmo sem nenhuma instância da classe ter sido construída. Um bom exemplo de métodos estáticos existe em todas as aplicações Java, o método main() é invocado sem a existência de nenhuma instância.

    Métodos e variáveis podem ser referenciados além da forma padrão (através do nome do objeto) através do nome da classe. Embora as duas formas sejam corretas e trabalham exactamente da mesma forma a primeira pode tornar-se confusa quando referenciando métodos e variáveis estáticas, levando o programador a pensar que este método ou variável é não estático. Por esse motivo e conveniente sempre referenciar variáveis estáticas através do nome da classe para evitar confusões.

    É importante dizer que métodos estáticos podem apenas aceder a variáveis também estáticas, ou seja, é proibido o uso de variáveis não estáticas dentro de blocos estáticos, com excepção de variáveis criadas dentro do próprio bloco é claro. Essa restrição deve-se ao fato de que é possível fazer uma chamada a um método estático mesmo sem haver nenhuma instância dessa classe, ou seja, a provável variável a ser referenciada dentro do método pode nem mesmo ter sido criada ainda. Outro motivo dessa restrição é caso haja várias instâncias criadas, qual é a instância que contêm a variável na qual estamos a referenciar?

    Outra importante característica é que não podemos usar a palavra chave this com métodos e variáveis estáticas, já que esta é uma referência para o objecto que contém o método o qual não é verdadeiro para métodos e variáveis estáticas já que estes não pertencem a um objecto em particular, mas sim à classe.

    Um outro local onde podemos usar o modificador static são nos desconhecidos blocos de código estáticos de Java. Veja o código da Figura 19.

    1.	public class BlocoEstatico {
    2.	  static int i = 4;
    3.	  
    4.	  static {
    5.	    System.out.println("Carregando BlocoEstatico\r\n valor de i: " + i);
    6.	  }
    7.	
    8.	  public static void main(String args[]) {
    9.	    System.out.println("metodo main");
    10.	  }
    11.	}

    Figura 19: Código da Classe Carro.java

  • native
  • Algumas vezes é necessário executar código não Java em aplicações. Quando desejamos aceder a chamadas do Sistema Operativo, criar interfaces com dispositivos de hardware, reutilizar código não Java, implementar código onde o tempo é um parâmetro critico, etc. Esse modificador é usado somente em métodos e sua definição está fora da Maquina Virtual Java, em bibliotecas C e C++.

    A declaração de um método nativo é bastante semelhante a declaração de métodos em interfaces, não existe a definição do método. A chamada a esses métodos é exactamente da mesma forma que métodos não nativos.

  • transient
  • É aplicado somente a variáveis. Quando uma variável é declarada transient ela não é guardada como parte do estado de persistência do objecto.

    Muitas vezes é necessário escrever dados para fora da Máquina Virtual Java, quando isso ocorre nenhum dos mecanismos de segurança da linguagem é válido e se existe informações que não devem ser escritas as variáveis que contem esses dados devem ser declaradas como modificador transient para que estes não sejam escritos para fora da Máquina Virtual Java.

  • synchronized
  • Esse modificador é usado para sincronizar o acesso a código em ambientes paralelos.

  • volatile
  • São aplicados somente a variáveis. Este modificador indica que variáveis podem ser modificadas assincronamente.

    Fonte : www.jeebrasil.com.br

    Adaptado por mim.