quinta-feira, 2 de julho de 2009

Montando um ambiente utilizando Tomcat+Java+mysql (Debian)


Contador de acessoVisitas

Ferramentas necessárias

Considerações iniciais


O objetivo desse artigo não é ensinar a programação java, nem explicar o funcionamento do tomcat. Será considerado que o leitor já tem estas informações. Aqui iremos apenas mostrar o caminho para a instalação e configuração do servidor tomcat, apesar de utilizar de alguns códigos em java para testar o funcionamento de nosso servidor.

Ferramentas

Para começarmos a montagem de nosso ambiente, considerarei que algumas ferramentas já estão instaladas. Não irei entrar em detalhes sobre estas instalações, mas darei uma dica para instalá-las via apt-get.

Serão necessários:

mysql - servidor de base de dados
# apt-get install mysql-server-5.0

bind - servidor DNS
# apt-get install bind9

O servidor de nomes serivrá para utilizarmos o domínio de nosso servidor no lugar do localhost, apesar de este artigo utilizarmos sempre a URL http://localhost.

lynx - navegador de páginas em modo texto
# apt-get install lynx

Iremos mostrar neste artigo a instalação do

Java - jsdk
Tomcat - conatiner para aplicações java para web
drive do java para mysql.


Instalação das ferramentas

Antes de começar as instalações, gostaria de informar que as instalações serão feitas em modo shell, utilizando o apt-get, mas o leitor poderá optar por utilizar a ferramenta gráfica (front end) synaptic.

Obs.: se a apt-get não encontrar os pacotes que iremos instalar, adicione os seguintes repositórios em seu arquivo /etc/apt/source.list.


deb http://ftp.debian.org/debian/ etch main contrib non-free
deb http://ftp.br.debian.org/debian etch main contrib non-free.



Antes de mais nada será necessário instalar os pacotes java, para isso basta usar a seguinte linha de comando:

# apt-get install sun-java5-jdk

Agora, iremos instalar o tomcat. Outra tarefa muito fácil, basta como root digitar o seguinte comando:

# apt-get install tomcat5.5


O padrão do tomcat é responder a requisições solicitadas na porta 8180, logo, a URL utilizada para acessar as páginas em seu servidor será:

http://localhost:8180

Você poderá alterar esta porta alterando-a na linha
<Connector port="8180" maxHttpHeaderSize="8192"
do arquivo /usr/share/tomcat5.5/conf/server.xml, porém, aqui nós iremos trabalhar com esta porta padrão.

Feito isso, nosso container terá sido instalado, porém, não aparecerá nenhuma página, pois nada foi criado. Podemos então instalar a página de administração do tomcat e as páginas de exemplos, para isso excute, como root:

# apt-get install tomcat5.5-admin tomcat5.5-webapps

Agora, faça o teste

# lynx localhost:8180


Configurando o Tomcat

Primeiro, vamos verificar qual diretório Home do tomcat, para isso, basta entrar no arquivo /etc/init.d/tomcat5.5 e ver as variáveis de instalação.

# more /etc/init.d/tomcat5.5

aparecerá algo como:


PATH=/bin:/usr/bin:/sbin:/usr/sbin
NAME=tomcat5.5
DESC="Tomcat servlet engine"
CATALINA_HOME=/usr/share/$NAME
DAEMON=$CATALINA_HOME/bin/catalina.sh
DEFAULT=/etc/default/$NAME


ou seja, neste caso a pasta Home é /usr/share/tomcat5.5.


Vamos alterar o usuário e a senha do administrador.
Edite o arquivo /usr/share/tomcat5.5/conf/tomcat-users.xml e subistituir seu conteúdo por.


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="admin" password="123456" roles="admin,manager"/>
</tomcat-users>


salve o arquivo e reinicie o tomcat com o comando

# /etc/init.d/tomcat5.5 restart

Feito isso, podemos acessar a página de configuração do tomcat



# lynx localhost:8180

ir no link Status, digitar o usuário admin e senha 123456.

vá no link List Applications para ver as aplicações que estão em execução.


Criando nossa aplicação para teste

Nossa primeira aplicação de teste será um arquivo jsp.

Caso não exista, cria o diretório /var/www/teste. Importante é verificar a permissão para que o tomcat tenha acesso. Eu sugiro a permissão 755.

dentro de /var/www crie o arquivo teste.xml com o seguinte conteúdo


<Context path="/teste" docBase="/var/www/teste"
   debug="0" privileged="true" allowLinking="true">
</Context>


Esse arquivo informa que quando for acrescentado /teste no final da URL ele deverá redirecionar para o diretório /var/www/teste.

Existe um arquivo com <Context path="/" docBase=... informando para qual diretório o tomcat deverá apontar quando não for digitado nada depois da URL.

Ainda dentro diretório /var/www/teste, crie o arquivo index.jsp e coloque o conteúdo


Olá mundo !!!<br>
1 + 1 = ${1+1}


salve.
Essa será a nossa página.

Agora entre no diretório /usr/share/tomcat5.5/conf/Catalina/localhost/ e crie um link simbólico com o nome de teste.xml para /var/www/teste/teste.xml

# cd /usr/share/tomcat5.5/conf/Catalina/localhost/
# ln -s /var/www/teste.xml teste.xml


O tomcat irá ler todos os xml's que estão dentro desta pasta para configurar os acessos as páginas. Nós poderíamos ter criado o arquivo teste.xml direto neste local, mas por questão de organização preferi criá-lo em outro local e fazer um link.

Reinicie o tomcat e faça o teste acessando a URL localhost:8180/teste

deverá aparecer o seguinte conteúdo

Olá mundo !!!
1 + 1 = 2

Nosso segundo exemplo será a criação de servelet.

Para isso, criaremos dentro de nosso diretório /var/www/teste o diretório WEB-INF e dentro do diretório WEB-INF crie o diretório classes.

# cd /var/www/teste
# mkdir WEB-INF
# mkdir WEB-INF/classes


Dentro do diretório classes criaremos nosso código java. Chamarei de Teste2.java e conterá o seguinte conteúdo.


import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Teste2 extends HttpServlet
{
   public void doGet( HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
   {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.println("<html>");
      out.println("<body>");
      out.println("<head>");
      out.println("<title>Ola mundo !</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<h1>Ola Mundo!</h1>");
      out.println("</body>");
      out.println("</html>");
   }
}


Grave o arquivo.

Para gerar o arquivo class, precisaríamos do servlet.jar, porém no java 5 o arquivo correto é servlet-api.jar. Procure por esse arquivo em seu micro utilizando o comando find.

# find / -name servlet-api.jar

No nosso caso o arquivo foi encontrado no diretório /usr/share/java/servlet-api.jar, então, poderemos compilar nossa servlet com o seguinte comando:

# javac -classpath /usr/share/java/servlet-api.jar Teste.java

Agora nossa classe está pronta.

Vamos fazer com que possamos acessá-la pela url.

crie o arquivo WEB-INF/web.xml com o seguinte conteúdo:


<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

   <display-name>Teste !</display-name>
   <description>
      Tetste Ola Mundo !!
   </description>

   <servlet>
      <servlet-name>teste</servlet-name>
      <servlet-class>Teste</servlet-class> //Nome da classe a ser acessada
   </servlet>

   <servlet-mapping>
      <servlet-name>teste</servlet-name>
      <url-pattern>/teste-ola</url-pattern> // caminho a ser digitado
   </servlet-mapping>
</web-app>


Reinicie o tomcat.

# /etc/ini.d/tomcat5.5

Agora, o endereço http://localhost:8180/teste acessará nosso arquivo jsp e o endereço http://localhost:8180/teste/teste-ola acessará nosso servlet.


Conectando ao mysql

Vamos começar de forma diferente esse item. Começaremos criando o código para acessar as tabelas mysql e em seguida iremos corrigindo os erros conforme forem aparecendo.

Considerarei que o mysql acabou de ser instalado, logo, encontra-se sem banco, tabelas, senha etc.

Criando a senha do root como 123456:

# mysqladmin -u root password 123456

Entrando no mysql

# mysql -u root -p

Basta digitar a senha criada.

Confirmando se existe banco de dados criado.

mysql> show databases;

Se aparecer empty é porque está vazio.

Criando o banco de dados DBTeste

mysql> create database dbTeste;

Confirmando se criou.

mysql> show databases;

+-------------------------+
| Database |
+-------------------------+
| dbTeste |
+-------------------------+

Acessando o Banco:

mysql> use dbTeste

Crinando uma tabela (tbTeste) com apenas um registro (codteste) para podermos testar.

mysql> create table tbTeste (codteste integer);

Verificando se a tabela foi criada.
mysql> show tables;
+-------------------+
| Tables_in_dbTeste |
+-------------------+
| tbTeste |
+-------------------+

Inserindo registros na tabela.
mysql> insert into tbTeste (codteste) value (1);

mysql> insert into tbTeste (codteste) value (7);

mysql> insert into tbTeste (codteste) value (17);

mysql> insert into tbTeste (codteste) value (37);

Listando para saber se os registros realmente foram inseridos de forma correta.

mysql> select * from tbTeste;
+----------+
| codteste |
+----------+
| 1 |
| 7 |
| 17 |
| 37 |
+----------+

Beleza, nossa base está pronta para ser usada. Vamos sair.

mysql> exit

Agora, criaremos nosso código em java para testarmos a conexão com a base de dados.

Crie um arquivo com o nome OlaBase.java, em qualquer diretório, apenas para teste, e inclua o conteúdo a seguir.


import java.sql.*;
public class OlaBase
{
   public static void main (String args[])
   {
      String url = "jdbc:mysql://localhost:3306/dbTeste"; //string de conexão a base dbTeste
      String user = "root"; //usuário da base de dados
      String pwd = "123456";//senha do usuário criado
      try
      {
         Class.forName("com.mysql.jdbc.Driver");
         System.out.println("\nDrive carregado com sucesso!!!\n");
         try
         {
            Connection cn = DriverManager.getConnection(url, user, pwd);
            System.out.println("\nConexao estabelecida!!!\n");
            String sql = "select * from tbTeste";
            Statement stm = cn.createStatement();
            try
            {
               ResultSet rs = stm.executeQuery(sql);
               while (rs.next())
               {
                  System.out.println("\n" + rs.getString("codteste") + "\n");
               }
            }
               catch (Exception ex)
            {
               System.out.println("\nErro no Select!!!\n");
            }
         }
         catch (Exception ex)
         {
            System.out.println("\nErro na conexao!!!\n");
         }
      }
      catch (ClassNotFoundException ex)
      {
         System.out.println("Erro na conexao com a base de dados!!!");
         ex.printStackTrace();
      }
      catch (Exception ex)
      {
         System.out.println("Drive nao pode ser carregado!!!");
      }
      System.out.println("Olá Base!!!");
   }
}


Agora vamos compilar.

# javac OlaBase.java

Tudo deverá ocorrer OK. Então, vamos executar.

# java OlaBase

Devera aparecer a seguinte saída.

Erro na conexao com a base de dados!!!

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at OlaBase.main(OlaBase.java:11)
Ola Base!!!

Vimos nesta saída que o drive não foi encontrado (ClassNotFoundException: com.mysql.jdbc.Driver).

Então, vamos instalar o drive para mysql.
Primeiro, vamos ver se ele exeiste em nossa máquina.

# find / -name "mysql-connect*"

Se não retornar nenhum arquivo, vamos a instalação de drive.
Vamos ver se existe algum pacote para podermos instalarmos via apt-get.

# apt-cache search jdbc

Aparecerá a seguinte lista de pacotes.

haskell-hsql-doc - Multi-Database Interface System for Haskell
henplus - JDBC SQL commandline frontend with TAB-completion
hsqldb-server - Java SQL database server
libghc6-hdbc-dev - Haskell Database Connectivity, GHC6 package
libghc6-hsql-dev - Multi-Database Interface System for Haskell
libghc6-hsql-mysql-dev - Multi-Database Interface System for Haskell
libghc6-hsql-odbc-dev - Multi-Database Interface System for Haskell
libghc6-hsql-postgresql-dev - Multi-Database Interface System for Haskell
libghc6-hsql-sqlite-dev - Multi-Database Interface System for Haskell
libghc6-hsql-sqlite3-dev - Multi-Database Interface System for Haskell
libhsqldb-java - Java SQL database engine
libhsqldb-java-doc - documentation for HSQLDB
libhugs-hdbc - Haskell Database Connectivity, Hugs package
liblog4j1.2-java - Logging library for java
libmysql-java - Java database (JDBC) driver for MySQL
libodbc++-dev - C++ library for ODBC SQL database access
libodbc++-doc - C++ library for ODBC SQL database access
libodbc++4 - C++ library for ODBC SQL database access
libpg-java - Java database (JDBC) driver for PostgreSQL
libpgjava - Java database (JDBC) driver for PostgreSQL - transitional package
libpostgis-java - geographic objects support for PostgreSQL -- JDBC support
libsapdbc-java - JDBC interface to the MaxDB database system
libstruts1.2-java - Java Framework for MVC web applications
openoffice.org-base - OpenOffice.org office suite - database
postgresql-contrib-7.4 - additional facilities for PostgreSQL

No nosso caso queremos a "libmysql-java - Java database (JDBC) driver for MySQL". Então, vamos instalar.

# apt-get install libmysql-java

Após a instalação, vamos conferir se o arquivo .jar passou a existir.

# find / -name "mysql-connect*"

Agora aparecerá o arquivo, no meu caso o resultado da busca foi:
/usr/share/java/mysql-connector-java-5.0.4.jar

Então, basta colocar esse arquivo no classpath.

# export CLASSPATH=$CLASSPATH:"/usr/share/java/mysql-connector-java-5.0.4.jar"

Agora, tente executar o nosso programa.

# java OlaBase

O resultado será:


Drive carregado com sucesso!!!


Conexao estabelecida!!!


1


7


17


37

Ola Base!!!

Pronto, a conexão com a base de dados foi estabelecida.

Claro que a variável CLASSPATH não continuará não valerá quando reiniciarmos a máquina. Mas para resolver o problema, basta adicionar a linha no final do arquivo /etc/profile

echo "export CLASSPATH=\$CLASSPATH:"/usr/share/java/mysql-connector-java.jar"" >> /etc/profile

Agora, vamos voltar nosso arquivo index.jsp no diretório /var/www/teste e vamos fazer a alteração abaixo, para conectar a base de dados. Basta incluir no final de nosso arquivo o código:


<%
try
{
   Class.forName("com.mysql.jdbc.Driver");
   out.println ("<br>Drive encontrado!!!");
}
catch (ClassNotFoundException ex)
{
   out.println ("<br>Erro drive<br>");
   out.println (ex.toString());
}
catch (Exception ex)
{
   out.println ("<br>Erro ao procurar o drive<br>" + ex.toString());
}
%>


Salve o arquivo e em seu browser, acesse a url hocalhost:8180/teste

Aparecerá a página:

Olá mundo !!!
1 + 1 = 2

Erro drive
java.lang.ClassNotFoundException:com.mysql.jdbc.Driver

Mas como o drive é encontrado em nossa aplicação e não é encontrado em nossa página ? O motivo é que nossa aplicação procura pelo CLASSPATH já as páginas tem é limitada a buscar no diretório padrão ou no diretório de nosso projeto.

Então, basta copiar o arquivo com o drive para o diretório <CATALINA_HOME>/common/lib, porém aqui iremos apenas criar um link simbólico para o arquivo.

# cd /usr/share/tomcat5.5/common/lib
# ln -s ../../../java/mysql-connector-java-5.0.4.jar mysql-connector-java.jar


Reinicie o tomcat
# /etc/init.d/tomcat5.5 restart

Tente novamente acessar a URL localhost:8180/teste
Desta vez o resultado será:

Olá mundo !!!
1 + 1 = 2

Drive encontrado!!!

Vamos continuar nosso exemplo de teste, aumentando o código.
Edite novamente o arquivo /var/www/teste/index.jsp

Agora, vamos modificá-lo deixando com o seguinte código:


<%@page import="java.sql.*"%>
Olá mundo !!!<br>
1 + 1 = ${1+1}
<br>

<%
String url = "jdbc:mysql://localhost:3306/dbTeste"; //string de conexão a base dbTeste
String user = "root"; //usuário da base de dados
String pwd = "123456";//senha do usuário criado
try
{
   Class.forName("com.mysql.jdbc.Driver");
   out.println("<br>Drive carregado com sucesso!!!<br>");
   try
   {
      Connection cn = DriverManager.getConnection(url, user, pwd);
      out.println("<br>Conexao estabelecida!!!<br>");
      String sql = "select * from tbTeste";
      Statement stm = cn.createStatement();
      try
      {
         ResultSet rs = stm.executeQuery(sql);
         while (rs.next())
         {
            out.println( " - " + rs.getString("codteste"));
         }
      }
      catch (Exception ex)
      {
         out.println("<br>Erro no Select!!!<br>" + ex.printStackTrace());
      }
   }
   catch (Exception ex)
   {
      out.println("<br>Erro na conexao!!!<br>" + ex.printStackTrace());
   }
}
catch (ClassNotFoundException ex)
{
   out.println("<br>Erro na conexao com a base de dados!!!<br>" + ex.printStackTrace());
}
catch (Exception ex)
{
   out.println("<br>Drive nao pode ser carregado!!!<br>" + ex.printStackTrace());
}
   out.println("<br>Olá Base!!!<br>");
}

%>


Ao acessarmos a URL localhost:8081/teste nos depararemos com a seguinte mensagem:

Olá mundo !!!
1 + 1 = ${1+1}

Erro na conexão

com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: ** BEGIN NESTED EXCEPTION ** java.security.AccessControlException MESSAGE: access denied (java.net.SocketPermission localhost resolve) STACKTRACE: java.security.AccessControlException: access denied (java.net.SocketPermission localhost resolve) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264) at java.security.AccessController.checkPermission(AccessController.java:427) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) at java.lang.SecurityManager.checkConnect(SecurityManager.java:1031) at java.net.InetAddress.getAllByName0(InetAddress.java:1134) at java.net.InetAddress.getAllByName(InetAddress.java:1072) at java.net.InetAddress.getAllByName(InetAddress.java:1008) at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:138) at com.mysql.jdbc.MysqlIO.(MysqlIO.java:277) at com.mysql.jdbc.Connection.createNewIO(Connection.java:2668) at com.mysql.jdbc.Connection.(Connection.java:1531) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:266) at java.sql.DriverManager.getConnection(DriverManager.java:525) at java.sql.DriverManager.getConnection(DriverManager.java:171) at org.apache.jsp.index_jsp._jspService(index_jsp.java:65) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97) at javax.servlet.http.HttpServlet.service(HttpServlet.java:802) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:334) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264) at javax.servlet.http.HttpServlet.service(HttpServlet.java:802) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:243) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAsPrivileged(Subject.java:517) at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:275) at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:161) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:245) at org.apache.catalina.core.ApplicationFilterChain.access$0(ApplicationFilterChain.java:177) at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:156) at java.security.AccessController.doPrivileged(Native Method) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:152) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869) at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664) at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527) at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684) at java.lang.Thread.run(Thread.java:595) ** END NESTED EXCEPTION ** Last packet sent to the server was 52 ms ago.

Felizmente, se tudo correu bem até aqui, esse será nosso último erro.

Teremos que liberar a permissão de conexão.

As permissões estão definidas no arquivo "$CATALINA_BASE/conf/catalina.policy", neste caso em /usr/share/tomcat5.5/conf/catalina.policy.

Seria só alterar esse arquivo, mas se verificarmos nosso daemon (/etc/init.d/tomcat5.5), veremos que este arquivo e montado na inicialização do tomcat, pois encontraremos a seguinte linha:

# cat /etc/tomcat5.5/policy.d/*.policy \
>> "$CATALINA_BASE/conf/catalina.policy"


Ou seja, não adianta modificar o arquivo /usr/share/tomcat5.5/conf/catalina.policy, pois quando iniciarmos o tomcat esse arquivo será refeito. Na inicialização, o conteúdo do arquivo "$CATALINA_BASE/conf/catalina.policy" é substituindo pelo conteúdo de todos os arquivos ".policy" do diretório /etc/tomcat5.5/policy.d/. Então, a linha abaixo nós poderemos incluir dentro de um arquivo ".policy" do diretório /etc/tomcat5.5/policy.d/ ou, o que acho mais organizado, criar um arquivo.

Crie um arquivo /etc/tomcat5.5/policy.d/05teste.policy. Inclua o seguinte conteúdo:


grant codeBase "file:/var/www/teste/-" {
   permission java.security.AllPermission;
};


Com esse conteúdo, você faria todas as liberações para sua aplicação. O mais seguro é ir liberando as permissões a medida que forem aparecendo as necessidades, então, sugiro substituir o conteúdo do arquivo por


grant codeBase "file:/var/www/teste/-" {   
   permission java.net.SocketPermission "localhost:3306", "connect,resolve";
};


Assim, liberaremos apenas a conexão com o mysql.

Agora, basta reiniciarmos o tomcat

# /etc/init.d/tomcat5.5 restart

e testarmos nossa aplicação acessando a URL localhost:8180/teste

deverá aparecer o seguinte conteúdo:

Olá mundo !!!
1 + 1 = 2

Drive carregado com sucesso!!!

Conexao estabelecida!!!

- 1

- 7

- 17

- 37

sexta-feira, 8 de maio de 2009

Identificando o em qual Field está o Foco


Contador de acessoVisitas



Pra saber em qual fiel está o foco não é muito difícil, para isso iremos usar algumas API's do Palm OS.

Todas sa rotina estão dentro do arquivo PalmOS/Form.pas e serão elas:
FrmGetActiveForm - retorna o form ativo e sua declaração é function FrmGetActiveForm: FormPtr; external sysTrapFrmGetActiveForm;

FrmGetFocus - retorna o objeto ativo dentro do form. Sua declaração é function FrmGetFocus(const formP: FormPtr): UInt16; external sysTrapFrmGetFocus;

FrmGetObjectType - retorna o tipo de objeto, para sabermos se é um Field. Sua declaração é function FrmGetObjectType(const formP: FormPtr; objIndex: UInt16): FormObjectKind; external sysTrapFrmGetObjectType;

FrmGetObjectID - retorna o ID do Objeto focado, sua declaração é function FrmGetObjectId(const formP: FormPtr; objIndex: UInt16): UInt16; external sysTrapFrmGetObjectId;

Sendo assim, a função abaixo retorna o ID do Filed selecionado ou retorna 0 caso não haja nenhum filed focado.


function FieldFocuse: UInt16;
var
   frm: FormPtr;
   ffoc: UInt16;
begin
   result := 0;

   frm := FrmGetActiveForm;
   ffoc := FrmGetFocus(frm);
   if ffoc=noFocus then exit;
   if FrmGetObjectType(frm, ffoc)<>frmFieldObj then exit;
   result := FrmGetObjectID(frm, ffoc);
end;


O exemplo abaixo mostra como utilizar essa função, o código abaixo deixará invisível o campo Field que estiver focado.


   fieldFoc := FieldFocuse; // fieldFoc é uma variável do tipo UInt16;
   if fieldFoc <> 0 then PSField.Hide(fieldFoc);

Movimentando o Form


Contador de acessoVisitas



Neste post resolvi mostrar como mudar a posição do form via código. Para melhorar a "brincadeira", resolvi fazer o form se movimentar ao se arrastar a caneta igual a movimentação em uma janela desktop.

Para fazer essa movimentação, será necessário a utilização:

Dos tipos

FormPtr - encontra-se no arquivo PalmOS/Form.pas

   FormType = record
   {$ifdef ALLOW_ACCESS_TO_INTERNALS_OF_FORMS} // These fields will not be available in the next OS release!
      window: WindowType;
      formId: UInt16;
      attr: FormAttrType;
      bitsBehindForm: WinHandle;
      handler: FormEventHandlerType;
      focus: UInt16;
      defaultButton: UInt16;
      helpRscId: UInt16;
      menuRscId: UInt16;
      numObjects: UInt16;
      objects: ^FormObjListType;
   {$endif}
   end;

   FormPtr = ^FormType;



WinHandle - encontra-se no arquivo PalmOS/Window.pas

WindowType = record
   {$ifdef ALLOW_ACCESS_TO_INTERNALS_OF_WINDOWS} // These fields will not be available in the next OS release!
      displayWidthV20: Coord; // use WinGetDisplayExtent instead
      displayHeightV20: Coord; // use WinGetDisplayExtent instead
      displayAddrV20: Pointer; // use the drawing functions instead
      windowFlags: WindowFlagsType;
      windowBounds: RectangleType;
      clippingBounds: AbsRectType;
      bitmapP: BitmapPtr;
      frameType: FrameBitsType;
      drawStateP: ^DrawStateType; // was GraphicStatePtr
      nextWindow: ^WindowType;
   {$endif}
   end;

   WinPtr = ^WindowType;
   WinHandle = ^WindowType;


RectangleType - encontra-se no arquivo PalmOS/Rect.pas


   PointType = record
      x: Coord;
      y: Coord;
   end;
   PointPtr = ^PointType;

   RectangleType = record
      topLeft: PointType;
      extent: PointType;
   end;



Precisamos também das rotinas que se encontram no arquivo PalmOS/Form.pas

FrmGetActiveForm
function FrmGetActiveForm: FormPtr; external sysTrapFrmGetActiveForm;

FrmGetWindowHandle(Frm);
function FrmGetWindowHandle(const formP: FormPtr): WinHandle; external sysTrapFrmGetWindowHandle;

FrmGetFormBounds
procedure FrmGetFormBounds(const formP: FormPtr; var rP: RectangleType); external sysTrapFrmGetFormBounds;


FrmDrawForm(Frm);
procedure FrmDrawForm(formP: FormPtr); external sysTrapFrmDrawForm;


e no arquivo PalmOS/Window.pas

WinSetBounds(Wnd, rp);
procedure WinSetBounds(winHandle: WinHandle; {const} var rP: RectangleType); external sysTrapWinSetBounds;

o código para movimentação do form é bem simples. Criar as variável privadas que irão armazenar o ponto de toque.


var
    posX: int16;
    posY: int16;


No evento PenDown do form, o código

procedure Form1PenDown(X, Y: Int16);
begin
   posX:=X;
   posY:=Y;
   PSApplication.Handled := False; // leave event unhandled
end;


Obs.: o form não pode ser desenhado em posição negativa, ou seja o canto superior direito não pode estar acima da posição 0 e também não pode estar mais a esquerda do que a posição 0.

Sendo assim, o codigo do evento PenMove ficará


procedure Form1PenMove(X, Y: Int16);
var
    DifX: integer;
    DifY: integer;

    Frm: FormPtr;
    Wnd: WinHandle;
    rp: RectangleType;
begin
   if PenDown then
       begin
            DifX := X - posX;
            DifY := Y - posY;

            //Pega o form ativo
            Frm := FrmGetActiveForm;

            //Pega o Handle do form ativo
            Wnd := FrmGetWindowHandle(Frm);

            //Pega os valores de grafico do form
            FrmGetFormBounds(Frm, rp);

            //garante que o calculo de quanto se movel a caneta não será inferior a 0, o que causaria um erro
            posX := rp.TopLeft.x + DifX;
            if posX < 0 then posX := 0;
            posY := rp.TopLeft.y + DifY;
            if posY < 0 then posY := 0;

            //Repondo os valores corretos
            rp.TopLeft.x := posX;
            rp.TopLeft.y := posY;

            //setando os novos valores do form
            WinSetBounds(Wnd, rp);

            //redesenhando o Form
            FrmDrawForm(Frm);
       end;

       posX := X;
       posY := Y;

   PSApplication.Handled := False; // leave event unhandled
end;

terça-feira, 5 de maio de 2009

Alterando a data via código


Contador de acessoVisitas



Os funções para manipulação de data e hora no Pocketstudio são encontradas no arquivo PalmOS/DateTime.pas. Nós iremos usar o tipo DateTimeType e a função TimDateTimeToSeconds que recebe como parâmetro um ponteiro para o tipo DateTimeType.

O tipo DateTimeType é:

DateTimeType = record
   second: Int16;
   minute: Int16;
   hour: Int16;
   day: Int16;
   month: Int16;
   year: Int16;
   weekDay: Int16; // Days since Sunday (0 to 6)
end;


A função TimDateTimeToSeconds é declarada:

function TimDateTimeToSeconds(dateTimeP: DateTimePtr): UInt32; external sysTrapTimDateTimeToSeconds;


De posse dessas informações, basta incluir o código abaixo no evento que fará a alteração da hora. No exemplo abaixo são utilizados valores fixos.


var
   DtHo: DateTimeType;
begin
   DtHo.Day := 4;
   DtHo.Month := 5;
   DtHo.Year := 2009;   DtHo.Hour := 20;
   DtHo.Minute := 15;
   DtHo.Second := 34;

   //Como nossa variável não é um ponteiro e a função requer um ponteiro
   //passaremos o endereço da variável.
   TimSetSeconds(TimDateTimeToSeconds(@DtHo));
end;

segunda-feira, 4 de maio de 2009

Acionar o menu via código


Contador de acessoVisitas


No Palm, para acessar o menu é necessário clicar na barra de título, porém, pode ser que seu form não tenha barra de título, você não quis, sendo assim ele ocupa toda a área da tela.

Então, vou postar aqui uma forma de chamar o menu atravez de um botão.

O menu tem que estar criado normalmente no Resources e associado ao Form.

Para chamar o Menu, nós iremos usar as rotinas abaixo, ambas se encontram no arquivo PalmOS/Menu_.pas.

MenuInit - sua declaração é MenuInit(resourceId: UInt16): MenuBarPtr; external sysTrapMenuInit; Ela retorna o ponteriro para o menu referente ao resourceId passado como parâmetro.

MenuSetActiveMenu - sua declaração é function MenuSetActiveMenu(menuP: MenuBarPtr): MenuBarPtr; external sysTrapMenuSetActiveMenu; Ela ativa o Menu passado como ponteiro no parâmetro.

MenuGetActiveMenu - declaração function MenuGetActiveMenu: MenuBarPtr; external sysTrapMenuGetActiveMenu; Retorna um ponteiro referente ao menu ativo.

MenuDrawMenu - declaração procedure MenuDrawMenu(menuP: MenuBarPtr); external sysTrapMenuDrawMenu; Desenha na tela o menu passado como parâmetro em forma de ponteiro.

Entã, para chamar o menu basta incluir o código abaixo.


MenuSetActiveMenu(MenuInit(Menu1));
MenuDrawMenu(MenuGetActiveMenu);


uma outra forma seria guardar o ponterio do menu que foi ativado, assim não precisaremos usar a função MenuGetActiveMenu, pois já temos o ponteiro para o menu.


var
   MenuP: MenuBarPtr;
begin
   MenuP := MenuInit(Menu1);
   MenuSetActiveMenu(MenuP);
   MenuDrawMenu(MenuP);
end;

quinta-feira, 30 de abril de 2009

Como chamar outra aplicação


Contador de acessoVisitas


No Pocketstudio é possível chamar outra aplicação de dentro da sua, porém o palm não tem o mesmo conceito do windows de passear pelas aplicações mantendo-as abertas, sendo assim, você não poderá voltar a sua aplicação. Para isso, você terá que fechar a aplicação que foi aberta e iniciar a sua aplicação normalmente.

Para executarmos uma aplicação, precisaremos de duas funções:
DmFindDatabase - que se encontra dentro do arquivo PalmOS/DataMgr.pas ou seja na Unit DataMgr. Sua declaração é function DmFindDatabase(cardNo: UInt16; const nameP: PChar): LocalID; external sysTrapDmFindDatabase;

Essa função será responsável por localizar a aplicação pelo nome e nos retornar o dbID que será usado para executar a aplicação.

SysUIAppSwitch - que se encotra dentro do arquivo PalmOS/SystemMgr.pas ou seja Unit SystemMgr. Sua declaração é function SysUIAppSwitch(cardNo: UInt16; dbID: LocalID; cmd: UInt16; cmdPBP: MemPtr): Err; external sysTrapSysUIAppSwitch;

Essa fução será responsável pela execução da aplicação, de que passemos o dbID da aplicação desejada.

Então, a função para executar uma aplicação no Palm ficaria:


function exec (nameP: PChar): UInt16;
var
   dbID: LocalID;
begin
   dbID := DmFindDatabase(0, nameP);
   result := SysUIAppSwitch(0, dbID, sysAppLaunchCmdNormalLaunch, nil);
end;


Se a função não tiver sucesso na execução, ela retornará o número do erro, caso tenha sucesso retornará 0, mas não servirá pois a aplicação principal será fechada.

Como saber se um PDB está aberto


Contador de acessoVisitas


A função DmOpenDatabaseInfo retorna informações de uma base de dados aberta. Se a base de dados não estiver aberta, ela retorna um erro.

A função encontrasse dentro de PalmOS/DataMgr.pas ou seja na Unit DataMgr.

Sua declaração é:

function DmOpenDatabaseInfo(dbP: DmOpenRef; var dbIDP: LocalID; var openCountP, modeP, cardNoP: UInt16; var resDBP: Boolean): Err; external sysTrapDmOpenDatabaseInfo;


Logo a função seria:


function DBIsOpen (dbP: DmOpenRef): boolean;
var
   d: LocalID;
   o, m, c: UInt16;
   r: Boolean
begin
   result := (dmOpenDatabaseInfo(dbP, d, o, m, c, r) = 0)
end;

Mudando o título do form em tempo de execução


Contador de acessoVisitas


Para mudar o Title do form em tempo de execução no PocketStudio (Palm) basta usar a função FrmSetTitle da API do Palm OS.
Essa função encontra-se em PSL/PSForm.pas ou seja na unit PSForm e tem declaração FrmSetTitle(FrmGetActiveForm, Title);

Logo é só usar

PSForm.FrmSetTitle(Form, 'Novo Título');

Colocando o conteúdo de um campo em um Labell


Contador de acessoVisitas


Colocando o conteúdo de um campo em um Label em PocketStudio (Palm)


procedure Button1_OnCtlSelect(var Handled: Boolean; ControlID: UInt16; Control: ControlPtr; On: Boolean);
var
   Texto: PChar;
   TextoSize: UInt16;
begin
   //pegando o tamanho do texto e acrescentando mais 1 que será usado para o caracter de terminação de string
   TextoSize := PSField.TextLength(Field1) + 1;

   // Alocando o tamanho necessário para caber o texto
   Texto := PSString.StrAlloc(TextoSize);

   // Copiando o conteúdo do campo para a variável
   PSField.Text(Field1,Texto,TextoSize);

   // Colocando o conteúdo da variável no Caption do Label
   PSLabel.SetCaption(Label1,Texto);

   // Liberando o espaço alocado
   PSString.Dispose (Texto);

   // A atribuição Handled := True; serve para informar ao PalmOS que o
evento foi tratado totalmente pela sua aplicação.
   Handled:=True;

end;

terça-feira, 7 de abril de 2009

Transformando arquivos com zeros e uns em executável


Contador de acessoVisitas


Postei aqui anteriormente o viewbin, que transformava um arquivo binário, executável em uma seqüência binária de 1's e 0's.
Agora estou postando o oposto, um programa que transforma esse arquivo seqüencial de uns e zeros em um executável.

De posse dos 2, é possível transformar um executável em seqüência binária, alterar o arquivo em um editor de texto e voltar o arquivo para executável.

A idéia desses programas é fornecer ferramentas para estudo do formato ELF, para entendermos e criarmos um vírus didático para linux. É uma evolução do artigo já postado por mim sobre criação de vírus para linux.

Segue o código.


/* bintoexe.c */

#include

char bitToByte (char* bin);

int main (int argc, char* argv[])
{
   FILE *arq;
   FILE *arqDest;
   char buf[2];
   char byte[8];
   int contBit=0;
   unsigned int f;

   if (argc!=3)
   {
      printf ("Parametro incorreto.\n");
      printf ("Informe o nome do arquivo a ser convertido e o nome do arquivo de destino\n");
      return 1;
   }

   if (!(arq=fopen(argv[1],"r")))
   {
      printf ("Nao foi possivel abrir o arquivo %s!",argv[1]);
      return 1;
   }

   if (!(arqDest=fopen(argv[2],"wb")))
   {
      printf ("Nao foi possivel criar o arquivo %s!\n",argv[2]);
      return 1;
   }

   while (f=fread(buf,1,1,arq))
   {
      if ((buf[0]=='1') || (buf[0]=='0'))
      {
         byte[contBit] = buf[0];
         contBit++;
         if (contBit == 8)
         {
            buf[0] = bitToByte (byte);
            f=fwrite(buf,1,1,arqDest);
         }
      }
      /* o programa ignora qualquer sequencia que seja diferente de 8 zeros ou uns consecutivos */
      else
      {
         contBit = 0;
      }
   }
   close (arq);
   close (arqDest);
   printf ("\n");
}

char bitToByte (char* bin)
{
   char r=0;
   /* faz um OR do r com as posições dos bits do mais ao menos significativos */
   if (bin[0]=='1') r |= 0x80;
   if (bin[1]=='1') r |= 0x40;
   if (bin[2]=='1') r |= 0x20;
   if (bin[3]=='1') r |= 0x10;
   if (bin[4]=='1') r |= 0x8;
   if (bin[5]=='1') r |= 0x4;
   if (bin[6]=='1') r |= 0x2;
   if (bin[7]=='1') r |= 0x1;

   return r;
}

segunda-feira, 6 de abril de 2009

Aumentando a performance na concatenação de string em VB


Contador de acessoVisitas


Muitas vezes, simples alterações no código podem fazer com que a velocidade de seu sistema aumente em muito. Aqui nós veremos uma dica simples, porém muito eficiente com relação a concatenação de string.

No Visual Basic, assim com na maioria das linguagens, o tempo gasto com a alocação de memória é bastante alto. Sim, o Visual Basic faz alocação de memória assim como qualquer outra linguagem de programação, o fato da alocação não ser explicita muitas vezes não significa que ela não exista.

Sendo assim, se conhecermos o tamanho da string final, depois das concatenações, ficaria muito mais eficiente se alocássemos uma vez apenas a string com o tamanho final e adicionássemos as substrings com a função Mid$.

Abaixo seguem dois códigos que terão o mesmo resultado, porém com um pequena diferença na implementação e veremos que o tempo gasto na execução é absurdamente diferente.

Crie um módulo e acrescente a chamada a API que será responsável por pegar a data do micro. Usaremos essa função para pegar a data no início e no fim do código, assim o tempo gasto será a diferença entre os 2 tempos.


'data do clock no formato long
Declare Function GetCurrentTime Lib "kernel32" Alias "GetTickCount" () As Long


Agora crie um form e acrescente 2 TextBox e 2 CommandButton.

No botão 1 acrescente o código a seguir.

Código 1.


Private Sub Command1_Click()
   Dim i As Integer
   Dim j As Integer

   Dim t1 As Long
   Dim t2 As Long

   Dim texto As String

   d1 = GetCurrentTime

   For i = 1 To 300
      For j = 1 To 300
         texto = texto & "1"
         DoEvents
      Next
   Next

   d2 = GetCurrentTime

   Text1.Text = CStr(d2 - d1)

End Sub


Neste código, para adicionar o caracter a string, o processador terá um trabalho árduo, ele terá que a cada laço alocar uma memória com o tamanho de 1 byte maior que a anterior, fazer a concatenação da string nesta nova área de memória e desalocar a string antiga.

O resultado, em minha máquina foi um tempo de 59786

No botão 2 acrescente o código a seguir.

Código 2.


Private Sub Command2_Click()
   Dim i As Integer
   Dim j As Integer
   Dim k As Long

   Dim t1 As Long
   Dim t2 As Long

   Dim texto As String

   d1 = GetCurrentTime
   texto = String(90000, 0)
   k = 1
   For i = 1 To 300
      For j = 1 To 300
         Mid$(texto, k, 1) = "1"
         k = k + 1
         DoEvents
      Next
   Next

   d2 = GetCurrentTime

   Text2.Text = CStr(d2 - d1)

End Sub


Neste código, nós alocamos um string com o tamanho total desejado e a cada loop, nós colocamos a substring no lugar desejado. O resultado na minha máquina foi um tempo de 241.

Comprando os resultado constatamos que o código 2 é aproximadamente 248 x mais rápido do que o código 1.

Atenção em alguns detalhes na hora da criação de um sistema podem fazer a diferença entre um código eficiente ou não.

sexta-feira, 3 de abril de 2009

Compartilhando a Internet no linux (Debian)


Contador de acessoVisitas


Há vários tutoriais sobre esse assunto na internet, porém uns não funcionam, outros funcionam parcialmente, outros são complicados, etc.

Essa dica é utilizada por mim e funciona muito bem, cria um PROXY transparente. Bastando incluir o ip do computador no gateway das outras máquinas.

Crie um arquivo /etc/init.d/xxxxx com o seguinte conteúdo:


#!/bin/bash

echo "********* Compartilhando internet ***********"
echo "1" > /proc/sys/net/ipv4/ip_forward

# Limpando as tabelas
iptables -F
iptables -t nat -F
iptables -t mangle -F

# Mascarando conexões da rede
# se sua conexão estiver na interface ppp0, basta trocar o eth0 por ppp0
# a interface ppp0 é usada também em dial-up, então, neste caso, troque o eth0
# por ppp0
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE


Salve o arquivo. A permissão desse arquivo deve ser 07xx, de acordo com sua segurança.

OBS.: Os comandos do arquivo podem ser executados no terminal, na mesma ordem que irá funcionar. Porém ao reiniciar o computador, algumas configurações voltam ao default fazendo com que o compartilhamento não seja mais realizado.

Com os comandos nesse arquivo, toda vez que reiniciar o computador e desejar fazer o compartilhamento basta digitar:

# /etc/init.d/xxxxx

Fazer com que esse script seja executado na inicialização do sistema. Criar um link simbólico para ele no diretório /etc/rc2.d:

# cd /etc/rc2.d
# ln -s /etc/init.d/internet /etc/rc2.d/S99xxxxxx


Pronto. Agora toda vez que reiniciar o computador a internet será compartilhada automaticamente.

Trabalhando com partições Linux no Windows (visualiza, edita normalmente)


Contador de acessoVisitas


Para quem trabalha com dual boot, sempre aparece a necessidade de transferir arquivos de um sistema operacional para outro, muitas vezes trabalhar com arquivos que foram gravados em partições diferentes da reconhecida pelo SO que está sendo utilizado no momento.

Para quem trabalha com Windows e Linux em uma mesma máquina isso é possível. O Ext2IFS permite que você trabalhe com partições Linux (ext2 e ext3) no Windows como se fosse uma partição (FAT ou NTFS).

O problema é que as permissões do Linux deixam de ser válidas, assim qualquer pessoa que esteja utilizando o Windows pode alterar, renomear, excluir etc arquivos do Linux sem o menor problema, independente do usuário ou permissão atribuídos ao arquivo/pasta no Linux.

Para mais informações, veja o link:

* http://www.fs-driver.org/index.html


Veja o link com o screenshots comprovando o que digo:

* http://www.vivaolinux.com.br/screenshots/userview.php?login=grj_rj


Baixe o programa, em seu Windows, pelo link:

* http://www.fs-driver.org/download.html


Execute a instalação. Após confirmações, aparecerá uma tela listando todas as partições Linux e a opção de escolher a unidade desejada. Após seleção, aparecerá no Windows Explorer uma nova unidade, a escolhida para a partição Linux, permitido que você trabalhe nela normalmente, como se fosse uma partição Windows.

Instalando o Qemu (Debian)


Contador de acessoVisitas


Resolvi escrever esta dica pois senti dificuldade em instalar o Qemu + Kqemu no Debian Etch, mesmo sendo algo tão simples. A maioria das dicas incentivavam a instalação do KQemu com linhas de comando que não funcionavam.

Quebrando a cabeça e com alguns "chutes", encontrei uma forma muito fácil de utilizá-lo.

Porém o real motivo de postar essa dica é que será necessário a utilização do Qemu em um artigo que estou escrevendo, então resolvi escrevê-la para referenciá-la no artigo e não explicá-la na artigo, fugindo por completo do assunto.

Vamos à instalação.

No caso do Debian, é só executar a linha a seguir no shell como root:

# apt-get install qemu qemu-launcher qemuctl

OBS.: Não é necessário repositório extra.

Após instalação, será criado um atalho no menu do GNOME:

Aplicações > Acessórios > Qemu Laucher



Em Configuration Name, dê um nome a configuração.

Selecione Snapshot mode e Use CD Rom.

Usarei como exemplo a instalação do Debian na máquina virtual, então selecione CD-ROM em Boot Disk.

Em Hard disk 0, selecione o botão novo e crie o arquivo que servirá de HD para a máquina virtual. No exemplo, aumentei a capacidade do HD virtual de 1 para 2 GB e dei o nome de HHdebian.

Modifique o tamanho da memória em RAM (MB) caso queira.

Na aba Launcher settings verifique se qemu-ctl está como /usr/bin/qemuctl, se não estiver, localize-o.

Salve a configuração e clique em Lauch para inciar o qemu.

Comece a instalação do Linux pelo CD.



Se usarmos o comando "ps -ax | grep qemu" em um terminal no momento da instalação, veremos que o comando executado pelo Qemu Laucher é:

# /usr/bin/qemu -boot d -snapshot -m 128 -hda /home/usuario/HHdebian -cdrom /dev/cdrom -net nic,vlan=0 -net user,vlan=0 -localtime -soundhw sb16

Após término da instalação, modifique no Qemu Launcher (na configuração salva) o disk boot para Hard disk 0, desmarque o Use CD-ROM e clique em Launch para iniciar o Linux no Qemu.

# /usr/bin/qemu -boot c -snapshot -m 128 -hda /home/gjunior/ HHdebian -net nic,vlan=0 -net user,vlan=0 -localtime -soundhw sb16

Fazendo isso o Qemu já estará funcionando. Porém, ainda de forma lenta. Então instalaremos o módulo Kqemu para acelerar o Qemu de 4 a 5 x.

Entre no site:

* http://bellard.org/qemu/download.html


e baixe o arquivo kqemu-1.3.0pre11.tar.gz.

Descompacte o arquivo:

$ tar -zxf kqemu-1.3.0pre11.tar.gz

Entre no diretório kqemu-1.3.0pre11:

$ cd kqemu-1.3.0pre11

Mude para o usuário root e instale o Kqemu:

# ./configure
# make
# make install


Depois de instalado, carregue o módulo do kqemu com o comando:

# modprobe kqemu

Caso necessário, crie o device que ele utiliza:

# mknod /dev/kqemu c 250 0
# chmod 666 /dev/kqemu

O módulo kqemu precisa ser carregado sempre que o Linux é iniciado, para isso, crie o arquivo /etc/init.d/kqemu e inclua as linhas.


#! /bin/sh
# Carregando o módulo Kqemu
modprobe kqemu


Mude a permissão do arquivo para 755:

# chmod 0755 kqemu

Crie um link simbólico em /etc/rcS.d/:

# ln -s ../init.d/kqemu S99kqemu

Se quisermos compartilhar a unidade de CD-ROM, basta incluir os parâmetros "-cdrom /dev/cdrom" na linha de comando:

# /usr/bin/qemu -cdrom /dev/cdrom -boot c -snapshot -m 128 -hda /home/gjunior/ HHdebian -net nic,vlan=0 -net user,vlan=0 -localtime -soundhw sb16

Pronto, Qemu+Kqemu instalados no Debian.

Instalando Tomcat e JDK com apt-get (Debian)


Contador de acessoVisitas


Acabei de passar pela necessidade de instalar o Tomcat em meu servidor Debian. Porém não tive muito sucesso com as dicas já oferecidas em português e algo que parecia simples não foi tanto. Passei a procurar então material em inglês e consegui fazer a instalação, na realidade, de forma bastante simples e resolvi postar aqui.

Primeiro é necessário instalar o Sun JDK 5 (Java Developer kit 5). Nós instalaremos a partir de um repositório.

Obs.: Usaremos repositórios não estáveis, mas não tive problema com isso.

Os comandos deverão ser executados como usuário root.

Edite o arquivo /etc/apt/sources.list:

# vi /etc/apt/sources.list

e adicione as seguintes linhas:


deb http://ftp.debian.org/debian/ unstable non-free
deb-src http://ftp.debian.org/debian/ unstable non-free


Salve e feche o arquivo.

Agora vamos atualizar o apt usando o seguinte comando:

# apt-get update

Instalando o jdk:

# apt-get install sun-java5-jdk


Para confirmar se o Java está instalado e qual sua versão:

# java -version


A saída será algo da forma:

java version "1.5.0_10"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode, sharing)

Para instalar o Apache Tomcat usaremos os comandos a seguir:

# apt-get install tomcat5.5
# apt-get install tomcat5.5-admin
# apt-get install tomcat5.5-webapps


Para verificar se o Tomcat está em execução, abra um navegador e digite o seguinte endereço:

http://localhost:8180/

Você poderá trocar o localhost pelo IP ou nome do seu servidor.

Você poderá iniciar/parar/reiniciar o serviço Tomcat utilizando os seguintes comandos:

# /etc/init.d/tomcat5.5 start
# /etc/init.d/tomcat5.5 stop
# /etc/init.d/tomcat5.5 restart


Configurando o Tomcat
Pare o serviço Tomcat:

# /etc/init.d/tomcat5.5 stop

Edite o arquivo /var/lib/tomcat5.5/conf/tomcat-users.xml e substitua seu conteúdo pelas linhas abaixo. Neste caso configuraremos a mesma senha para as opções de configuração do Tomcat via browser.


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="admin"/>
<role rolename="manager"/>
<role rolename="tomcat"/>
<user username="tomcat"
password="tomcatpassword"
roles="tomcat,admin,manager"/>
</tomcat-users>


Salve o arquivo.

Inicie o serviço Tomcat:

# /etc/init.d/tomcat5.5 start

Agora você poderá usar o usuário de gerente na página de configuração do Tomcat:

http://localhost:8180/manager/html

Seu usuário será "tomcat" e a senha "tomcatpassword".

Apt-get sem CD (Debian)


Contador de acessoVisitas


Acabei de passar pela necessidade de instalar o ntpdate no servidor de minha empresa. Porém ao usar o apt-get ele pediu para inserir o CD.

O problema é que o servidor se encontra distante, sem possibilidade de levar o CD de instalação até ele.

Procurei no VOL como utilizar o apt-get sem a necessidade do CD. Encontrei excelentes dicas e artigos explicando como criar um repositório local, porém isso não adiantava.

Como não achei nada que resolvesse meu problema, resolvi fazer um teste que funcionou.

Edite o sources.list:

# vi /etc/apt/sources.list (use o editor que preferir)

Comente a linha referente ao cdrom e salve, pois não queremos que o cdrom faça parte de nosso repositório.


#deb cdrom:[Debian GNU/Linux 4.0 r0 _Etch_ - Official i386 CD Binary-1 20070407-11:55]/ etch contrib main


Confirme se existe o repositório da sua distribuição, neste caso o Debian.


deb http://ftp.debian.org/debian/ etch main


Atualize o repositório:

# apt-get update

Pronto!

quinta-feira, 2 de abril de 2009

Identificando a versão do Windows com Visual Basic



Contador de acessoVisitas


Muitas vezes é necessário identificar qual a versão do windows está sendo usado. O código abaixo mostra como fazer isso.

O código identifica exatamente se a versão do Windows é 3.X, 98, 98, 98 SE, ME, NT, 2000, XP ou se é uma versão 64 Bits. Não foi possível testar e identificar as versões Vista, 2003 e Seven, porém quem desejar basta utilizar o código e testar o valor das variáveis. Como não foi testado nessas versões, não é possível garantir o seu funcionamento para estas.

Crie um módulo e insira as seguintes linhas


Public Type T_WINVER
   PlatformID As Long
   VersionName As String
   VersionNo As String
   ServicePack As String
   BuildNo As String
End Type

Public Type T_OSVersionInfo
   OSVSize As Long
   dwVerMajor As Long
   dwVerMinor As Long
   dwBuildNumber As Long
   PlatformID As Long
   szCSDVersion As String * 128
End Type

Public Const VER_PLATFORM_WIN32s = 0
Public Const VER_PLATFORM_WIN32_WINDOWS = 1
Public Const VER_PLATFORM_WIN32_NT = 2

Public Declare Function GetVersionEx Lib "Kernel32" _
   Alias "GetVersionExA" _
   (lpVersionInformation As T_OSVersionInfo) As Long


No mesmo módulo, ou no seu form inclua as linhas abaixo. O detalhe é que se resolver colocar essa rotina dentro do mesmo módulo a rotina tera que ser publica ou seja:

Public Sub getWindowsVersion(ByRef win As T_WINVER)


Private Sub getWindowsVersion(ByRef win As T_WINVER)
   Dim OSVersionInfo As T_OSVersionInfo
   Dim pos As Integer
   Dim sVer As String
   Dim sBuild As String

   OSVersionInfo.OSVSize = Len(OSVersionInfo)
   If GetVersionEx(OSVersionInfo) = 1 Then
      #If Win32 Then
         'PlatformId contém o valor que representan o SO
         'no mesmo PlatformId o Windows pode variar de acordo com a versão
         'do sistema
         win.PlatformID = OSVersionInfo.PlatformID

         Select Case OSVersionInfo.PlatformID
            Case VER_PLATFORM_WIN32s:
               win.VersionName = "Win32s"
            Case VER_PLATFORM_WIN32_NT:
               win.VersionName = "Windows NT"
               Select Case OSVersionInfo.dwVerMajor
                     Case 4:
                        win.VersionName = "Windows NT"
                     Case 5:
                        Select Case OSVersionInfo.dwVerMinor
                           Case 0: win.VersionName = "Windows 2000"
                           Case 1: win.VersionName = "Windows XP"
                        End Select
               End Select

            Case VER_PLATFORM_WIN32_WINDOWS:
               Select Case OSVersionInfo.dwVerMinor
                  Case 0: win.VersionName = "Windows 95"
                  Case 90: win.VersionName = "Windows ME"
                  Case Else: win.VersionName = "Windows 98"
               End Select
         End Select

         win.VersionNo = OSVersionInfo.dwVerMajor & "." & OSVersionInfo.dwVerMinor

         win.BuildNo = (OSVersionInfo.dwBuildNumber And &HFFFF&)

         pos = InStr(OSVersionInfo.szCSDVersion, Chr$(0))
         If pos Then
            win.ServicePack = Left$(OSVersionInfo.szCSDVersion, pos - 1)
         End If
      #ElseIf Win64 Then
         getWindowsVersion = "Windows 64 Bits"
      #Else
         getWindowsVersion = "Windows 3.X"
      #End If
   End If
End Sub


Agora crie a chamada para rotina onde preferir
Um exemplo de utilização segue abaixo


Dim win As T_WINVER
getWindowsVersion win
MsgBox "Nome: " & win.VersionName & Chr(13) & _
   "ID da Plataforma: " & win.PlatformID & Chr(13) & _
   "ServicePack: " & win.ServicePack & Chr(13) & _
   "Numero da Versão: " & win.VersionNo & Chr(13) & _
   "Build: " & win.BuildNo

Instalando e configurando o aMule (Debian)



Contador de acessoVisitas


Instalação

O aMule é uma boa alternativa para usuários Linux do programa eMule, seu concorrente famoso usando na plataforma Windows. Os dois são bastante parecidos, o que o torna bastante atraente para usuários novos na plataforma Linux acostumados com seu concorrente no Windows. A grande vantagem do aMule é que ele tem versões para várias plataformas: Linux, Mac e até Windows.

Para quem tem dúvida sobre sua performance, se tem a mesma quantidade de usuários consequentemente mesma quantidade de arquivos disponíveis. O aMule trabalha com a mesma rede, eDonkey.

Instalação
A instalação é bastante simples. Os passos abaixo foram testados no Debian e não apresentaram problemas.

Abra o terminal em modo root.

Digite a seguinte linha de comando:

# apt-get install amule

Responda sim (yes) em todas as perguntas.

Feito isso a instalação irá se completar sem problemas.

OBS.: Se os pacotes não forem encontrados, siga os passo do repositório e volte a executar esses passos. Caso contrário, pule para a configuração.

Repositório
Se a instalação falhou, os pacotes não foram encontrados, é porque o repositório usado não os contém. Para solucionar esse problema vamos incluir novos repositórios as seu Debian. Caso algum dos repositórios já esteja sendo utilizado, não o adicione.

Edite o arquivo /etc/apt/sources.list:

# vim /etc/apt/sources.list

Inclua no final do arquivo as seguintes linhas:


############
deb http://ftp.debian.org/debian/ etch main
deb-src http://ftp.debian.org/debian/ etch main

deb http://security.debian.org/ etch/updates main contrib
deb-src http://security.debian.org/ etch/updates main contrib
############


Salve o arquivo.

Os repositórios estão adicionados, volte a instalação.

Configuração

O grande problema que tenho visto após o aMule estar instalado é o fato de não conseguirem se conectar a rede. Isso acontece pois várias listas de servidores foram desativadas, incluindo a padrão da instalação do aMule.

Para corrigir isso:

Vá opção Rede > servidores e inclua as seguintes URLs. Clique em atualizar lista após cada uma.

http://www.picsystems.net/emule/servermet/all_server.met
(essa lista deve te retornar aproximadamente uns 180 servidores)

http://www.gruk.org/server.met.gz
(essa lista de te retornar uns 25 servidores)

http://www.gruk.org/server.met
(essa lista deve trazer uns 5 servidores)

Pronto, você está pronto, o aMule está pronto para conectar-se a rede.

OBS.: Sugiro que inclua essas três URLs em:

Preferências > Servidor > Atualizar lista de servidor ao se conectar (Botão lista). Sugiro também que marque esta mesma opção.

quarta-feira, 1 de abril de 2009

Instalação do Skype no Debian



Contador de acessoVisitas


O Skype é um programa VoIP que tem conquistado cada vez mais espaço. Particularmente prefiro ele ao Windows messenger por achá-lo mais profissional, mais leve, além de ter uma grande quantidade de recurso. A versão para Linux, infelizmente não é tão atraente quanto a Versão Windows, porém cumpre a sua função muito bem.

Veja uma screenshot dele em ação.

Para instalar, entre no site:

http://www.skype.com/intl/en/download/skype/linux/choose/



Escolha a sua distribuição e faça a instalação.

Neste caso irei me basear no Debian.

Escolha neste site o download da distribuição Debian. Salve o arquivo .deb.

Como root, abra um terminal e digite o comando:

# dpkg -i skype-debian_xxx.deb

Onde xxx é a versão do skype.

Uma outra forma bastante fácil é através do apt-get.

Neste caso, inclua o repositório para baixar o skype no arquivo /etc/apt/sources.list. Edite o arquivo da forma que preferir e inclua a linha:


deb http://download.skype.com/linux/repos/debian/ stable non-free


Salve o arquivo e execute os comandos:

# apt-get update
# apt-get install skype


Seguindo os passos, o Skype estará instalado e funcionando sem nenhuma configuração adicional.

segunda-feira, 30 de março de 2009

leitura/escrita de dados/estruturas em arquivo



Contador de acessoVisitas


O código a seguir é apenas um exemplo simples de gravação de dados em arquivo texto sob forma de estrutura.


#include <stdio.h>

typedef struct Taluno
{
   char nome[20];
   int idade;
} Taluno;

Taluno aluno, raluno;

int main(void)
{
    /* aqui pode usar o strcpy, mas preferir por caracter x caracter para melhor visualizacao do que esta ocorrendo */
    aluno.nome[0] = 'F';
    aluno.nome[1] = 'u';
    aluno.nome[2] = 'l';
    aluno.nome[3] = 'a';
    aluno.nome[4] = 'n';
    aluno.nome[5] = 'o';
    aluno.nome[6] = '\ 0';

    aluno.idade = 10;

    FILE *file;

    /* abrindo o arquivo para escrita */
    if (!(file=fopen("teste.txt","w+"))) return 0;

    /* gravando os dados */
    fwrite (&aluno, 1, sizeof (Taluno), file);

    close (file);

    /* apenas para separar a escrita da leitura em 2 tempos */
    /* vou usar variaveis diferentes apenas para realmente verem que realmente a leitura esta sendo feita totalmente independente da escrita, nao quero deixar duvida */
    printf ("precione qualquer para continuar ...\n");
    getchar();

    FILE *filer;

    /* abrindo o arquivo para leitura */
    if (!(filer=fopen("teste.bkp","r"))) return 0;

    long ret;

    /* lendo o arquivo */
    ret = fread (&raluno, 1,sizeof (Taluno), filer);

    if (ret > 0)
    {
       /* imprimindo o conteudo lido */
       printf ("Nome: %s\nidade: %d anos\n", raluno.nome, raluno.idade);
    }

    close (filer);
    return 1;
}

X Window, Controladores de Janelas e Ambientes Desktop



Contador de acessoVisitas


O que é o X ?

O X window é um conjunto de protocolos e funções de comunicação utilizados para construir as primitivas gráficas, em sistema de janelas; como pontos, linhas e retângulos, e interface com hardware gráfico e entrada de dados (mouse, teclado). Praticamente tudo que você vê em um ambiente gráfico do GNU/Linux, FreeBSD, OpenBSD, NetBSD, Solaris e outros - Irei generalizar tudo como Linux - partiu de uma solicitação de uma aplicação ou biblioteca para o X.

O X foi criado desde sua base para suportar gráficos em rede. Os programas ou aplicações são conhecidos como clientes. Os clientes não desenham ou manipulam os gráficos direto em seu exibidor, mas se comunicam com seu servidor X para que esses manipulem o seu exibidor.

A confusão se dá basicamente por dois motivos:

* Normalmente os usuários caseiros executam o servidor e o cliente X na mesma máquina, passando a falsa sensação de que o exibidor é controlado pela aplicação que está sendo executada. Porém é possível executar vários servidores X em um único computador e os clientes de computadores remotos. Isso significa que ele pode ser acessado por vários tipos de rede ou através de uma linha dial-up.
* Outro motivo é que a idéia de quem é o cliente e quem é o servidor aparenta estar invertida neste caso. Se interajo com uma aplicação rodando remotamente, vou supor que sou o cliente e a outra máquina o servidor. Mas no caso do X, minha máquina será o servidor para a aplicação remota, pois esta enviará os pedidos (desenhe uma janela, um ícone, etc) para o servidor X rodando na minha máquina, que por sua vez exibirá na minha tela as solicitações da aplicação cliente X, e enviará para mesma a movimentação do mouse e entradas do teclado relevantes.

Você não deve se referir ao X Window como X Windows, os termos apropriados são X, X11, X versão 11 ou sistema X Window versão 11.

O X Foi desenvolvido de início no Instituto de Tecnologia de Massachussets no início dos anos 80. O primeiro lançamento oficial foi o X 10 no meado da década de 80 com lançamento do X11R1 em 1987. Com o fim de sua associação criadora o X passou a ser de propriedade da organização não-comercial X.org, cujos membros executivos incluem a Compaq, HP, IBM, Sun, SGI etc - que mantiveram o modelo original inalterado.

A evolução do X

Um sistema X Window muito utilizado nas distribuições Linux é a coleção de programas do Projeto XFree86 que é baseado na X11R6.4 ou X11, revisão 6.4.

O XFree86 é resultado do trabalho de vários programadores do Open Source e desenvolvedores ao redor do mundo. Uma das vantagens do XFree86 é que a maioria, senão todo o código fonte para os servidores, clientes, módulos, bibliotecas está disponível. Todavia o XFree86 não é distribuído sob a licença GLP, ele é protegido por um tipo de licença BSD de direito autoral, nem todo o código fonte tem que ser fornecido e os vendedores podem fazer melhorias porém distribuir apenas versões em binário.

O XFree86 funciona em uma quantidade bastante vasta de chips de vídeo, placas gráficas e sistemas para notebook, incluindo hardware não Intel. Porém, se você tiver uma necessidade especial ou o XFree86 não funcionar adequadamente, você pode usar fontes alternativas.

Posteriormente, a versão XFree86 da X.Org, baseado no X11R6.4 incluíram algumas melhorias como exibidores multi-head (XINERMA), recursos de configuração mais simples, Display Power Management Signal (DPMS) para economizar energia dos monitores, exigência de memória reduzida, APIs, novas placas gráficas suporte DRI para gráficos 3D etc.

As novas distribuições vem disponibilizando como X Window o XOrg e não mais o XFree86. O XOrg é um fork no projeto Xfree a partir da versão 4.4 Rc2. Essa mudança originou-se por causa da licença do Xfree4.4 final que impunha cláusulas de propaganda.

Basicamente, como o xfree é open source, ex-programadores do xfree, insatisfeitos com o desenvolvimento do mesmo, resolveram fazer um novo projeto baseado no xfree. Como o xfree mudou a sua licença, onde cada distro que a utilizasse ficaria obrigada a mencionar o uso do xfree em sua licença principal, algumas distros resolveram mudar para a XOrg, que utiliza a licença GNU/GPL tradicional.


Entendendo o X

Antes de continuarmos vamos analisar a estrutura típica do Linux.



Cada camada recebe solicitações da camada superior e faz suas solicitações as camadas inferiores. Contudo as camadas não são obrigadas a fazer solicitações as camadas imediatamente inferiores, as solicitações podem pular camadas e fazer solicitações a camadas ainda mais abaixas. As camadas inferiores, assim, não tem consciência de quem está acima. Acima de tudo está o usuário que ao interagir com as aplicações não precisam saber se estão manipulando o Kernel, ferramentas, ambiente gráfico ou seja lá o que venham a inventar.

Esse tipo de estrutura é bem flexível, pois, podemos trocar qualquer componente de uma camada por outro compatível que continua tudo a funcionar normalmente. Lembrando que o padrão seguido pelos Linux POSIX, que estabelece compatibilidade em nível de código fonte, e recompilações seriam necessárias, possivelmente em outras camadas além da que estivesse sendo substituída. Isso é exatamente o que chamamos de arquitetura modular.

A vantagem desse tipo de arquitetura é exemplificado com o caso do servidor XFree86, que devido à uma mudança no licenciamento e outros problemas, já citados, fizeram com que a maioria dos desenvolvedores saíssem do projeto com o código anterior a mudança da licença e criassem o X.Org, gerido pela X.Org. Hoje em dia X.Org avança muito mais rápido que o XFree86 e é o padrão da maioria das distribuições, enquanto isso o XFree86 agoniza lentamente. A substituição não foi tecnicamente problemática pois os clientes continuavam fazendo suas solicitações via o protocolo X11.

O funcionamento do X
Como já mencionado, no X o servidor e cliente se comunicam via protocolo X11. O servidor desenha as informações no exibidor e repassam as informações recolhidas, como clique do mouse, ao cliente. Este por sua vez processa as informações recebidas e requisita ao servidor para que o resultado seja mostrado no exibidor. Veja a estrutura:



Com isso podemos:

Executar o X11 via SSH:

$ ssh login@servidor -X

Usando o parâmetro X no ssh habilitamos o modo X11 porém por uma solicitação criptografada.

Multihead:

O Incrível Computador de Duas Cabeças.

Com dois ou mais monitores e placas de vídeo, na quantidade certa, podemos ter o resultado de uma aplicação executada em um cliente X mostrada de forma "configurável" em todos os monitores. Esse recurso é conhecido como Xinerama.

Múltiplos Servidores X:

Podemos rodar mais de um servidor X na mesma máquina. Essa forma é facilmente observada nas distribuições mais novas quando fazemos uso da opção "Logar como outro usuário". Neste caso, um novo servidor X é executado e sem deslogar o anterior ficando possível alternar entre os servidores.

Podemos ainda ter servidores X dentro de outro servidor X, é o que se chama servidor aninhado.

Controladores de janelas x Ambiente desktop

Até o momento, estivemos tratando o ambiente gráfico do Linux como se fosse apenas o servidor X, mas na realidade o ambiente gráfico como conhecemos se divide em mais duas camadas, o Controlador de Janelas e o Ambiente Desktop.

Atualmente, estamos acostumados com um padrão gráfico, ou melhor, um paradigma gráfico, que foi desenvolvido pela Xerox e que obteve muito sucesso, sendo copiado pela maioria, senão por todos os ambientes Desktops encontrados, o WIMP - Window, Icon, Menu, Pointing device (Janela, Ícone, Menu, Dispositivo de apontador).

No Linux:

* o Servidor X cuida apenas do Dispositivo de apontador, do WIMP ( além do vídeo, teclado e mouse).
* o Gerenciador de Janelas cuida de toda a lógica referente a janela, como: arrastar, redimensionar, minimizar, não deixar redimensionar bordas fixas etc.
* o Ambiente Desktop, por sua vez abstrai, através de ícones e Menus.

Para ilustrarmos o funcionamento das três camadas, vamos imaginar a execução de um programa através de dois cliques dado no ícone.

O Servidor X captura os cliques e passa adiante, para quem for responsável, isso não o importa para ele. Neste caso o responsável foi o Ambiente Desktop que abstraiu a execução da aplicação em um ícone, ele então, entende o clique realiza a execução da aplicação, porém a solicitação de execução da aplicação poderia ser feita por uma linha de comando no shell. Ao criar a janela, o gerenciador de janelas passa a gerenciá-la. Nem a aplicação, nem o Servidor X querem saber quem vai tratar o gerenciamento da janela, nem se alguém vai tratar. A aplicação estará preocupada com o que ela se destina a fazer, já o Servidor X está preocupado em desenhar na tela, onde pedirem.

Logo, quando a janela é arrastada, o Gerenciador de Janelas solicita ao Servidor X que redesenhe a janela em várias posições diferentes, apagando sempre o desenho anterior, dando a sensação de movimento. Porém, o Gerenciador de Janelas poderia pedir que ao X que desenhasse apenas quando chegasse ao destino, ou poderia não ter gerenciador de janela, fazendo com que a janela não pudesse ser movida.

Um gerenciador de janelas, normalmente, não oferece abstração para ícones e menus, eles esperam que o Ambiente Desktop faça esse trabalho, porém nada impede que sejam criados Gerenciadores de Janelas como o Fluxbox e Enlightenment, que foram feitos para não necessitarem de nenhum componente superior.

As imagens abaixo mostram a Ambiente Desktop GNOME, que veremos mais tarde, exibindo uma janela do Iceweasel.

Na primeira imagem o Gerenciador de Janelas metacity está em execução. Note que a janela apresenta a barra de título, os botões de controle, bordas etc. Todas estas funcionalidades existem pois o metacity está controlando-as.

Na segunda imagem temos o mesmo ambiente, porém o processo do metacity foi destruído, logo, não há mais um Gerenciador de Janelas sendo executado. Note que todas as funcionalidades referentes ao Gerenciador de Janelas deixou de existir.

Em ambos os casos, o Servidor X, neste caso o Xorg, e o ambiente Desktop, o GNOME, estão em execução.






Como foi mostrado, o Ambiente Desktop é algo bastante abstrato. Ele é formado por um conjunto de bibliotecas, serviços muito bem integrados e disponibilizado de forma agradável para utilização dos usuários. Porém, isso tem um custo. O desempenho da máquina é diminuindo de forma sensível. Isso faz com que usuários mais hardcore prefiram usar Gerenciadores de Janelas como, os já citados, Fluxbox e Enlightenment.

Os GNOME, KDE, XFCE, XPde, WindowMaker e IceWM são exemplos de Ambiente Desktop bastante usado no Linux. O XFCE, por exemplo, embora seja bem modesto, também é muito leve, contudo, traz muito mais funcionalidade que qualquer Gerenciador de Janelas, isso o torna uma opção bastante interessante para usuários de máquinas mais modestas.

Recentemente a Novell liberou o servidor XGL que usa a aceleração 3D da placa de vídeo para fazer efeitos maravilhosos. Graças a essa independência dos pacotes, esses efeitos podem ser vistos em qualquer Desktop (GNOME, KDE, XFCE, XPde, WindowMaker, IceWM etc) e qualquer Gerenciador de Janelas (metacity, fluxbox, enlightenment etc), pois o XGL é um Servidor X (que segue o padrão X11), logo ele é transparente as camadas superiores. Além do XGL, existe também o AIGLX da X.Org.

Percebam a modularização, essa independência das camadas do "Linux" (aqui entre aspas pois me refiro ao Linux de uma forma mais abrangente ainda do que vinha tratando) é um dos motivos que levam cada dia mais o "Linux" ganhar não usuários, mas amantes.

Brincado com as camadas

Veremos, praticando, o funcionamento das três camadas vistas neste artigo. Para isso, será usada a instalação Desktop básica de uma distribuição Debian, os testes poderão ser feitos usando o Ambiente Gráfico de qualquer distribuição, levando em consideração - é claro - suas diferenças.

De todas as três camadas; Servidor X, Gerenciador de Janelas e Ambiente Desktop; o único processo que não será parado é o Servidor X, pois se este for destruído, torna-se impossível utilizarmos a parte gráfica da distribuição.

Nestes exemplos usaremos o XOrg como Servidor X, o metacity como Gerenciador de Janelas e o GNOME como Ambiente Desktop.

Você poderá instalá-los usando (para usuários do Debian):

# apt-get install xorg metacity gnome

Na seção de login, use a seção Terminal de segurança, abrirá um terminal em um ambiente gráfico. Neste momento, apenas o XOrg (servidor X) estará rodando.

Digite no terminal:

$ ps -ax

Veja que não há ocorrência do Gerenciador de Janelas (metacity) e nem do Ambiente Desktop (gnome).

Apenas com o Servidor X ativo, digite:

$ xcalc &
$ gimp &

Você terá seguinte tela.



Tente mover ou redimensionar a janela, verá que não é possível.

Note que as janelas estão sem a barra de título, os botões de controle etc. Isso se deve pelo fato de que o Gerenciador de Janelas não está ativo. Também não há a barra de menu do gnome, controle de volume etc, afinal, o Ambiente Desktop também não está ativo.

Ativaremos então, o Gerenciador de Janelas. Digite no terminal:

$ metacity &

Obs.: Caso não consiga passar o foco para o terminal, feche o gimp (pois o gimp prende o foco em sua janela) execute o metacity e depois o gimp novamente.

Agora o seguinte ambiente será mostrado.



Note que agora, como o metacity, as janelas já apresentam sua funcionalidades, apesar do Ambiente Desktop ainda não estar ativo.

Então, ativaremos o Ambiente Desktop. Digite no terminal:

$ gnome &

Teremos agora o ambiente que estamos acostumados com o Servidor X, Gerenciador de Janelas e Ambiente Desktop.



Faltou vermos o Ambiente Desktop redando direto sobre o Servidor X, sem um Gerenciador de Janelas entre eles. Então, mate o processo metacity. Digite no terminal:

$ ps -ax | grep metacity

Anote o número do processo do metacity e:

$ kill -9

ou digite no terminal:

$ exit

Logue novamente na seção Terminal de segurança. No terminal digite:

$ gnome &
$ xcalc &
$ gimp &

Teremos então a seguinte tela:



Espero ter esclarecido algumas dúvidas com relação ao assunto proposto.
Advogados
Visitas