📄 x7229.htm
字号:
an <TT
CLASS="LITERAL"
>InfoQueryBuilder</TT
> to construct the
<TT
CLASS="LITERAL"
><iq/></TT
> envelope and an
<TT
CLASS="LITERAL"
>IQAuthBuilder</TT
> to construct the
<TT
CLASS="LITERAL"
><query/></TT
> content.</P
><P
>Taking the code step-by-step, we create or declare each
of the three things <I
CLASS="EMPHASIS"
>iqb</I
>,
<I
CLASS="EMPHASIS"
>iq</I
>, and <I
CLASS="EMPHASIS"
>iqAuthb</I
>
in <A
HREF="x7229.htm#JABTDG-CH-7-FIG-3"
>Figure 7-3</A
>:</P
><P
><PRE
CLASS="SCREEN"
> InfoQueryBuilder iqb=new InfoQueryBuilder();
InfoQuery iq;
IQAuthBuilder iqAuthb=new IQAuthBuilder();</PRE
></P
><DIV
CLASS="FIGURE"
><A
NAME="JABTDG-CH-7-FIG-3"
></A
><P
><B
>Figure 7-3. Creating the authorization packet</B
></P
><PRE
CLASS="SCREEN"
>
+--+
|iq|--------+
+--+ |
|
v
[4]
+- build()
+---+ |
|iqb|--+- [3b] addExtension() -----------+
+---+ | |
| +- [1] setType() ------+ |
| | | +-------+
| +------------v----------|-------------+ +-- represents --|iqAuthb|
+- represents -> <iq type='set'> v | | +-------+
| +--------------------------------:-v-+ |
| | <query xmlns='jabber:iq:auth'> : | [2] |
| | <username>myserver</username>: <------ setUsername() -+
| | <password>secret</password> : <------ setPassword() -+
| | <resource>alive</resource> : <------ setResource() -+
| | </query> : | |
| +--------------------------------:--- build() -+
| </iq> | [3a]
+-------------------------------------+
</PRE
></DIV
><P
>There are numbered steps in <A
HREF="x7229.htm#JABTDG-CH-7-FIG-3"
>Figure 7-3</A
>;
these follow what happens in the rest of the authentication
preparation:</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>Step [1] Set the <TT
CLASS="LITERAL"
>type</TT
> attribute of
the IQ</DT
><DD
><P
>We call the <TT
CLASS="LITERAL"
>setType()</TT
> method on our
<I
CLASS="EMPHASIS"
>iqb</I
> object that represents our outer
IQ envelope to set the value of the <TT
CLASS="LITERAL"
>type</TT
>
attribute:</P
><P
><PRE
CLASS="SCREEN"
> iqb.setType("set"); </PRE
></P
></DD
><DT
>Step [2] Set the values for the parts of the authorization
section of the element</DT
><DD
><P
>Having constructed our <I
CLASS="EMPHASIS"
>iqAuthb</I
> object,
which represents the
<TT
CLASS="LITERAL"
><query/></TT
> portion of our element,
we fill the values with these calls:</P
><P
><PRE
CLASS="SCREEN"
> iqAuthb.setUsername(USER);
iqAuthb.setPassword(PASSWORD);
iqAuthb.setResource(RESOURCE); </PRE
></P
></DD
><DT
>Step [3] Crystallize <TT
CLASS="LITERAL"
>iqAuthb</TT
> and add
it to the IQ object</DT
><DD
><P
>Once the values inside the authorization
<TT
CLASS="LITERAL"
><query/></TT
>
tag are set, we can call the <TT
CLASS="LITERAL"
>build()</TT
> method on the
object representing that tag (<I
CLASS="EMPHASIS"
>iqAuthb</I
>) to generate
an extension object—to <I
CLASS="EMPHASIS"
>crystallize</I
> the tag—
that can then be attached as an extension to the <I
CLASS="EMPHASIS"
>iqb</I
>
object using the <TT
CLASS="LITERAL"
>addExtension()</TT
> method:</P
><P
><PRE
CLASS="SCREEN"
> try
{
iqb.addExtension(iqAuthb.build());
}
... </PRE
></P
></DD
><DT
>Step [4] Crystallize <I
CLASS="EMPHASIS"
>iqb</I
> and assign it
to the <I
CLASS="EMPHASIS"
>iq</I
> object</DT
><DD
><P
>In the same way that we crystallized the authorization
<TT
CLASS="LITERAL"
><query/></TT
>
tag, we can crystallize the whole element and assign it to
<I
CLASS="EMPHASIS"
>iq</I
>:</P
><P
><PRE
CLASS="SCREEN"
> try
{
//build the full InfoQuery packet
iq=(InfoQuery)iqb.build();
}
... </PRE
></P
></DD
></DL
></DIV
><P
>Once we've constructed our authorization element, now held as
the <I
CLASS="EMPHASIS"
>iq</I
> object, we can send it down the stream
to the Jabber server with the <TT
CLASS="LITERAL"
>send()</TT
> method of
the ConnectionBean object <TT
CLASS="LITERAL"
>cb</TT
>:</P
><P
><PRE
CLASS="SCREEN"
> cb.send(iq); </PRE
></P
><P
>Finally, once we've authenticated, we can construct our presence
packet and send it.
<A
NAME="AEN7450"
HREF="#FTN.AEN7450"
>[3]</A
>
This is achieved using the same technique as before. We construct a
new object to represent the presence packet denoting general
availability—<TT
CLASS="LITERAL"
><presence/></TT
>:</P
><P
><PRE
CLASS="SCREEN"
> PresenceBuilder pb=new PresenceBuilder(); </PRE
></P
><P
>In this case, there are no namespace-qualified extensions to add to our
<TT
CLASS="LITERAL"
><presence/></TT
> element, but we do want to
add the IP address that was passed into the script and available in
<TT
CLASS="LITERAL"
>argv[0]</TT
>. We can use the <TT
CLASS="LITERAL"
>setStatus()</TT
>
method on our presence object to set the optional
<TT
CLASS="LITERAL"
><status/></TT
> to contain that IP address:</P
><P
><PRE
CLASS="SCREEN"
> pb.setStatus(argv[0]); </PRE
></P
><P
>After this, we can go ahead and crystallize the element, which will
look like this:</P
><P
><PRE
CLASS="SCREEN"
><presence>
<status>123.45.67.89</status>
</presence></PRE
></P
><P
>After the crystallization with the <TT
CLASS="LITERAL"
>build()</TT
> call,
we send it down the stream in the same way that as the authorization
<TT
CLASS="LITERAL"
><iq/></TT
>
element:</P
><P
><PRE
CLASS="SCREEN"
> try
{
cb.send(pb.build());
}
catch (InstantiationException e)
{
System.out.println("Fatal Error on Presence object build:");
System.out.println(e.toString());
return;
} </PRE
></P
><P
>As for each of the <TT
CLASS="LITERAL"
>build()</TT
> calls, we must
trap a possible exception that <TT
CLASS="LITERAL"
>build()</TT
> throws
if it can't complete (for example, due to lack of information). This
is the <I
CLASS="EMPHASIS"
>InstantiationException</I
>.</P
><P
>We can see the results of <I
CLASS="EMPHASIS"
>myserver</I
> sending
such an information-laden
<TT
CLASS="LITERAL"
><presence/></TT
> element to
<I
CLASS="EMPHASIS"
>dj</I
> in
<A
HREF="x7229.htm#JABTDG-CH-7-FIG-4"
>Figure 7-4</A
>. As the server connects to the
Internet, the Java script is started via the <TT
CLASS="LITERAL"
>ip-up</TT
>
script and relays the assigned IP address which is shown in Jarl's
status bar as the availability information reaches <I
CLASS="EMPHASIS"
>dj</I
>'s
client.</P
><DIV
CLASS="FIGURE"
><A
NAME="JABTDG-CH-7-FIG-4"
></A
><P
><B
>Figure 7-4. <I
CLASS="EMPHASIS"
>myserver</I
> becoming available and relaying
its IP address</B
></P
><P
><IMG
SRC="CH-7-FIG-4.jpg"></P
></DIV
><P
>All that remains for the script to do now is to hang around. While
the XML stream to the Jabber server remains, and the connection is
not broken, our availabiliy will remain as it was as described by
the simple <TT
CLASS="LITERAL"
><presence/></TT
> element we
sent. So we simply go into a sort of hibernation. We have no hope of
escaping, but it should be taken care of by our <TT
CLASS="LITERAL"
>ip-down</TT
>
script as described earlier.</P
><P
><PRE
CLASS="SCREEN"
> while (true) {
try {
Thread.sleep(9999);
}
catch (InterruptedException e)
{
System.out.println("timeout!");
}
} </PRE
></P
><P
>In fact, when the <TT
CLASS="LITERAL"
>ip-down</TT
> script kills our script,
the socket connection will be closed, but there was no clean
disconnect—no <TT
CLASS="LITERAL"
><presence type='unavailable/></TT
>
was sent by the script to the Jabber server. In this case, the Jabber
server will
notice that the socket was closed, and generate an unavailable
presence element on behalf of the client. </P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="JABTDG-CH-7-SECT-2.3"
>The script in its entirety</A
></H2
><P
>Here's the script in its entirety. </P
><P
><PRE
CLASS="SCREEN"
>import org.jabber.jabberbeans.*;
import org.jabber.jabberbeans.Extension.*;
import java.net.InetAddress;
public class HostAlive
{
public static final String SERVER = "gnu.pipetree.com";
public static final String USER = "myserver";
public static final String PASSWORD = "secret";
public static final String RESOURCE = "alive";
public static void main(String argv[])
{
ConnectionBean cb=new ConnectionBean();
InetAddress addr;
try
{
cb.connect(addr=InetAddress.getByName(SERVER));
}
catch (java.net.UnknownHostException e)
{
//from getByName()
System.out.println("Cannot resolve " + SERVER + ":" + e.toString());
return;
}
catch (java.io.IOException e)
{
//from connect()
System.out.println("Cannot connect to " + SERVER);
return;
}
InfoQueryBuilder iqb=new InfoQueryBuilder();
InfoQuery iq;
IQAuthBuilder iqAuthb=new IQAuthBuilder();
iqb.setType("set");
iqAuthb.setUsername(USER);
iqAuthb.setPassword(PASSWORD);
iqAuthb.setResource(RESOURCE);
try
{
iqb.addExtension(iqAuthb.build());
}
catch (InstantiationException e)
{
//building failed ?
System.out.println("Fatal Error on Auth object build:");
System.out.println(e.toString());
System.exit(0);
}
try
{
//build the full InfoQuery packet
iq=(InfoQuery)iqb.build();
}
catch (InstantiationException e)
{
//building failed ?
System.out.println("Fatal Error on IQ object build:");
System.out.println(e.toString());
return;
}
cb.send(iq);
PresenceBuilder pb=new PresenceBuilder();
pb.setStatus(argv[0]);
try
{
cb.send(pb.build());
}
catch (InstantiationException e)
{
System.out.println("Fatal Error on Presence object build:");
System.out.println(e.toString());
return;
}
while (true) {
try {
Thread.sleep(9999);
}
catch (InterruptedException e)
{
System.out.println("timeout!");
}
} </PRE
></P
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN7325"
HREF="x7229.htm#AEN7325"
>[1]</A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>The parameters that are passed from <B
CLASS="COMMAND"
>pppd</B
> to the
<TT
CLASS="LITERAL"
>ip-up</TT
> script are:
<I
CLASS="EMPHASIS"
>interface-name</I
>,
<I
CLASS="EMPHASIS"
>tty-device</I
>,
<I
CLASS="EMPHASIS"
>speed</I
>,
<I
CLASS="EMPHASIS"
>local-link-local-address</I
>,
<I
CLASS="EMPHASIS"
>remote-link-local-address</I
>, and
<I
CLASS="EMPHASIS"
>ipparam</I
>. It's the
<I
CLASS="EMPHASIS"
>remote-link-local-address</I
> that we're interested
in here.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN7379"
HREF="x7229.htm#AEN7379"
>[2]</A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>We're not bothering in this example to ask the server for the
authentication methods it supports and are just going ahead
with a plaintext attempt.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN7450"
HREF="x7229.htm#AEN7450"
>[3]</A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>We're assuming our password is correct here, to keep this example
straightforward. If it isn't correct, there's not much we can do
at this point anyway.</P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x6950.htm"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.htm"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="x7499.htm"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>CVS notification</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c6941.htm"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Presence-sensitive CVS notification</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -