hisham hm

Java: if you have trouble declaring a static hashmap…

Java (as of version 6, aka 1.6) does not allow you to declare a static HashMap as conveniently as an array. Still, you have the alternative of using a static block in your class to add fields. Take this example:

import java.util.HashMap;

public class StaticHashMapTest {
	private final static HashMap constants = new HashMap();
	static
	{
		constants.put("A", "The Letter A");
		constants.put("B", "The Letter B");
		constants.put("C", "The Letter C");
	}
	/* Rest of your class that needs to know the consts */
}

This works fine. But then you want to map something a little more complex than a string to another string. And I don't mean something very complex... just, say, a string to a string and an integer (yes, you'd like to use some kind of "pair object", but it looks like Java does not have it).

So you go and try to do things The Java Way (tm) and create a tiny class just to hold your two values:

import java.util.HashMap;

public class StaticHashMapTest {

	private class Pair {
		final String name;
		final int number;
		public Pair(String name, int number) {
			this.name = name;
			this.number = number;
		}
	}

	private final static HashMap constants = new HashMap();
	static
	{
		constants.put("A", new Pair("The Letter A", 123));
		constants.put("B", new Pair("The Letter B", 456));
		constants.put("C", new Pair("The Letter C", 789));
	}
	/* Rest of your class that needs to know the consts */
}

This should suffice, right? I even made the Pair class private to my class, to ensure good information hiding (that's what Java is all about, right?). Turns out this fails to compile:

StaticHashMapTest.java:18: non-static variable this cannot be referenced from a static context
      constants.put("A", new Pair("The Letter A", 123));
                         ^
StaticHashMapTest.java:19: non-static variable this cannot be referenced from a static context
      constants.put("B", new Pair("The Letter B", 456));
                         ^
StaticHashMapTest.java:20: non-static variable this cannot be referenced from a static context
      constants.put("C", new Pair("The Letter C", 789));
                         ^
3 errors

The error messages say that my "new" operators are failing due to the use of the "this" variable, which is not there at all! But hey, we can call "new" from a static context, can't we? We just did that when declaring the HashMap itself.

It turns out that the problem is that we're using an inner class. Objects from inner classes hold a "this" reference to their parent object (yes, as in myInnerObject.this.myParentAttribute... go figure), hence the trouble with the implicit "this" reference.

You have to make it a static inner class, which means it doesn't know anything about the enclosing class. Yes, that's yet another meaning for the word "static" in programming. Due to this peculiar meaning, inner classes are the only context where you can use the "static" qualifier to a class declaration in Java.

This, therefore, works:

import java.util.HashMap;

public class StaticHashMapTest {

	private static class Pair {
		final String name;
		final int number;
		public Pair(String name, int number) {
			this.name = name;
			this.number = number;
		}
	}
	private final static HashMap constants = new HashMap();
	static
	{
		constants.put("A", new Pair("The Letter A", 123));
		constants.put("B", new Pair("The Letter B", 456));
		constants.put("C", new Pair("The Letter C", 789));
	}
	/* Rest of your class that needs to know the consts */
}

And that's Java for you.


Tethering no Linux com celular Nokia, conectando no 3G da TIM

E eis que consegui conectar o notebook à internet usando o celular Nokia (N85) e um cabo USB. (Ok, tive que catar instruções lendo no browserzinho do celular, mas rolou!)

Condensando aqui as instruções para facilitar minha vida da próxima vez:

1) Configurar o celular para conectar em modo “PC Suite” (normalmente eu deixo em “Mass storage”). No celular: Tools → Settings → Connection→ USB → USB Connection Mode: “PC Suite”

2) Plugar o celular na USB. Devem aparecer linhas mais ou menos assim no log do kernel (/var/log/kernel, dmesg)

usb 2-1.2: new high speed USB device using ehci_hcd and address 5
usb 2-1.2: New USB device found, idVendor=0421, idProduct=0094
usb 2-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-1.2: Product: N85
usb 2-1.2: Manufacturer: Nokia
usb 2-1.2: SerialNumber: 356808020426058
usb 2-1.2: configuration #1 chosen from 1 choice
cdc_acm 2-1.2:1.1: ttyACM0: USB ACM device
usbcore: registered new interface driver cdc_acm
cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters
NET: Registered protocol family 35
cdc_phonet: probe of 2-1.2:1.12 failed with error -22
usbcore: registered new interface driver cdc_phonet
usbcore: registered new interface driver cdc_ether
usb 2-1.2: bad CDC descriptors
usbcore: registered new interface driver rndis_host
usb 2-1.2: bad CDC descriptors
usbcore: registered new interface driver rndis_wlan

O principal ali é o “ttyACM0”, que indica que criou o device. Conferir que existe agora um arquivo /dev/ttyACM0

3) Arquivo /etc/ppp/peers/tether:

ttyACM0 460800 crtscts
connect '/usr/sbin/chat -v -f /etc/ppp/chat-tether'
noauth

O nome “tether” é arbitrário, pode ser qualquer um (será usado abaixo), mas o pppd parece realmente querer os arquivos no diretório /etc/ppp/peers.

4) Arquivo /etc/ppp/chat-tether:

TIMEOUT 5
ECHO ON
ABORT BUSY
ABORT ERROR
ABORT 'NO CARRIER'
ABORT VOICE
ABORT 'NO DIALTONE'
ABORT 'NO DIAL TONE'
ABORT 'NO ANSWER'
ABORT DELAYED
TIMEOUT 12
'' ATZ
OK AT+CGDCONT=1,"IP","tim.br"
OK ATD*99#
CONNECT ''

Note a APN da operadora TIM ali. Para outras operadoras, mudar ali de acordo (gprs.oi.com.br, claro.com.br, zap.vivo.com.br).

O nome do arquivo deve ser o mesmo referenciado dentro do arquivo /etc/ppp/peers/tether acima.

5) Rodar: sudo pppd call tether

Se tudo for bem, aparecerá algo assim no /var/log/messages:

Jul 16 21:24:32 (none) pppd[4746]: pppd 2.4.4 started by root, uid 0
Jul 16 21:24:33 (none) chat[4747]: timeout set to 5 seconds
Jul 16 21:24:33 (none) chat[4747]: abort on (BUSY)
Jul 16 21:24:34 (none) chat[4747]: abort on (ERROR)
Jul 16 21:24:34 (none) chat[4747]: abort on (NO CARRIER)
Jul 16 21:24:34 (none) chat[4747]: abort on (VOICE)
Jul 16 21:24:34 (none) chat[4747]: abort on (NO DIALTONE)
Jul 16 21:24:34 (none) chat[4747]: abort on (NO DIAL TONE)
Jul 16 21:24:34 (none) chat[4747]: abort on (NO ANSWER)
Jul 16 21:24:34 (none) chat[4747]: abort on (DELAYED)
Jul 16 21:24:34 (none) chat[4747]: timeout set to 12 seconds
Jul 16 21:24:34 (none) chat[4747]: send (ATZ^M)
Jul 16 21:24:34 (none) chat[4747]: expect (OK)
Jul 16 21:24:34 (none) chat[4747]: ATZ^M^M
Jul 16 21:24:34 (none) chat[4747]: OK
Jul 16 21:24:34 (none) chat[4747]:  -- got it
Jul 16 21:24:34 (none) chat[4747]: send (AT+CGDCONT=1,"IP","tom.br"^M)
Jul 16 21:24:34 (none) chat[4747]: expect (OK)
Jul 16 21:24:34 (none) chat[4747]: ^M
Jul 16 21:24:34 (none) chat[4747]: AT+CGDCONT=1,"IP","tom.br"^M^M
Jul 16 21:24:34 (none) chat[4747]: OK
Jul 16 21:24:34 (none) chat[4747]:  -- got it
Jul 16 21:24:34 (none) chat[4747]: send (ATD*99#^M)
Jul 16 21:24:34 (none) chat[4747]: expect (CONNECT)
Jul 16 21:24:34 (none) chat[4747]: ^M
Jul 16 21:24:34 (none) chat[4747]: ATD*99#^M^M
Jul 16 21:24:34 (none) chat[4747]: CONNECT
Jul 16 21:24:34 (none) chat[4747]:  -- got it
Jul 16 21:24:34 (none) chat[4747]: send (^M)
Jul 16 21:24:34 (none) pppd[4746]: Serial connection established.
Jul 16 21:24:34 (none) pppd[4746]: Using interface ppp0
Jul 16 21:24:34 (none) pppd[4746]: Connect: ppp0 <--> /dev/ttyACM0
Jul 16 21:24:37 (none) pppd[4746]: local  IP address 189.67.100.239
Jul 16 21:24:37 (none) pppd[4746]: remote IP address 10.6.6.6

E deve aparecer um ppp0 no ifconfig:

ppp0      Link encap:Point-to-Point Protocol
          inet addr:189.67.100.239  P-t-P:10.6.6.6  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:8938 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7998 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:7405264 (7.0 Mb)  TX bytes:1018670 (994.7 Kb)

6) Estabelecer o default gateway: sudo route add default gw 10.6.6.6

Conferir com o comando route:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.6.6.6        *               255.255.255.255 UH    0      0        0 ppp0
default         10.6.6.6        0.0.0.0         UG    0      0        0 ppp0

7) Configurar o DNS (por exemplo, com o DNS público do Google). Arquivo /etc/resolv.conf:

nameserver 8.8.8.8

Feito isso, o acesso à internet deve estar funcionando normalmente no computador!