terça-feira, 22 de novembro de 2011

Instalação do OpenLDAP no Solaris 10 em Sparc

A instalação tem de ser realizada com o utilizador root.

1. Descarregar os seguintes pacotes

Localização dos pacotes: http://www.sunfreeware.com/indexsparc10.html
  • openldap-2.4.26
  • openssl-1.0.0e
  • db-4.7.25.NC
  • gcc-3.4.6
  • libgcc-3.4.6
  • sasl-2.1.25
  • libiconv-1.14
  • libtool-2.4

2. Instalar os pacotes
  • gunzip gcc-3.4.6-sol10-sparc-local.gz
  • gunzip libgcc-3.4.6-sol10-sparc-local.gz
  • gunzip sasl-2.1.25-sol10-sparc-local.gz
  • gunzip libiconv-1.14-sol10-sparc-local.gz
  • gunzip libtool-2.4-sol10-sparc-local.gz
  • gunzip db-4.7.25.NC-sol10-sparc-local.gz
  • gunzip openssl-1.0.0e-sol10-sparc-local.gz
  • gunzip openldap-2.4.26-sol10-sparc-local.gz
  • pkgadd -d gcc-3.4.6-sol10-sparc-local
  • pkgadd -d libgcc-3.4.6-sol10-sparc-local
  • pkgadd -d sasl-2.1.25-sol10-sparc-local
  • pkgadd -d libiconv-1.14-sol10-sparc-local
  • pkgadd -d libtool-2.4-sol10-sparc-local
  • pkgadd -d openssl-1.0.0e-sol10-sparc-local
  • pkgadd -d db-4.7.25.NC-sol10-sparc-local
  • pkgadd -d openldap-2.4.26-sol10-sparc-local


2.1

crle -c /var/ld/ld.conf -l /lib:/usr/lib -s /lib/secure:/usr/lib/secure:/usr/lib/mps:/usr/lib/mps64


3. Preparação do ambiente

export LD_NOVERSION=yes
export PATH=$PATH:/usr/local/sbin


4. Criação do grupo e utilizador LDAP

groupadd –g 55 ldap
useradd -u 55 -g 55 -d /export/home/ldap -s /bin/false ldap

mkdir /export/home/ldap
chown -R ldap:ldap /export/home/ldap/



4.1 Adicionar ldap ao grupo deamon


vi /etc/group

daemon::12:root,ldap


5. Preparação da pasta do OpenLDAP


mkdir –p /usr/local/var/openldap-data
chmod 700 /usr/local/var/openldap-data
chown –R ldap:daemon /usr/local/var/openldap-data
chown –R ldap:daemon /usr/local/etc/openldap

chown -R root:daemon /usr/local/var/run/
chmod -R 775 /usr/local/var/run/



6. Configuração

6.1 Editar o ficheiro slapd.conf

6.1.1 Adicionar

include        /usr/local/etc/openldap/schema/cosine.schema
include        /usr/local/etc/openldap/schema/inetorgperson.schema



6.1.2 Alterar

suffix          "dc=pt2,dc=pt"
rootdn          "cn=Manager,dc=pt2,dc=pt"
rootpw          passwordDoManager


6.1.3 Adicionar

# Indices to maintain
index default pres,eq
index   objectClass     eq
index uid,cn,sn



6.2

cd /usr/local/etc/openldap/

cp /usr/local/etc/openldap/DB_CONFIG.example /usr/local/var/openldap-data/DB_CONFIG


7. Iniciar o OpenLDAP

cd /usr/local/libexec/
./slapd 

Caso seja necessário efectuar debug para resolver eventuais problemas no arranque:

./slapd -d 100


8. Verificar se está funcional

ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts

9. Criar a raíz


9.1) base.ldif

dn: dc=pt2,dc=pt
dc: pt2
objectClass: domain


9.2) ldapadd   -D "cn=Manager,dc=pt2,dc=pt" -w password -f base.ldif



Referência

http://oskb.wordpress.com/2009/02/23/install%C2%A0and%C2%A0configure%C2%A0openldap%C2%A0server%C2%A0solaris10/

quarta-feira, 9 de novembro de 2011

Criar um CA e assinar certificados

Por vezes é necessário criar uma CA (CertificateAuthority) e assinar certificados com a CA. Obviamente que quer a CA quer os certificados não devem ser usados num ambiente de produção. Nesse caso usar uma das CAs oficiais.

Passos resumidos:
  1. Criar a chave e o certificado da CA
  2. Criar a chave e o pedido de certificado para o servidor (usar o mesmo método para criar vários)
  3. Assinar o pedido de certificado para o servidor com a CA criada

Passo 1:

openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

Passo 2:

openssl genrsa -des3 -out server.key 4096
openssl req -new -key server.key -out server.csr


Passo 3:

openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt


Aquando da criação do certificado da CA e do pedido de certificado de servidor ter em atenção que o Common Name tem de ser diferente. Caso contrário poderão surgir problemas inesperados quando se usam os certificados.

No exemplo acima os certificados têm a validade de um ano.

O número de série deve ser diferente se o mesmo certificado for regerado, para evitar problemas nos clientes que já tenham o certificado em cache.


Referências:
http://www.tc.umn.edu/~brams006/selfsign.html

Alterar cor dos links já visitados no Google

Ultimamente a Google anda a alterar a pesquisa e o modo como a informação é apresentada. Uma das piores coisas que eles fizeram foi não indicar que links já visitamos como faziam antigamente. Houve uma altura que indicavam quando foi a última vez que o link foi visitado dando o dia e a hora, e antes disso simplesmente um link já visitado tinha uma cor diferente.

Ora bem, para indicar com uma cor diferente os links já visitados, se tiverem a usar o Firefox, é só instalar o plug-in Stylish e adicionar a seguinte regra:

(depois de instalar é necessário fazer restart ao Firefox)

@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document domain("www.google.com") {
a:visited {color:#0F0!important;}
}

Para adicionar a regra fazer:

Carregar no botão do Stylish (se não aparecer ir ao menu Firefox > Add-ons.
Escolher  Write new style -> Blank Style.
Dar um nome (por exemplo Google) e colar a regra acima. Salvar.
E pronto. Os links já visitados irão, neste caso, aparece a verde alface (0F0). Podem mudar a cor para outra.



quarta-feira, 2 de novembro de 2011

Activar SSL entre Apache e Weblogic

A activação de SSL entre o Apache (a actuar como Reverse Proxy) e o Weblogic é relativamente simples.
A configuração que irá ser demonstrada aqui não usa o Plug-in Weblogic existente para Apache. Antes ir-se-á usar apenas e só directivas Apache.

Existem alguns pressupostos na configuração seguinte:
  1. O Apache já está configurado com SSL
  2. O Weblogic já está preparado para SSL (certificados criados, keystores configuradas)
Uma configuração possível é então a seguinte:
  1. Activar a opção SSL Enabled no Weblogic. Indicar o porto de escuta de SSL ([Domínio] -> Environment -> Servers -> [Servidor] -> Configuration -> General)
    1. SSL Listen Port Enabled
    2. SSL Listen Port
  2. Adicionar o certificado do Apache à keystore do Weblogic. Efectuar este passo com a ferramenta keytool, por exemplo.
  3. No Apache na secção <VirtualHost *:443> adicionar a instrução: SSLProxyEngine on
  4. Se no Apache se tiver configurado o mod_proxy, um exemplo de configuração para Reverse Proxy é:
<Location / >
  ProxyPass https://weblogic.host.com:7002/futebol
  ProxyPassReverse https://weblogic.host.com:7002/futebol
</Location / >

quarta-feira, 19 de outubro de 2011

Redireccionar ambiente gráfico através de SSH de uma segunda máquina

Acedendo remotamente a máquinas Solaris é necessário por vezes reencaminhar a parte gráfica para a máquina onde estamos (pois é o único monitor a que temos acesso). Usando o Xming e o PUTTY isto é relativamente fácil.

Contudo por vezes temos outra necessidade. Entrando numa máquina remota, usamos essa para aceder a outra. Como fazer para obter o ambiente gráfico desta segunda máquina?

É simples. Tendo tudo montado para receber os gráficos da primeira máquina basta iniciar a sessão na segunda máquina do seguinte modo:

ssh -X user@maquina.xpto.pt

Fontes gratuitas

http://www.azfonts.net/

terça-feira, 18 de outubro de 2011

Configuração two-way SSL no Apache

Para se obter uma configuração two-way SSL (comunicação SSL duas vias entre Cliente e Servidor) no Apache com certificados auto-assinados (self-signed) efectuar os passos seguintes (é uma das maneiras. eventualmente há melhores maneiras):
  • Parte-se do principio que o Apache já está configurado para SSL
  • Em cima desta configuração:
    • No ficheiro ssl.conf
      • Descomentar a linha
        SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
      • Dentro da tag <virtualhost> ...,</virtualhost> incluir uma linha do género
        Include /etc/apache2/vhost.d/*.conf
        que é o local ou o ficheiro que contém as configurações SSL mais específicas que irão ser efectuada
    • Supondo, por exemplo, que se quer proteger uma location com two-way SSL
      • <location />
        SSLVerifyClient optional
        SSLUserName SSL_CLIENT_S_DN_CN

        SSLRequire %{SSL_CLIENT_S_DN_CN} eq "Teste"

        </location>
    • Se não existir criar o ficheiro /etc/apache2/ssl.crt/ca-bundle.crt
    • Tendo o certificado cliente basta efectuar: cat client.crt > ca-bundle.crt
    • Restart do apache e tem-se comunicação 2 way SSL

Na location, a linha SSLRequire %{SSL_CLIENT_S_DN_CN} eq "Teste" indica que só os certificados de cliente que tenham o CN=Teste é que serão aceites. É possível efectuar outras configurações. Para mais detalhes ver: httpd.apache.org/docs/2.2/mod/mod_ssl.htm

Configuração two-way SSL no SoapUi

Para configurar two-way SSL (SSL duas vias) no SoapUI, é necessário antes de mais ter a versão 4 ou superior. Existem problemas com a versão 3.6.1 por isso o melhor mesmo é actualizar para a versão mais recente.

A configuração two-way SSL implica que existam dois certificados, um de Cliente e um de Servidor.

Para o cliente basta criar um ficheiro p12 com a chave publica e  privada, e de lá exportar o certificado de cliente para adicionar ao servidor.

Caso o certificado do servidor seja auto-assinado, é necessário adicionar esse mesmo certificado ao ficheiro p12 do cliente.

No SoapUi:

File -> Preferences

SSL Settings

Na KeyStore indicar o ficheiro p12 criado para o cliente.
Na KeyStore Password indicar a password para o ficheiro p12.


Criar o ficheiro de cliente p12 e respectivo certificado

Instalar, por exemplo, o programa KeyStore Explorer.

  1. Create a new KeyStore
    1. JKS
  2. Tools
    1. Generate Key Pair
    2. Ok
    3. Carregar no botão "Edit Name"
      1. Preencher os campos (pelo menos o CN deverá ser preenchido)
      2. Escolher um alias
      3. OK
      4. Escolher e confirmar a password privada
      5. Ok
      6. Ok
  3. Com o botão da direita carregar em cima da nova chave (vai-se exportar o certificado a importar no servidor)
    1. Escolher formato e nome de ficheiro
    2. Export
    3. Ok
  4. Salvar a keystore
    1. File -> Save
    2. Introduzir a password para a keystore
    3. Ok


quinta-feira, 13 de outubro de 2011

Axis2 e Weblogic

Devido a problemas de compatibilidade, (um WSDL em RPC) foi necessário criar um webservice em Axis2 e fazer deploy do mesmo em Weblogic 11g.

Para simplificar, usou-se o axis2.war para ser o container dos serviços.

Para a coisa funcionar em Weblogic 11g, o war do Axis2 tem de ser deployed exploded.
Para fazer isto basta, por exemplo, descomprimir o war para a directoria .../AdminServer/upload/axis2.

Depois instalar da maneira normal escolhendo a directoria axis2.

E tudo irá funcionar.

quarta-feira, 12 de outubro de 2011

Colocar Liferay em HTTPS com Apache Reverse Proxy

Tendo o Liferay instalado (versão 6.0.6) numa máquina e o Apache HTTP Server (versão 2.0) noutra máquina diferente a servir de Reverse Proxy, são necessários alguns passos para disponibilizar o Liferay em HTTPS.

No restante texto explica-se como fazer esta configuração em Solaris 10.

1.  Criar um certificado auto-assinado

Instruções detalhadas em http://www.akadia.com/services/ssh_test_certificate.html

1.1 Gerar uma RSA Private Key


Numa shell Solaris:
# /usr/sfw/bin/openssl

Introduzir o comando:
genrsa -des3 -out liferay.key 2048

Escolher uma pass phrase.

Irá gerar o ficheiro liferay.key.

1.2 Gerar um Certificate Signing Request

Numa shell Solaris:
#/usr/sfw/bin/openssl

Introduzir o comando:
req -new -key liferay.key -out liferay.csr

Introduzir a pass phrase escolhida para a chave privada (RSA Private Key).

Introduzir informação nos campos seguintes (exemplo):

Country Name (2 letter code) [US]:PT
State or Province Name (full name) [Some-State]:Lisboa
Locality Name (eg, city) []:Lisboa
Organization Name (eg, company) [Unconfigured OpenSSL Installation]:CFB
Organizational Unit Name (eg, section) []:FUTEBOL
Common Name (eg, YOUR name) []:LIFERAY
Email Address []:
--
A challenge password []:
An optional company name []:

Irá gerar o ficheiro liferay.csr.

1.3 Remoção da pass phrase da chave

Criar uma cópia da chave liferay.key e renomeá-la para liferay.key.futebol

De seguida executar numa shell Solaris:
#/usr/sfw/bin/openssl

Introduzir o comando:
rsa -in liferay.key.futebol -out liferay.key

Introduzir a pass phrase escolhida para a chave privada (RSA Private Key).

1.4 Gerar um certificado auto-assinado

Numa shell Solaris:
#/usr/sfw/bin/openssl


Introduzir o comando:
x509 -req -days 3650 -in liferay.csr -signkey  liferay.key -out liferay.crt

Irá gerar o ficheiro liferay.crt.


2. Copiar a chave e o certificado para o Apache


De seguida executar numa shell Solaris:
# mkdir /etc/apache2/ssl.crt
# mkdir /etc/apache2/ssl.key

# cp liferay.crt /etc/apache2/ssl.crt/ssl.crt
# cp liferay.key /etc/apache2/ssl.key/ssl.key


3. Configurar SSL no Apache








No ficheiro /etc/apache2/ssl.conf


Comentar:

#SSLRandomSeed startup builtin
#SSLRandomSeed connect builtin


Descomentar:

SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512


Alterar
SSLCertificateFile /etc/apache2/ssl.crt/server.crt

para

SSLCertificateFile /etc/apache2/ssl.crt/ssl.crt


Alterar
SSLCertificateKeyFile /etc/apache2/ssl.key/server.key

para

SSLCertificateKeyFile /usr/local/apache/conf/ssl.key/ssl.key


Alterar

<VirtualHost _default_:443>


para

<VirtualHost *:443>

4. Activar o SSL no Solaris
Verificar se o SSL está activo



Nnuma shell Solaris:
# svcprop -p httpd/ssl svc:network/http:apache2

Se false:

# svccfg -s http:apache2 setprop httpd/ssl=true
# svcadm refresh http:apache2
# svcprop -p httpd/ssl svc:network/http:apache2

Deverá agora dar true.

 5. Restart Apache

Testar

https://apache.reverse.proxy


Onde apache.reverse.proxy é o endereço da máquina onde está instalado o Apache.



6. Configuração do Reverse Proxy no Apache


No ficheiro http.conf ou noutro que seja incluído:

<Location / >
  ProxyPass http://liferay.location:8080/
  ProxyPassReverse http://
liferay.location:8080/
<Location />

Onde liferay.location é o endereço da máquina onde está instalado o Liferay.

Restart ao Apache


7. Configuração do Reverse Proxy no Liferay

Editar o ficheiro  ~/liferay-portal-6.0.6/tomcat-6.0.29/webapps/ROOT/WEB-INF/classes/portal-ext.properties


Acrescentar:

web.server.http.port=80
web.server.host=
apache.reverse.proxy


web.server.https.port=443
web.server.protocol=https

redirect.url.security.mode=ip
redirect.url.domains.allowed=
redirect.url.ips.allowed=127.0.0.1,LIFERAY_IP_MACHINE,APACHE_REVERSE_PROXY_IP_MACHINE
# Para não criar o esquema de demonstração
schema.run.enabled=true
schema.run.minimal=false

Restart ao Liferay.

Testar.
http://apache.reverse.proxy

Deverá abrir a página do Liferay.


8. Configuração do Reverse Proxy com SSL no Apache


<Location / >

  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}


  ProxyPass http://liferay.location:8080/
  ProxyPassReverse http://
liferay.location:8080/

<Location />

Restart ao Apache.


Testar.
https://apache.reverse.proxy

Deverá aparecer a página do Liferay em HTTPS.


Escrevendo http://apache.reverse.proxy dever-se-á ser redireccionado para https://apache.reverse.proxy

sexta-feira, 7 de outubro de 2011

Importação de WSDLs no Oracle Service Bus

A melhor maneira de evitar problemas na importação de WSDLs (problemas do género classes duplicadas, etc) no OSB é colocar os WSDLs e respectivos XSDs num só zip e usar a ferramenta de Bulk -> Zipped Resources.

Oracle Service Bus - Gerando correctamente WSDLs

Quando o OSB (versão 11.1.1.5.0) não está acessível directamente aos clientes (por detrás de um Reverse Proxy por exemplo), os WSDLs não são gerados correctamente, ficando o endpoint com o hostname da máquina onde está deployed o OSB.

Isto é uma situação que se deve evitar, pois está-se a expor nomes internos que não devem ser conhecidos fora.

Esta situação só ocorre se o OSB não estiver em Cluster.

Para corrigir o problema efectuar os seguintes passos:
  1. Criar um cluster
  2. Adicionar o servidor do OSB ao cluster
  3. No cluster, na tab HTTP configurar os campos Frontend Host e Frontend HTTP Port para os valores do Reverse Proxy por exemplo
  4. Parar o AdminServer e o servidor do OSB
  5. Editar o ficheiro config.xml conforme indicado a seguir
  6. Restart do Admin Server
  7. Restart do servidor OSB
  8. Verificar a geração de WSDLs
Pode-se também recriar o domínio do OSB, configurando o mesmo em cluster, e assim não haverá edição manual de ficheiros.

Agora a geração já será feita como deve ser.


Edição manual do ficheiro config.xml

Esta edição apenas é necessária se não se quiser recriar o domínio de raiz.
  • Substituir o nome do servidor do OSB pelo nome do cluster excepto nos casos seguintes:
    • <server>
      • <name>.....
      • <jta-migratable-target><user-preferred-server>....
      • <server-diagnostic-config><name>....
      • <virtual-machine-name>NOME_DO_DOMINIO_.....</virtual-machine-name>
    • </server>
    • Todos os valores nos vários <jms-server>
    • Todos os valores em <migratable-target>
    • Todos os valores nos vários <file-store>
    • Todos os valores nos vários <jms-system-resource>
    • Todos os valores nos vários <saf-agent>

terça-feira, 4 de outubro de 2011

Teclas Home, End, etc a funcionar na linha de comandos (bash) em Solaris

As teclas home, end em Solaris 10 na shell bash escrevem caracteres esquisitos (~) em fez de executarem a sua função espectável.

Para corrigir este problema executar os passos seguintes:

  1. Editar o ficheiro .profile
  2. Adicionar a linha: export INPUTRC=inputrc
  3. Salvar e fechar o ficheiro
  4. Criar o ficheiro inputrc
  5. Adicionar o conteúdo:



    set meta-flag on
    set input-meta on
    set convert-meta off
    set output-meta on
    
    "\e[1~": beginning-of-line
    "\e[4~": end-of-line
    "\e[5~": beginning-of-history
    "\e[6~": end-of-history
    "\e[3~": delete-char
    "\e[2~": quoted-insert
    "\e[5C": forward-word
    "\e[5D": backward-word
    




  6. Salvar e fechar o ficheiro
  7. Fazer logout e login
Solução encontrada em: http://www.cyberciti.biz/tips/freebsd-how-to-customized-home-del-insert-keys-for-bash-shell.html

Colocar as teclas de cursor a funcionar no vi em Solaris

Em Solaris 10, o vi vem com uma funcionalidade muito irritante que é a de não ter a funcionar nem o backspace nem o delete nem as teclas de cursor no modo de edição. As teclas de cursor por exemplo trocam minúsculas por maiúsculas e vice-versa.

A solução do problema não é difícil, bastando criar um ficheiro e colocar alguns mapeamentos que solucionam o problema.

Assim, criar na home do utilizador o ficheiro .exrc.

Dentro desse ficheiro colocar os mapeamentos pretendidos.
O conteúdo tem de ser escrito à mão e NÃO PODE SER COPIADO. Caso contrário não irá funcionar.
Os mapeamentos não podem ter espaços no final, nem pode haver linhas em branco no ficheiro.

Exemplo de ficheiro .exrc (NÃO COPIAR. Escrever no ficheiro o conteúdo, conforme instruções mais abaixo):


:map! ^[OA ^[ka
:map! ^[OB ^[ja
:map! ^[OC ^[la
:map! ^[OD ^[ha
:map! ^[[3~ ^[xa
:map! ^? ^[Xa

Para escrever o conteúdo usar os seguintes comandos (são comandos de controlo, por isso não podem ser copiados):

^[OA = CTRL-V + Seta-para-cima
^[ka = CTRL-V + ESCAPE + k + a

^[OB = CTRL-V + Seta-para-baixo
^[ja = CTRL-V + ESCAPE + j + a

^[OC = CTRL-V + Seta-para-direita
^[la = CTRL-V + ESCAPE + l + a

 ^[OD = CTRL-V + Seta-para-esquerda
^[ha = CTRL-V + ESCAPE + h + a

^[[3~ = CTRL-V + DELETE
 ^[xa = CTRL-V + ESCAPE + x + a

^H = CTRL-V + BACKSPACE
 ^[Xa = CTRL-V + ESCAPE + x + a


Explicação dos mapeamentos:

:map! ^[OA ^[ka -> Coloca a seta para cima a funcionar em modo de edição
:map! ^[OB ^[ja-> Coloca a seta para baixo a funcionar em modo de edição
:map! ^[OC ^[la-> Coloca a seta para a direita a funcionar em modo de edição
:map! ^[OD ^[ha-> Coloca a seta para a esquerda a funcionar em modo de edição
:map! ^[[3~ ^[xa-> Coloca o delete a funcionar em modo de edição, apagando o carácter seleccionado pelo cursor
:map! ^? ^[Xa-> Coloca o backspace a funcionar em modo de edição, apagando o carácter à esquerda do cursor


Esta foi uma configuração que escolhi.
Pode-se adaptar esta configuração usando outros comandos do vi, e acrescentando mais mapeamentos se necessário.

Documentação vi: http://hea-www.harvard.edu/~fine/Tech/vi.html

Onde encontrei a solução: http://www.jonathanlaliberte.com/2009/12/01/fix-arrow-keys-in-vi-on-solaris/comment-page-1/#comment-3548

segunda-feira, 3 de outubro de 2011

./dbstart: test: argument expected

Ao executar o comando dbstart para levantar uma base de dados Oracle se ocorrer o erro:

dbstart: test: argument expected

então, por incrível que pareça, o problema está no início do script.

Substiruir

#!/bin/sh

por:

#!/bin/bash


Fazer o mesmo no dbshut.

Pós-instalação de Base de Dados Oracle 11g em Solaris

Depois de instalada a base de dados em Solaris, é necessário configurar o ambiente para se poder aceder à base de dados em condições.

Assim como utilizador que vai correr a base de dados (neste caso oracle):

Editar o ficheiro .profile (caso se use bash)

ORACLE_SID=SID_BASE_DADOS
export ORACLE_SID
ORACLE_HOME=RAIZ_DO_PRODUTO(por defeito: /u01/app/oracle/product/11.2.0/dbhome_1)
export ORACLE_HOME

ORAENV_ASK=NO
export ORAENV_ASK

export PATH=$PATH:/usr/local/bin
. /usr/local/bin/oraenv



Sair e voltar a entrar para assumir as alterações no perfil.

Executar:

sqlplus / AS SYSDBA
@?/rdbms/admin/utlrp.sql


Fora do SQLPLUS, na linha de comandos executar:

$ORACLE_HOME/bin/genclntst


Editar o ficheiro /var/opt/oracle/oratab

Verificar se o conteúdo termina com Y. Se terminar com N então a base de dados não arranca automaticamente.


Ex:
oracle_sid:/u01/app/oracle/product/11.2.0/dbhome_1:Y



Para a base de dados arrancar e terminar automaticamente a cada reboot do servidor, criar como root o ficheiro /etc/init.d/dbora com o conteúdo seguinte:

#! /bin/sh  -x
#
# Change the value of ORACLE_HOME to specify the correct Oracle home
# directory for your installation.

ORACLE_HOME=/u01/app/oracle/product/11.1.0/db_1
#
# Change the value of ORACLE to the login name of the
# oracle owner at your site.
#
ORACLE=oracle

PATH=${PATH}:$ORACLE_HOME/bin
HOST=`hostname`
PLATFORM=`uname`
export ORACLE_HOME PATH

case $1 in
'start')
         su - oracle -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME" &
        ;;
'stop')
         su - oracle -c "$ORACLE_HOME/bin/dbshut $ORACLE_HOME" &
        ;;
*)
        echo "usage: $0 {start|stop}"
        exit
        ;;
esac
#
exit
 
 
Dar as seguintes permissões ao ficheiro dbora 
chgrp GRUPO_ORACLE dbora
chmod 750 dbora

Depois de criado o ficheiro executar:

ln -s /etc/init.d/dbora /etc/rc0.d/K01dbora
ln -s /etc/init.d/dbora /etc/rc3.d/S99dbora

Mais detalhes aqui e aqui.

Mudar prompt de root em Solaris 10

Ao contrario do que muitos rumores dizem, já não há problema em mudar a prompt de root em Solaris 10. Antes desta versão a shell que vinha por defeito não era linkada, o que trazia (segundo dizem) segurança acrescida em caso de problemas. Contudo a partir da versão 10 a shell por defeito já é linkada e por isso é indiferente se se muda a shell ou não.

Então os passos para mudar de shell de root:
  1.  /usr/ucb/vipw -> Alterar a shell para, por exemplo: /bin/bash
  2. Sair e voltar a entrar da sessão
  3. Editar o ficheiro .profile e acrescentar uma linha para ter a prompt como se quer. Exemplo: PS1="[\H \w] $ "

Configuração da prompt de uma shell Bash

Para alterar a prompt de uma shell Bash, basta configurar a variável PS1 com um 
formato, usando um ou mais caracteres especiais:
 
              \a     an ASCII bell character (07)
              \d     the date  in  "Weekday  Month  Date"  format
                     (e.g., "Tue May 26")
              \e     an ASCII escape character (033)
              \h     the hostname up to the first `.'
              \H     the hostname
              \j     the  number of jobs currently managed by the
                     shell
              \l     the basename of the shell's terminal  device
                     name
              \n     newline
              \r     carriage return
              \s     the  name  of  the shell, the basename of $0
                     (the portion following the final slash)
              \t     the current time in 24-hour HH:MM:SS format
              \T     the current time in 12-hour HH:MM:SS format
              \@     the current time in 12-hour am/pm format
              \u     the username of the current user
              \v     the version of bash (e.g., 2.00)
              \V     the release of bash,  version  +  patchlevel
                     (e.g., 2.00.0)
              \w     the current working directory
              \W     the  basename  of the current working direc­
                     tory
              \!     the history number of this command
              \#     the command number of this command
              \$     if the effective UID is 0, a #, otherwise  a
                     $
              \nnn   the  character  corresponding  to  the octal
                     number nnn
              \\     a backslash
              \[     begin a sequence of non-printing characters,
                     which could be used to embed a terminal con­
                     trol sequence into the prompt
              \]     end a sequence of non-printing characters
 
Exemplo: PS1="[\H \w] $" 
 
 Mais detalhes em aqui.

quarta-feira, 28 de setembro de 2011

Criar um tunel para uma ligação VMWare Client (vSphere)

Com o putty, numa ligação com acesso à máquina destino criar um tunel com as seguintes caractrísticas:



Source port 127.0.0.2:443
Destination :443


Na ligação com o Cliente vSphere indicar:
127.0.0.2
user
password

Esta é a maneira mais fácil de criar um túnel para um servidor vSphere.

Referência: http://communities.vmware.com/message/1469203

quarta-feira, 21 de setembro de 2011

Problemas no SimpleDateFormat

O uso da classe SimpleDateFormat é muito frequente para parsar datas que estão em formato String e transformá-las para Date. É uma classe muito útil, e que resolve só por si toda uma série de problema de conversão de datas.

Contudo, quando se cria uma instância desta classe para fazer a formatação, há um campo desta mesma classe que por defeito vem a true. Este campo é a propriedade Lenient. Esta propriedade, quando a true permite à instância aplicar uma série de heurísticas na formatação e assim tentar efectuar o parse. A aplicação destas heurísticas pode, de vez em quando, indicar resultados incorrectos como no exemplo mais abaixo.

Usando a máscara "yyyy/MM/dd" no SimpleDateFormat e efectuando um parse a uma String no formato "dd/MM/yyyy", o SimpleDateFormat irá indicar que a data é válida, quando era expectável que desse uma excepção. Além de formatar a data, o SimpleDateFormat devolverá uma data completamente diferente da original (objecto Date).

Exemplo INVÁLIDO



        SimpleDateFormat dateFormat = new SimpleDateFormat(
        "yyyy/MM/dd");
     
        try {
            dateFormat.parse("12/12/1233");
        } catch (ParseException ex) {
            System.out.println("12/12/1233 Invalida");
        }
     
        try {
            dateFormat.parse("1212/12/12");
        } catch (ParseException ex) {
            System.out.println("1212/12/12 Invalida");
        }

Ao contrário do que seria de esperar o resultado é:

Thu Apr 16 00:00:00 GMT 16
Wed Dec 12 00:00:00 GMT 1212

Em primeiro lugar deveria ter ocorrido uma mensagem a dizer:



12/12/1233 Invalida

pois "12/12/1233" não está no formato esperado ("yyyy/MM/dd").

Em segundo lugar:

A data Thu Apr 16 00:00:00 GMT 16 nada tem a ver com "12/12/1233".





Para corrigir o problema, é necessário indicar ao SimpleDateFormat para não aplicar heurísticas. Isso é feito usando o método setLenient(false). Fazendo isto o resultado já será o expectável.

Exemplo VÁLIDO

        SimpleDateFormat dateFormat = new SimpleDateFormat(
        "yyyy/MM/dd");
     
        dateFormat.setLenient(false);
     
        try {
           System.out.println(dateFormat.parse("12/12/1233"));
        } catch (ParseException ex) {
            System.out.println("12/12/1233 Invalida");
        }
     
        try {
            System.out.println(dateFormat.parse("1212/12/12"));
        } catch (ParseException ex) {
            System.out.println("1212/12/12 Invalida");
        }

O resultado é:

12/12/1233 Invalida
Wed Dec 12 00:00:00 GMT 1212

Como esperado.

segunda-feira, 12 de setembro de 2011

Wii Puzzle Quest - "Resolvedor de Puzzles"

Se alguém tem o jogo Puzzle Quest para Wii (1ª versão do jogo de 2007) tem aqui disponível uma aplicação que permite resolver os puzzles.

quinta-feira, 8 de setembro de 2011

quinta-feira, 1 de setembro de 2011

Instalação da Base de Dados Oracle 11g em Solaris

Ao verificar os pré-requisitos de instalação, o instalador da base de dados poderá dizer que o patch 12486-15 (ou outro parecido) necessita de ser instalado. De acordo com a nota ID969497.1 este patch pode ser ignorado desde que não se use o pré-compilador Pro*C.

Solaris - "Cannot convert string "fixed" to type FontStruct"

Quando se tenta redireccionar o DISPLAY em Solaris para um computador remoto, podem ocorrer erros do género: "Cannot convert string "fixed" to type FontStruct" quando se usa o xming  no computador remoto.

A solução, depois de saber, é fácil:

      1. Instalar as fontes xming
      2. Adicionar o parâmetro -ac no arranque do xming #Se nos logs do xming aparecer que a ligação foi recusada
Pode acontecer dar um aviso quando se corre o programa que requer o display remoto, mas pode ser ignorado.
ex:  Warning: Cannot convert string "-monotype-arial-regular-r-normal--*-140-*-*-p-*-iso8859-15" to type FontStruct

quinta-feira, 4 de agosto de 2011

sábado, 30 de julho de 2011

Conjunto de Notas Usadas para a Certificação OCPJP 6 (1Z0-851)

Deixo aqui um conjunto de notas que poderão vir a ser úteis para quem vier a tirar a certificação OCPJP6 - Oracle Certified Professional Java Programmer 6 (exame 1Z0-851). Esta certificação era conhecida como SCJP6.


Estas notas não são exaustivas e não são o suficiente para passar o exame. Há que estudar bastante para lá chegar. Obviamente que os que programam em Java à bastante tempo estão em significativa vantagem para fazer o exame.

Alguns pontos são básicos, outros mais complexos, mas todos servem para reforçar alguns aspectos que na utilização diária passam despercebidos. Parte dos títulos das notas estão em inglês pois são de uso comum na comunidade e não faz sentido traduzir as mesmas, pois o exame é em inglês.

Antes de mais recomendo vivamente o livro SCJP Sun Certified Programmer for Java 6 Study Guide
que serve tanto para a certificação OCPJP6 como para a OCMJ6D - Oracle Certified Master, Java SE 6 Developer (ex-SCJD6).

E sem mais demoras as notas de estudo.



Identificadores legais:
  • todos os começados por letras
  • $ (dólar)
  • _ (sublinhado)
Palavras reservadas:
  • const
  • goto
  • native
  • strictfp
  • assert
  • enum
  • há mais...
strictfp: Pode ser usada numa classe ou método. Se uma classe for marcada como strictfp, então qualquer método na classe irá ser conforme as regras do standard IEEE 754 para vírgulas flutuantes e respectivas operações. Se não for usado, então as vírgulas flutuantes e respectivas operações são dependentes da plataforma. Pode-se marcar apenas um método como sendo strictfp.

native: apenas pode ser aplicado a métodos, e a sua declaração é semelhante a um método abstract.

Não há conflitos possíveis entre:
  • Nomes de classes
  • Type parameter placeholders
  • Identificadores de variáveis

JavaBeans property naming rules:
  • As assinaturas dos métodos setter têm de ser  
    • public
    • retornar void
    • ter um argumento que representa o tipo da propriedade
  • As assinaturas dos métodos getter têm de ser
    • public
    • não têm argumentos de entrada
    • tipo de retorno igual ao tipo de argumento do método setter para essa propriedade
JavaBeans listener naming rules:
  • Os nomes dos métodos dos listeners usados para "registar" um listener com uma fonte de evento tem de usar o prefixo add, seguido do tipo de listener [ex: addActionListener(ActionListener al)]
  • As regas para remover ("desregistar") são iguais ás do add excepto que o prefixo é remove [ex: removeMyListener(MyListener m)]
  • O tipo de listener a adicionar ou remover tem de ser passado como argumento do método
  • Os nomes dos métodos do listener têm de terminar com a palavra "Listener"
Source file declaration rules:
  • Pode haver apenas uma classe pública no ficheiro fonte
  • Pode haver mais do que uma classe não pública num ficheiro fonte
  • Num ficheiro sem classes públicas, o nome do ficheiro pode ser diferente de quaisquer classes nele contidas
Modificadores de acesso (visibilidade)



Qualquer classe no mesmo pacote

Qualquer classe (não subclasse) fora do pacote

Própria classe

Subclasse no mesmo pacote

Subclasse pacote diferente
* Através de herança
default OK NA OK OK NA
public OK OK OK OK OK
private NA NA OK NA NA
protected OK NA OK OK OK (*)

O modificador de acesso protected tem um efeito nas classes que pertençam a pacotes diferentes da superclasse, que é estes serem visíveis apenas através de herança. Isto é, se uma subclasse que esteja num pacote diferente da superclasse instanciar a superclasse e através desta referência tentar aceder a um membro protected, irá surgir um erro de compilação.


Declaração de Interfaces:

Todos os métodos declarados numa interface são automaticamente:
  • public
  • abstract
e estes modificadores podem ser omitidos total ou parcialmente. Só estes são permitidos!

Todas as variáveis definidas numa interface têm de ser:
  • public
  • static
  • final
ou seja, apenas é permitida a declaração de constantes. Não é preciso usar os modificadores. Podem ser omitidos ou usados intercaladamente.

Encapsulation:
  • Protecção dos dados (com modificadores de acesso)
  • Proteger as variáveis de instância
  • Assessores públicos ao invés de acesso directo a variáveis de instância (usando a metodologia dos Javabeans)

Variable argument list (var-args)

Usotipo... variável

Só pode existir um var-arg na assinatura de um método e o var-arg tem de ser o último parâmetro.

Intervalos para os primitivos

Regra geral para intervalos

     Positivos: 2(nº bits -1) - 1
     Negativos: -2 (nº bits -1)



Tipo

Bits

Intervalo Menor

Intervalo Maior
byte8-2727 - 1
short16-215215 - 1
int32-231231 - 1
long64-263253 - 1
float32NANA
double64NANA
char16NA216 - 1 (sem sinal)

O tipo char é representado em Unicode. Pode-se indicar o valor do carácter directamente em unicode. ex: \uxxxx ao invés de representar o carácter directamente. Cada carácter numa String é representado como um char.

O tipo double é a representação por defeito para números de vírgula flutuante. Podem opcionalmente ser terminados em D ou d.

O tipo float tem de ter F ou f na terminação.

Um literal inteiro é sempre um int implicitamente

O resultado de uma expressão envolvendo qualquer coisa do tamanho int ou inferior é sempre int. Por exemplo: a soma de dois byte é sempre um int.

Modificadores possíveis em variáveis e métodos

Variáveis Locais e Method Local Inner Classes Variáveis Não Locais Métodos e Inner Classes

1- Não aplicável a Inner Classes
2 - Só aplicável a Method Local Inner Classes
final










abstract 2




final
public
protected
static
transient
volatile 








 
final
public
protected
private
static1





abstract
synchronized1
strictfp
native1

Ao contrário das variáveis não locais, as variáveis locais não têm inicializações por defeito.

A inicialização de uma variável final tem de ocorrer antes do construtor(es) terminar(em).

Declaração de Arrays

Constituição de um array:

int[] xpto      =      new int[4]           {1, 2, 3, 4}      ;
_______              __________       __________
Declaração           Construção          Inicialização

Regras gerais:
  • Na parte da construção é obrigatório indicar o tamanho do array se não existir a parte da inicialização; se tiver inicialização então é opcional
  • A parte parte da construção pode ser omitida se a inicialização vier no mesmo statement
Num array multidimensional apenas é obrigatório indicar na parte da construção o tamanho da primeira dimensão, caso não haja inicialização.

Os [] podem estar intercalados com o identificador.
O tamanho do array apenas pode ser declarado na inicialização do mesmo, isto é, à direita do =.

Ex:  int[] array = new int[10];



Declaração de enumerados

enum xpto {X, Y, Z};

Só podem ser declarados:
  • na sua própria classe 
  • como um membro da classe 
  • tal como uma classe dentro de um ficheiro de uma classe pública
Os enum não podem ser declarados dentro de métodos!

Tal como numa não inner classe (quando o enum é declarado como tal), apenas se pode aplicar os modificadores:
  • public
  • default
Se mais nenhuma declaração se seguir ao enum, então o ; (ponto e vírgula) é opcional.

A ordem pela qual os valores no enum são declarados conta! Isto porque o método values() presente em todos os enums, retorna um array do tipo do enum com os valores pela ordem da declaração.

Num enum é possível fazer override a métodos do próprio enum.

Exemplo:


enum Xpto{
   A(1),
   B(2){
      // Este bloco denomina-se: Constant Specific Class Body
      public String getXptoza(){
         return "ABC";
      }
   };

   Xpto(int i){


      this.i = i;
   }
    
   private int i;
   
   public String getXptoza(){

      return "Z";
   }
}


Uma classe que implemente uma interface:
  • Não pode declarar novas checked exceptions para os métodos implementados
  • Não pode declarar excepções que são mais abrangentes que as excepções declaradas no método da interface
  • Pode declarar Runtime Exceptions em qualquer método da interface independentemente da declaração da interface
  • Não é obrigatório declarar todas as excepções da interface (pode mesmo não declarar nenhuma)
IS-A: Passa o teste do instanceof (uso de implements e extends)
HAS-A: Baseado no uso e não na herança. Ou seja, uma classe has-a outra se o código da primeira classe tiver uma referência para uma instância da segunda.

Herança, Overriding, Overloading  e Polimorfismo

Invocação de métodos polimórficos aplica-se apenas a métodos de instância overrriden! Apenas métodos de instância overriden são invocados dinamicamente baseados no tipo real de objecto.

A escolha de qual método overloaded invocar não é decidida dinamicamente em runtime. O tipo de referência (não o tipo de objecto) determina o método overloaded que é invocado.

O compilador apenas "olha" para o tipo de referência e não ao tipo de instância.

Os métodos abstract, quando concretizados pelas subclasses, são sempre do tipo override.

Os métodos static não podem ser overriden!

As variáveis de instância também podem ser overrided.

Resumindo:
  • overriding: decidido em runtime baseado no tipo de objecto
  • overloading: baseado no tipo de referência do argumento passado em tempo de compilação
Escolha de métodos overloaded


Não esquecer: O código tem de ser retro-compatível sempre! Por isso comportamentos anteriores são sempre preferidos!
  • widening é preferido sobre o boxing
  • widening é preferido sobre var-args
  • boxing é preferido sobre var-args
  • var-args é sempre o último recurso 
    Regras de overriding

    Regras para o método que está a fazer o override em relação ao método overriden:
    • Modificador de acesso
      • Não pode ter um modificador de acesso mais restritivo
      • Pode ter um modificador menos restritivo
    • Retorno
      • O tipo de retorno tem de ser o mesmo, ou um subtipo do tipo declarado
    • Excepções (em relação às excepções declaradas na assinatura do método overriden)
      • Pode lançar quaisquer excepções não checadas (que estendam RuntimeException)
      • Não pode atirar novas excepções checked
      • Não pode atirar excepções que sejam mais abrangentes
      • Pode atirar excepções que sejam subclasses
      •  Pode lançar (declarar) menos ou nenhuma excepção
    Casting
    • upcasting - o cast é implícito, é opcional fazer o cast
    • downcasting - o cast é obrigatório. É verificado apenas se o cast é possível, isto é, se os tipos estão na árvore de herança. Se não estiverem na árvore de herança dá erro de compilação.
    Implementação de interfaces
    • Seguir todas as regras para os overrides legais
    Uma interface pode estender outras (uma ou mais ao mesmo tempo).

    extends tem de preceder implements caso uma classe use os dois.

    Se uma superclasse implementar uma interface, e se uma subclasse indicar explicitamente que também implementa a mesma interface, a subclasse não tem de voltar a implementar os métodos da interface, quando a superclasse já o fez. Não faz mal voltar a tornar explícito a indicação de implementação da interface.

    Regras para construtores
    • Pode existir um método com o mesmo nome da classe, mas este não ser um construtor (basta retornar algo)
    • O construtor por defeito e sem argumentos apenas é automaticamente criado pelo compilador, se nenhum outro construtor for declarado
    • A chamada a outro construtor ou a um construtor da superclasse é o primeiro statement (a primeira instrução) de cada construtor. O compilador pode inserir a chamada a super() caso não exista nenhuma chamada a outro construtor
    • Não pode ser efectuada nenhuma chamada a métodos de instância ou acesso a variáveis de instância até depois do super construtor ter corrido (o construtor da superclasse). (Daí a chamada a outros construtores ter de estar na primeira linha)
    • O uso de variáveis estáticas e métodos estáticos é permitido na chamada a outros construtores da classe
    • As classes abstract têm construtores que são sempre chamados quando uma subclasse concreta é instanciada
    • Um construtor apenas pode ser invocado dentro de outro
    • Os construtores não são herdados!
    • Os construtores não podem ser marcados como:
      • static
      • final
      • abstract
    Construtor default
    • Tem o mesmo modificador de acesso da classe
    • Incluí ele próprio uma chamada a super()
    O compilador dará erro se uma subclasse tiver um construtor onde ele tenha de colocar uma chamada implícita a super() e a superclasse não tiver um construtor sem argumentos. Neste caso  a chamada tem de ser feita à mão, colocando a chamada ao construtor da superclasse com argumentos.

    static e o compilador


    No acesso a coisas static, o compilador apenas tem em atenção o tipo declarado da variável que está a aceder ao static, ou seja, é independente da variável de instância (o que conta é o tipo da variável de referência e não o tipo de objecto).     

    Coupling e Cohesion

    Coupling - Até que ponto uma classe está ligada às demais. Ou seja, até que ponto alterações numa classe afectam outras.
    Cohesion - Como é que uma dada classe é desenhada. Até que ponto uma classe tem um único e bem focado propósito.

    Heap e Stack

    Heap Onde estão as variáveis de instância e os objectos.
    Stack - Onde estão as variáveis locais.

    Números octais, decimais e hexadecimais


    Números octais Todos os números inteiros começados por 0 (zero) podem ter até 21 dígitos.
    Números hexadecimais - Todos os números começados por 0x (zero x). Podem ter até 16 dígitos (a representação das letras não é case sensitive).

    Por defeito, os números em octal, decimal, ou hexadecimal são ints, a não ser que sejam terminados por L ou l (L minúsculo) sendo então longs.

    Narrowing e Widening

    Sendo Maior e Menor tipos de dados :

    Maior  ------------ Narrowing (cast obrigatório) ----------------- > Menor
    Maior  <-----------Widening (cast opcional. é implícito) ---------- Menor

    "Escala":

    double > float > long > int > short > byte


    Existe o caso especial do char. Uma vez que o char é um inteiro sem sinal de 16 bits só é possível fazer widening a partir de int. Todo e qualquer cast de outro tipo de dados numérico (double, float, long, int, short ou byte) para char é sempre narrowing. Detalhes completos disponíveis na especificação.

    Os operadores de atribuição compostos (+=, -=, *=, /=) colocam automaticamente um cast, não sendo necessário, por isso, escrevê-lo.


    Valores por defeito de variáveis não locais atribuídos pelo compilador
    • Referência para objecto: null
    • byte, short, int, long: 0 (zero)
    • float, double: 0 (zero)
    • boolean: false
    • char: '\u0000' (u seguido de zeros)
    Se uma referência de array for construída mas não for inicializada dentro do array serão colocados os mesmos valores que o tipo dos valores têm na inicialização por defeito. Isto é verdade quer para variáveis locais ou de instância.

    Todas as variáveis locais têm de ser inicializadas antes de serem usadas. Caso não sejam usadas não é obrigatório inicializadas.

    Arrays

    Arrays são sempre objectos!

    Blocos de inicialização
    • Estáticos
    • de Instância - correm imediatamente depois de todos os super construtores terem corrido. Correm pela ordem que aparecem no ficheiro fonte
    Classes wrapper

    As classes wrapper (de tipos primitivos como por exemplo Integer) tal como a classe String são imutáveis. O seu valor depois de atribuído não pode ser alterado.

    Exceptuando a classe Character cujo construtor apenas recebe um char, todos os outros construtores das outras classes wrapper podem receber uma String ou o tipo que fazem wrap.

    A partir do Java 5, o objecto Boolean pode ser usado num teste booleano.

    Criação de objectos wrapper:
    • Usando um construtor
    • Usando o método estático valueOf() [tomar em atenção que a classe Character não tem este método]
    Conversão de um numérico wrapped para um primitivo (Character e Boolean não têm):
    • xxxValue()
    • parseXxx() [estático]
    Apenas os inteiros podem ter radix.


     Boolean Byte  Character  Double  Float    Integer  Long  Short
    xxxValue
    X
    X X X X X
    parseXxx
    X
    X X X X X
    parseXxx
    com radix

    X


    X X X
    valueOf X X
    X X X X X
    valueOf
    com radix

    X


    X X X
    toString(primitivo) X X X X X X X X
    toString(primitivo)
    com radix





    X X
    toXxxString
    Octal, hex ou bin





    X X

    Para o exame é necessário saber bem estes métodos, em que classes existem, etc.

    Boxing e Autoboxing

    Ao invés de se ter de:
    • criar o wrapper
    • tirar o primitivo de dentro do wrapper
    • usar o primitivo
    • voltar a criar um wrapper
    Pode-se usar o objecto como primitivo que a VM trata do resto.

    No caso dos operadores != e ==, a comparação entre um primitivo e um objecto wrapped é feita do seguinte modo:
    • Os objectos são unwrapped e a comparação será primitivo a primitivo
    Duas instâncias dos seguintes objectos wrapper (criadas através de boxing), serão sempre iguais (comparação com o operador ==) quando os seus primitivos forem do mesmo valor:
    • Boolean
    • Byte
    • Character -> de \u0000 (0) a \u007F (127)
    • Short -> de -128 a 127
    • Integer  -> de -128 a 127 

    O Boxing e o unboxing funcionam, de um modo geral, nos mesmos locais onde normalmente se usam primitivos ou um objecto wrapped.

    As classes wrapper não podem fazer widden umas para as outras.

    O que é e não é permitido (no boxing e widening):
    • widden seguido de box não é permitido
    • box seguido de widen é permitido
    Garbage Collector (GC)

    O Garbage Collector (GC) limpa apenas a heap (no que ao exame diz respeito).

    Método finalize()
    • Para qualquer objecto, finalize() será apenas chamado uma e uma só vez no máximo pelo GC
    • Chamar o método finalize() pode fazer com que o objecto não seja apagado
    • Poderá nunca ser executado
    Operadores

    Nos operadores compostos (+=, -=, *=, /=) a expressão à direita tem sempre precedência.

    Na comparação entre um carácter com outro  ou com um numérico é usado o valor unicode do carácter como valor numérico.

    Com os operadores == ou != apenas de pode comparar tipos compatíveis.

    Nos enum == ou equals() dão o mesmo resultado.

    instanceof não pode ser usado para testar duas classes hierárquicas diferentes (dá erro de compilação).

    Operador condicional :  

    variável = (expressão_booleana) ? valor_a_atribuir_ se_Verdade : valor_a_atribuir_se_Falso;

    && - short-circuit AND                                    & - non-short-circuit AND
    !!     - short-circuit OR                                    |   - non-short-circuit OR



    Switch


    switch (expression) {
         case constant1: code block
         case constant1: code block
         default: code block
    }

    Uma expressão (expression) no switch tem de ser avaliada como: char, byte, short, int ou enum, ou seja, apenas enums e variáveis que possam implicitamente ser promovidas a int podem ser usadas!

    A constante do case tem de ser avaliada tal qual a expressão (expression) do switch e ainda tem de ser uma constante em tempo de compilação!

    default case pode vir em qualquer posição do case.

    Ciclo for

    No ciclo for todas as partes da declaração são opcionais.

    Na parte da inicialização todas as variáveis têm de ser do mesmo tipo. Na parte da condição o resultado tem de ser booleano. Na parte do incremento qualquer statement é válido!

    No uso de continue e break com labels, ambos têm de estar dentro do loop que tem o mesmo nome da label. Caso contrário código não compila.

    Assertions

    Quando se usa assertions presume-se sempre que algo (o que se testa) é verdadeiro. Caso não seja uma AssertionError é lançada.
    • assert (boolean_expression);
    • assert (boolean_expression) : expressão_que_retorna_um_valor
    A parte expressão_que_retorna_um_valor é impressa apenas se uma AssertionError for lançada.

    assert só pode ser usado como identificador se o código for compilado com a opção: -source 1.3

    A opção de runtime -ea ou -enableassertions activa as assertions.

    Apeser de por defeito as assertions estarem desligadas, as opções de runtime -da ou -disableassertions inactivam as assertions também.

    A opção -dsa desliga as assertions para as classes de sistema.

    Pode-se combinar as opções de ligar e desligar assertions.


    Pode-se ligar/desligar as assertions do seguinte modo:
    • sem argumentos -> Todas as classes excepto as de sistema
    • com nome de pacote -> Todas as classes do pacote indicado e também, subpacotes
    • nome da classe -> Classe indicada
    Exemplo: -ea:pt.xpto.pacote

    Mais informação em:


    Excepções

    Unchecked Exceptions 
    • RuntimeException (e subclasses)
    • Error (e subclasses)

    Excepção Descrição Normalmente Lançada Por
    IllegalStateExceptionAtirada quando o estado do ambiente não corresponde à operação que se está a tentarProgramaticamente
    ExceptionInInitializerErrorAtirada quando se tenta inicializar uma variável ou bloco de inicialização estáticoJVM


    String Constant Pool

    Zona de memória onde são guardadas as Strings pela JVM. Se uma dada String já existir, a JVM apenas coloca uma referência extra para a String, e um novo objecto não é criado.


    Métodos mais importantes na classe String

    É imprescindível para o exame saber de cor vários métodos em várias classes. Não há consulta disponível por isso tem de se decorar a API.
    • char charAt(int)
    • String concat (String)
    • String replace(char o, char n)
    • String toLowerCase()
    • String toUpperCase()
    • String trim()
    • boolean equalsIgnoreCase(String)
    • int length()
    • String substring(int)
    • String substring(int b, int e) - O e é exclusive
    • Strint toString()
    Não esquecer: Arrays têm a propriedade length pública para leitura. Nas Strings só por acesso ao método length()!

    Métodos mais importantes na classe StringBuilder e StringBuffer
    • StringXxx append(...)
    • StringXxx delete(int s, int e) - O e é exclusive
    • StringXxx insert(int o, ...)
    • StringXxx reverse()
    • String toString()
    • boolean equals(Object) - Não compara os valores pois não é overriden!
    Java io


    Métodos principais na classe java.io.File

    Um objecto do tipo File pode representar ou um ficheiro ou uma directoria.
    O construtor da classe File não cria o ficheiro/directoria fisicamente. Apenas cria o nome do ficheiro/directoria.
    • File(File, String)
    • File(String, String)
    • File(String)
    • boolean createNewFile() - cria um ficheiro se ainda não existir
    • boolean mkdir() - cria a directoria se ainda não existir
    • boolean isFile()
    • boolean isDirectory()
    • boolean exists()
    • boolean delete() - não apaga uma directoria se esta não estiver vazia
    • String[] list()
    • boolean renameTo(File)
    Métodos principais na classe java.io.FileWriter
    • FileWriter(File) -> Cria o ficheiro fisicamente
    • FileWriter(String) -> Cria o ficheiro fisicamente
    • close()
    • write(...)
    • flush()
    Métodos principais na classe java.io.BufferedWriter

    • BufferedWriter(Writer)
    • close()
    • newLine()
    • flush()
    • write(...)
    Métodos principais na classe java.io.PrintWriter
    • PrintWriter(File)
    • PrintWriter(String)
    • PrintWriter(OutputStream)
    • PrintWriter(Writer)
    • flush()
    • close()
    • format(...)
    • write(...)
    • print(...)
    • printf(...)
    • println(...)
    • append(...)

    Nota : Só o mkdir() cria a directoria. Ao contrário do que ocorre com os ficheiros, as directorias não são criadas automaticamente pelos Writers (dá excepção).

    Métodos principais da classe java.io.FileReader
    • FileReader(File)
    • FileReader(String)
    • int read(char[])
    Métodos principais na classe java.io.BufferedReader
    • BufferedReader(Reader)
    • String readLine()
    • read()
    Métodos principais da classe java.io.Console
    • String readLine(mascaraStr, promptStr)
    • char[] readPassword(mascaraStr, promptStr)
    • format(mascaraStr, ...) - escreve na consola
    • format(String, ...) - escreve na consola
    Nenhum dos parâmetros dos métodos da classe Console pode ser null. Caso algum seja uma NullPointerException é lançada.

    Obter o objecto ConsoleSystem.console(); - Pode retornar null se a mesma não existir.

    Métodos principais na classe java.io.ObjectOutputStream
    • ObjectOutputStream(OutputStream) - OutputSteam é geralmente FileOutputStream
    • writeObject(Object)

    Métodos principais na classe java.io.ObjectInputStream

    • ObjectInputStream(InputStream) - InputStream é geralmente FileInputStream
    • Object readObject()
    Métodos principais da classe java.io.FileInputStream
    • FileInputStream(String)

    Métodos principais da classe java.io.FileOutputStream
    • FileOutputStream(String)

    Serialização

    Para serem serializáveis as classes têm de implementar Serializable.

    Se um objecto não serializável (que não implementa Serializable) for tentado ser serializado ocorre a excepção: java.ioNotSerializableException.

    Se todos os objectos do grafo de serialização forem serializáveis, não é preciso fazer nada. Caso contrário poderá ser necessário ajudar na serialização com estes dois métodos:
    • private void writeObject(ObjectOutputStream) - pode lançar IOException
      •  deve-se invocar na primeira linha do método: os.defaultWriteObject
    • private void readObject(ObjectInputStream) - pode lançar IOException e
      ClassNotFoundException
      •  deve-se invocar na primeira linha do método: os.defaultReadObject
    É recomendado tratar as excepções na serialização.

    Criação de novos objectos e Serialização

    Eventos que ocorrem quando se usa new para criar um novo objecto:
    1. Todas as variáveis de instância da classe têm atribuído os valores por defeito
    2. O construtor é invocado e, imediatamente, é chamado o construtor da superclasse
    3. Os construtores da superclasse completam (correm e terminam)
    4. As variáveis de instância que são inicializadas como fazendo parte da sua declaração vêm atribuído o seu valor inicial
    5. O construtor completa-se (corre e termina)

    Esta ordem de eventos não ocorre quando um objecto é desserializado! Quando uma instância de uma classe serializável, é desserializada:
    1. O construtor não corre
    2. Se uma classe serializável estender outra que não o é, o construtor da classe  serializável não corre (como indicado no ponto anterior), mas o da superclasse irá correr, tal como todos os construtores de todas as superclasses acima da superclasse!
    3. As variáveis de instância não têm os seus valores iniciais atribuídos
    4. Só os valores que foram salvos (o estado do objecto na altura da serialização) serão reatribuídos
    5. As variáveis que não estão no estado do objecto terão os valores por defeito do tipo da variável

    Métodos principais na classe java.util.Date
    • Date()
    • Date(long) - em milissegundos
    • setTime(long) - em milissegundos
    • long getTime() - em milissegundos
    Métodos principais da classe java.util.Calendar
    • Calendar getInstance()
    • Calendar getInstance(Locale)
    • add(...)
    • setTime(Date)
    • get(CALENDAR_CONSTANT)
    • roll(...)
    • Date getTime()
    • set(int year, int month, int day) - month começa em 0
    • CALENDAR_CONSTANT getFirstDayOfWeek()
    O método roll é igual ao método add, exceptuando que no roll os outros campos não são automaticamente incrementados ou decrementados. Só o campo indicado é que é.
      Métodos principas da classe java.util.DateFormat
      • DateFormat getInstance()
      • DateFormat getDateInstance()
      • DateFormat getDateInstance(int style) 
      • DateFormat getDateInstance(int style, Locale locale)
      • String format(Date)
      • Date parse(String)
      O argumento style pode ser:
      • DateFormat.SHORT
      • DateFormat.MEDIUM
      • DateFormat.LONG
      • DateFormat.FULL
      Métodos principais da classe java.text.NumberFormat
      • NumberFormat getInstance()
      • NumberFormat getInstance(Locale)
      • NumberFormat getNumberInstance()
      • NumberFormat getNumberInstance(Locale)
      • NumberFormat getCurrencyInstance()
      • NumberFormat getCurrencyInstance(Locale)
      • String format(Number)
      • Number parse(String)
      • int getMaximumFractionDigits()
      • setMaximumFractionDigits(int) - Só se aplica na formatação
      • setParseIntegerOnly(boolean)
      Métodos principais da classe java.util.Locale
      • Locale(String language)
      • Locale(String language, String country)
      • Locale getDefault()
      • String getDisplayCountry()
      • String getDisplayCountry(Locale)
      • String getDisplayLanguage()
      • String getDisplayLanguage(Locale)
      Existe um conjunto de constantes que correspondem já a Locales construídos. Ex: Locale.GERMANY

      Expressões Regulares (regex)

      Métodos principais da classe java.util.regex.Pattern
      • Pattern Pattern.compile(String regex)
      • Matcher matcher(String)
      • String pattern() - String Regex
      Métodos principais da classe java.util.regex.Matcher
      • boolean find() - Verifica se há um match/procura no próximo resultado
      • int start() - Indices na String fonte onde começam os emparelhamentos
      • Pattern pattern() - String regex. Só deve ser invocado se o método find retornar true.
      • String group() - Resultado que encontrou. Só deve ser invocado se o método find retornar true.
      • boolean matches() - Indica se toda a String fonte corresponde à expressão regular indicada.
      Como regra geral, uma procura regex corre da esquerda para a direita, e assim que um carácter da fonte tiver sido usado num resultado (match), não pode ser reutilizado.

      Metacaracteres
      • \s - Um carácter whitespace
      • \w - Um carácter palavra (letras, dígitos ou _ )
      Quantificadores

      Para se usar quantificadores em conjuntos [....] tem de se colocar o conjunto entre parêntesis. Por exemplo:  ([....])+
      • ?, * e + são gananciosos. Basicamente lê a fonte toda e trabalha da direita para a esquerda. Assim que encontrar pára. Dá o resultado mais longo.
      • ??, *? e +? são relutantes. Encontra o resultado mínimo.
      Com os quantificadores gananciosos, o método find da classe Matcher pode retornar resultados (matches) do tamanho 0 (zero) , nas seguintes condições:
      • Depois do último carácter da fonte
      • Entre carácteres depois de um resultado ter sido encontrado
      • No início da fonte
      • No início de uma fonte com tamanho zero
      java.util.Scanner

      Usado para tokenização on-the-fly. Por defeito o delimitador é o espaço em branco.

      Métodos principais
      • Scanner(InputStream)
      • Scanner(String)
      • Scanner(File)
      • String findInLine(String regex) - Usado em loops. Retorna null se não encontrar nada. Chamadas sucessivas encontram o próximo match.
      • boolean hasNext() - Usado em loops. Não avança.
      • String next() - Usado em loops. Obtém e avança para o próximo.
      • boolena hasNextInt() - Usado em loops. Não avança.
      • int nextInt() - Usado em loops. Obtém e avança para o próximo.
      • boolean hasNextBoolean() - Usado em loops. Não avança.
      • boolean nextBoolean() - Usado em loops. Obtém e avança para o próximo.
      • useDelimiter(String regex)
      Os métodos hasXXX e nextXXX existem para todos os primitivos excepto char.
      Os métodos nextXXX só devem ser chamados se o método correspondente hasXXX retornar true. Caso contrário pode dar excepção.

      String e Tokenizing
      • String[] split(String regex) - Deve ser usado em Strings relativamente pequenas.
       Os delimitadores usados no Scanner e no split podem ser apenas expressões regulares. Exemplo: "\d\d".

      Formatação com printf e format da classe java.io.PrintStream

      Ambos os métodos funcionam com os mesmos parâmetros: printf(String format, Object... argumentos).
      O parâmetro format pode conter simultaneamente informação normal de literais String que não estão associados a quaisquer argumentos e dados de formatação específicos de argumentos.

      Explicação da parte format:

      %[arg_index$][flags][width][.precision] conversion

      Nota: entre [] são opcionais

      arg_index$ - Um inteiro imediatamente seguido de $. Indica qual argumento deve ser impresso nessa posição.

      flag:
      • - -> Alinhar à esquerda
      • + -> Incluir o sinal (+ ou -)
      • 0 -> Preencher com zeros
      • , -> Usar separadores específicos do Locale
      • ( -> Colocar entre parêntesis os números negativos
      width - Indica o número mínimo de caracteres a imprimir.

      precision - Usado em números de vírgula flutuante e indica o número de dígitos depois da vírgula.

      conversion -O tipo de argumento a formatar:
      • b - Booleano
      • c - Carácter (char)
      • d -Inteiro
      • f - Vírgula flutuante
      • s - String
      Se o tipo indicado não condizer com o tipo de argumento uma IllegalFormatConversionException ocorre (RuntimeException).

      Métodos principais da classe java.lang.Object
      • boolean equals(Object) - Este método, se não for overrided, apenas usa o operador == para as comparações. Se este método não for overrided, então o objecto não será usável, por exemplo,  como chave em Hashtables, pois a não ser que ainda se tenha referência para a chave, nunca a mesma será encontrada. Fazendo override a este método então deve-se fazer override ao método hashcode (por causa do contrato do equals e do hashcode).
      • int hashCode() - O overriding deste método deve usar as mesmas variáveis de instância usadas no overriding do método equals. Por esta razão se for efectuado o override deste método então deve-se fazer também o overriding do método equals (contrato do hashcode e do equals).
      • String toString() - Se não for overrided, retorna o nome_da_classe@hashcode do objecto (hexadecimal sem sinal).
      • final void notify()
      • final void notifyAll()
      • final void wait()
      • void finalize()
      Contrato do equals() 
      • Reflexivo: x.equals(x) deve retornar true
      • Simétrico: x.equals(y) = true se e só se y.equals(x) = true
      • Transitivo: x.equals(y) = true e y.equals(z) = true => x.equals(z) = true
      • Consistente: Múltiplas invocações de x.equals(y) consistentemente retornam true ou consistentemente retornam false, desde que os objectos não sejam modificados na informação usada no equals.
      • x.equals(null) = false
      • Se x.equals(y) = true => x.hashcode() = y.hashcode()
      Contrato do hashcode()
      • Consistente: Múltiplas invocações no mesmo objecto, durante a execução de uma mesma aplicação Java, retornam o mesmo inteiro, desde que nenhuma informação usada na comparação equals seja alterada.
      • Se x.equals(y) = true => x.hashcode() = y.hashcode()
      • Se x.equals(y) = false não implica que x.hashcode() <> y.hascode()
      • Se x.hascode() = y.hashcode não implica que x.equals(y) = true
      Nota: Variáveis transient não são apropriadas para uso no equals e hashcode.

      Ordem Natural dos Caracteres

      Espaço em branco < UPPERCASE < lowercase 

      Collections








      Propriedades principais das colecções
      • ArrayList e Vector - Iteração rápida e acesso aleatório rápido.
      • LinkedList - Iteração rápida e remoção rápida. Boa para adicionar elementos ao início ou ao fim. Serve para concretizar uma pilha ou fila.
      • HashSet - Acesso rápido. Sem duplicados e sem ordem.
      • LinkedHashSet - Sem duplicados e com ordem de iteração pela a de inserção.
      • TreeSet - Sem duplicados. Por defeito a ordenação é feita pela ordem natural (ascendente).
      • EnumMap - A chave tem de ser um enum e tem de pertencer ao tipo indicado. Chaves null não são permitidas (dá NullPointerException). Valores null são permitidos.
      • HashMap  - Actualizações rápidas. Só uma chave null e múltiplos valores null.
      • Hashtable - Actualizações rápidas. null não é permitido em lado nenhum.
      • LinkedHashMap - Iteração rápida. Mantém a ordem de inserção. Itera pela ordem de inserção ou último acesso.
      • TreeMap - Por defeito, a ordenação é feita pela ordem natural ascendente.
      • ConcurrentSkipListMap - log(n). null não permitidos em lado nenhum. Ordem natural.
      • PriorityQueue - Priority-in, Priority-out. Os elementos são ordenados pela sua prioridade relativa. O construtor pode levar um comparador no 2º argumento.


      Classe Map Set List Queue Ordered Sorted Identificadores Duplicados
      HashMapX


      NãoNãoÚnicos(chave)Sim (valores)
      HashtableX


      NãoNãoÚnicos(chave)Sim (valores)
      TreeMapX


      SimOrdem Natural ou CostumizávelÚnicos(chave)Sim (valores)
      LinkedHashMapX


      Por Ordem de Inserção ou por Último AcessoNãoÚnicos(chave)Sim (valores)
      ConcurrentSkipListMapX


      Ordem NaturalNãoNASim (valores)
      EnumMapX


      SimNãoÚnicos(chave)Sim (valores)
      HashSet
      X

      NãoNãoNANão
      TreeSet
      X

      SimOrdem Natural ou CostumizávelNANão
      LinkedHashSet
      X

      Por Ordem de InserçãoNãoNANão
      ArrayList

      X
      Por ÍndiceNãoNASim
      Vector

      X
      Por ÍndiceNãoNASim
      LinkedList

      XXPor ÍndiceNãoNASim
      PriorityQueue


      XSimPor Prioridades ou Ordem NaturalNASim

      Métodos principais da interface java.util.Set
      • boolean add(Object)
      • boolean remove(Object)
      • int size()
      • boolean contains(Object)
      • Iterator iterator()
      • Object[] toArray()
      • Object[] toArray(Object[])
      Métodos principais da interface java.util.List
      • boolean add(int, Object)
      • boolean add(Object)
      • Object get(int)
      • boolean remove(int)
      • boolean remove(Object)
      • int size()
      • boolean contains(Object)
      • int indexOf(Object)
      • Iterator iterator()
      • Object[] toArray()
      • Object[] toArray(Object[])
      Métodos principais da interface java.util.Queue
      • Object peek() - Retorna o primeiro elemento da fila sem o remover
      • Object pool() Retorna o primeiro elemento da fila removendo-o
      • boolean add(Object) - Adiciona o elemento à fila 
      • boolean offer(Object) - Adiciona o elemento à fila
      Métodos principais da interface java.util.Map
      • Object put(Object key, Object value)
      • Object get(Object key)
      • Object remove(Object key)
      • int size()
      • boolean contains(Object key)
      • boolean contains(Object value)
      • Set keySet()
      As chaves nos Map devem (não é obrigatório mas nada será retornado) fazer override de equals() e hashCode().

      Não esquecer que os Maps funcionam em dois passos:
      • Usam o método hashCode() para encontrar o balde certo (se o hashCode do objecto usado como chave mudar, o Map irá procurar o objecto no local errado!)
      • Usam o método equals() para encontrar o objecto no balde

      Métodos principais da classe java.util.Collections
      • int Collections.binarySearch(List, Object)- Os objectos na lista têm de implementar Comparable!
      • int Collections.binarySearch(List, Object, Comparator)
      • void Collections.sort(List) - Os objectos na lista têm de implementar Comparable!
      • void Collections.sort(List, Comparator)
      • Comparator Collections.reverseOrder(List) - Os objectos na lista têm de implementar Comparable!
      • Comparator Collections.reverseOrder(Comparator)
      • void Collections.reverse(List)
      Métodos principais da classe java.util.Arrays
      • int Arrays.binarySearch(Object[], Object)
      • int Arrays.binarySearch(Object[], Object, Comparator) 
      • void Arrays.sort(Object[]) - Os objectos no Object[] têm de implementar Comparable!
      • void Arrays.sort(Object[], Comparator)
      • List Arrays.asList(Object[]) - A lista e o array ficam ligados um ao outro. O Object[] não pode ser um array de primitivos
      • boolean equals(Object[], Object[])
      • String toString(Object[])
      Métodos importantes na classe java.util.TreeSet
      • Object ceiling(Object) - Elemento mais pequeno, maior ou igual ao objecto
      • Object heigher(Object) - Elemento mais pequeno, maior que o objecto
      • Object floor(Object) - Elemento maior, menor ou igual ao objecto
      • Object lower(Object) - Elemento maior, menor que o objecto
      • Object poolFirst() - Remove e devolve a primeira entrada
      • Object poolLast() - Remove e devolve a última entrada
      • NavigableSet descendingSet() - Retorna um NavigableSet por ordem inversa
      • NavigableSet/SortedSet headSet(Object, Boolean) - Retorna o subconjunto que termina no elemento Object (*)
      • NavigableSet/SortedSet tailSet(Object, Boolean) - Retorna o subconjunto que começa no elemento Object (*)
      • NavigableSet/SortedSet  subSet(Object start, Boolean, Object end, Boolean) - Retorna o subconjunto que começa no elemento Object start e termina no elemento Object end (*)
       (*) - Os Boolean são opcionais (Java 6). Indicam se o final é inclusive e retornam NavigableSet. Caso não sejam usados os Boolean, é retornado um SortedSet.

      Métodos importantes na classe java.util.TreeMap
      • Object firstKey() - Retorna a primeira chave
      • Object ceilingKey(Key) - Retorna a menor chave, maior ou igual a Key
      • Object heigherKey(Key) - Retorna a menor chave, maior que Key
      • Object floorKey(Key) -Retorna a maior chave, menor ou igual a Key
      • Object lowerKey(Key) -Retorna a maior chave, menor que Key
      • Object poolFirstEntry() - Retorna e remove o primeiro par chave-valor
      • Object poolLastEntry() - Retorna e remove o último par chave-valor
      • Map.entry lastEntry() -Maior chave no Map ou null se vazio.
      • NavigableMap descendingMap() -Retorna um NavigableMap na ordem inversa
      • NavigableMap/SortedMap headMap(Key, Boolean) - Submapa terminado em Key (*)
      • NavigableMap/SortedMap tailMap(Key, Boolean) - Submapa começado em Key inclusivé (*)
      • NavigableMap/SortedMap subMap(Key start, Boolean, Key end, Boolean)  - Retorna o submapa começado em start e terminado em end (*)
      (*) - Os Boolean são opcionais (Java 6). Indicam se o final é inclusive e retornam NavigableMap. Caso não sejam usados os Boolean, é retornado um SortedMap.

      Os seis métodos de TreeSet e TreeMap que retornam subconjuntos, retornam subconjuntos que estão ligados aos conjuntos originais. Pode-se efectuar operações no subconjunto que irão afectar também o conjunto original. Se se adicionar/remover elementos ao conjunto original, estes serão igualmente adicionados/removidos do subconjunto se os elementos estiveram dentro do intervalo. Se se adicionar um elemento ao subconjunto que esteja fora do intervalo deste, irá atirar uma excepção. O mesmo não acontece se este mesmo elemento for adicionado ao conjunto original!

      No TreeSet e no TreeMap os seus elementos têm de implementar Comparable.

      Collections e Código Legado

      Na invocação de código legado com colecções que usam genéricos, se o código legado inserir algo na colecção que seja diferente do tipo especificado no genérico, não irá dar erro de Runtime (embora se se usar o tipo guardado numa operação supostamente de outro tipo irá dar excepção). Contudo, em tempo de compilação, chamadas a métodos legados com colecções que usam genéricos e que inserem elementos nas colecções (se a inserção for invocada do código não legado) irá dar um aviso (warning) do género: A classe usa operações não seguras ou não checadas. Usar -Xlint para ver detalhes.

      Tomar em atenção que os métodos "get" das colecções retornam Object. Se a colecção não usar generics, então é obrigatório o uso de casts, inclusive para primitivos e respectivos wrappers. Não há autoboxing automático. No "add" já há autoboxing.

      Pesquisa nas classes Arrays e Collections

      O método binarySearch das classes Arrays e Collections retorna:
      • >= 0 - Índice do elemento procurado
      • < 0 - Índice que presenta o ponto de inserção. Para calcular devidamente: ABS(ponto de inserção -1)
      Os Arrays/Collections têm de estar ordenados antes de se proceder à procura. Caso contrário os resultados serão imprevisíveis.

      Os Arrays/Collections têm de ser procurados com o mesmo tipo de ordenação que foi usado na ordenação dos mesmos (ordem natural ou usando um Comparator).

      Em tudo o que envolva ordenação (Collections, Arrays, Sets ordenados, etc), os objectos têm de ser mutuamente comparáveis (do mesmo tipo)!

      Interface java.lang.Comparable - (implements Comparable)
      •  int compareTo(Object) - O Object pode ser implementado com o próprio tipo da classe (por causa dos generics)
      Interface java.util.Comparator  - (implements Comparator)
      • int compare(Object, Object) - Os Objects podem ser implementados com o próprio tipo da classe (por causa dos generics)

      Métodos principais da classe java.util.Iterator
      • boolean hasNext()
      • Object next()

      Generics
       
      A informação de typing (do genérico) não existe em tempo de execução. Só em tempo de compilação. Todo o código "generics" é apenas para compilação.

      Com generics, atribuir a uma referência de um supertipo, um objecto de um subtipo (ou do mesmo tipo) mas com um generic diferente do declarado, nunca irá compilar com generics. O tipo de uma declaração de variável tem de ser igual ao tipo que se passa. Não funciona nem com super nem subtipos.

      Ou seja, o tipo de genérico da referência e o tipo de genérico do objecto ao qual se refere têm de ser idênticos. O polimorfismo aplica-se apenas ao tipo base.

      Tipo_Base <Tipo_Genérico> = Tipo_Base<Tipo_Genérico>;

      O mesmo acontece na invocação de métodos. Não há polimorfismo com generics.

      O polimorfismo é permitido nos arrays. Em runtime a JVM sabe o tipo dos arrays, mas não sabe o tipo das colecções (por causa do compilador apagar o tipo - Type Erasure).


      O uso de Tipo1, indica ao compilador que se pode aceitar qualquer subtipo (?) de genérico do tipo de argumento declarado (Tipo2). Esta indicação implica que nenhum objecto possa ser adicionado à colecção. Se tal suceder um erro de compilação ocorre. Esta indicação é uma excepção à regra do não polimorfismo dos generics.

      ? extends - Usa-se quer para classes quer para interfaces.


      O uso de Tipo1, indica ao compilador que se pode aceitar qualquer tipo (?) genérico do indicado (Tipo2) e também qualquer supertipo do Tipo2. Ou seja, toda a hierarquia superior do Tipo2 e o próprio Tipo2 são aceites. Isto permite adicionar elementos à colecção.

      O uso de Tipo1, indica ao compilador que se pode aceitar qualquer tipo (?) genérico. Contudo não se pode adicionar elementos à colecção.

      Não se pode usar a notação ? (wildcard) na criação de objectos. Apenas é possível nas referências.

      Criando classes genéricas (exemplos com classe genérica):
      • public class Xpto{... - Qualquer identificador Java é válido
      • private List xpto2; -Usar o tipo da classe para o tipo da lista
      • public Xpto (List x){... -Construtor que recebe uma lista do tipo da classe
      • public T getXpto(){... -Retorna-se T
      • public void returnX(T qq)... -Recebe-se T como parâmetro
      • T instânciaDeClasse - Como tipo de variável de classe
      • T[] array - Como tipo de array
      • public class useTwo{ -Dois tipo parametrizados
      • public class Bla{... -Género de limitador de tipo
      Criando métodos construtores genéricos (exemplos em que a classe não é genérica. Só os métodos):
      • public void make(T t){...
      • public doda(T t){...
      • public Radio(T t){... - Construtor

      Convenções na documentação de API's:
      • Element (colecções)
      • Type (usado em tudo excepto colecções)

      Inner Classes

      O código na Inner Class pode aceder aos  membros da enclosing (outer) class, como se a inner class fosse parte da outer class. Uma instância da inner class tem acesso a todos os membros da outer class, incluindo aqueles marcados como private.

      As inner classes são definidas dentro das {} da outer class.
      Uma inner class não pode ter quaisquer declarações static.
      Para se aceder à inner class tem de ser ter uma instância da outer class.

      Exemplos:
      Instanciar uma inner class de dentro da outer class: new InnerClass();
      Instanciar uma inner class de fora da outer class: MyOuter.MyInner x = MyOuter.new MyInner(); (*)
      Referenciar a inner class dentro dela própria: this
      Referenciar a instância da outer class dentro da inner class: MyOuter.this

      (*) Tem mesmo de se usar o nome da classe. Não se pode usar a instância.

      Method-Local Inner Classes

      Definida dentro de um método. Só pode ser instanciada dentro do método onde é declarada mas depois da declaração. Pode aceder a todos os membros da outer class (mesmo os privados). Contudo não consegue ver as variáveis locais do método a não ser que sejam marcadas como final. Este tipo de classes pode ser criada dentro de métodos estáticos (com as mesmas restrições aplicáveis a métodos estáticos).

      Anonymous Inner Classes

      Declaram uma nova classe que não tem nome, mas que é uma subclasse do tipo de declarado no new.

      Ex: Popcorn p = new Popcorn(){....};

      Também pode implementar uma interface.
      Tomar em atenção que só faz sentido implementar ou fazer overriding a métodos da superclasse, pois a variável de referência é sempre a da interface/superclasse (no exemplo acima: Popcorn). Contudo é possível fazer overloading ou criar novos métodos. Estes nunca poderão é ser invocados de fora.

      Aplicam-se as mesmas regras das inner classes.

      Argument-Defined Anonymous Inner Classes


      Definida mesmo dentro de uma chamada a um método como argumento.


      Aplicam-se as mesmas regras das inner classes.


      Static Nested Classes

      É pura e simplesmente um membro estático da enclosing class. Aplicam-se todas as restrições dos métodos static.

      Instanciação de fora: Outer,Nest x = new Outer.Nest();
      Instanciação dentro da Outer é feita de modo normal.


      Nota: Tomar em atenção que nas Anonymous Inner Classes e Argument-Defined Anonymous Inner Classes os construtores são invocados! Ex: new Popcorn() - Invoca o construtor vazio. new Popcorn(10) - O construtor recebe um int, etc.



      Métodos Principais da classe java.lang.Thread (implements java.lang.Runnable)
      • Thread()
      • Thread(String name)  
      • Thread(Runnable) - Neste caso o método run() invocado é o da instância passada.
      • Thread(Runnable, String name) - Neste caso o método run() invocado é o da instância passada.
      • public void run() - A classe Thread espera que exista o método run() sem argumentos, e executa este método numa chamada separada (numa stack diferente) depois da thread começar. Este método é invocado pelo start().
      • start() - Invoca o método run(). Começa a nova thread de execução. A thread passa para o estado Runnable. Assim que poder executar invoca o run(). O método start() apenas pode ser invocado uma vez. Uma IllegalThreadStateException (não checada) é atirada se o método for invocado mais do que uma vez.
      • boolean isAlive() - true se o método start() já foi invocado; false caso start() ainda não tenha sido invocado ou se o método run() já terminou.
      • public final void join() throws InterruptedException - Faz com que uma thread espere até que a outra entre no estado Dead.
      • String getName() - Devolve o nome da thread
      • static Thread currentThread() - Devolve a corrente thread de execução
      • void setName(String) 
      • long getId() - Devolve o id da thread
      • static void sleep(long milis) throws InterruptedException -  (*)
      • static void yeld() - Faz com que a thread passe do estado Running para o estado Runnable. Nada é garantido [dependa da JVM] (*) 
      • public final setPriority(int) - Inteiro entre 1 e 10 (depende a JVM). 
      (*) - Não libertam os locks

      Métodos Principais da Interface java.lang.Runnable
      •  public void run() - Comportamento igual ao método run() da classe Thread. É invocado pelo start().
       Para correr uma Runnable:
      1. Criar a classe que implementa Runnable
      2. Passar a instância para dentro de uma nova Thread (new Thread(Runnable))

      Nota : Tomar em atenção que a invocação directa do método run() (sem ser pelo start()) não cria um nova thread de execução!




      Continua....