Логин:   Пароль:






Новости
Рассылки
Форум
Поиск


Java
- Апплеты
- Вопрос-ответ
- Классы
- Примеры
- Руководства
- Статьи
- IDE
- Словарь терминов
- Скачать

Мобильная Java
- Игры
- Примеры
- Статьи
- WAP, WML и пр.

JavaScript
- Вопрос-ответ
- Примеры
- Статьи

Веб-мастеринг
- HTML
- CSS
- SSI

Разминка для ума
Проекты
Книги
Ссылки
Программы
Юмор :)




Rambler's Top100
Rambler's Top100

Java: СтатьиМодификация открытого кода пакета apache xml-rpc в Java

Модификация открытого кода пакета apache xml-rpc в Java

Для языка Java существует огромное количество пакетов для самых разных целей. Большинство из них распространяется с открытым кодом. Именно это мы используем для модификации rpc пакета под себя.

RPC-Remote Procedures Call. Удаленный вызов процедур. Типа клиент связывается с сервером, и вызывает с его компа нужные процедуры. Удобно и быстро.

XML-RPC – тот же RPC, но в качестве языка запросов/ответов используется XML. Удобно, т.к. XML-парсеров (проги такие, синтаксис XML на структуры делят—одни строят деревья, другие построчно) сейчас пруд-пруди. Кроме того, удобочитаемо(но нам это пока по боку).

Пакет xml-rpc для Java лежит на сайте http://jakarta.apache.org

Работать будем в IDE Eclipse, хотя это лично мой выбор.

Вначале пару слов о самом пакете.

Сервер создаётся так:
В функции main:


WebServer server = new WebServer(8080,InetAddress.getLocalHost());
server.addHandler("sample", new RPCServer());
server.start();
Sample—это имя сервака.
Кроме того, в классе сервака надо создать public-метод, вызываемый клиентом.
Пусть это будет такое:

public String ServerDate()
    {
    	System.out.println("Client connected");
   	return new Date().toString();
  	            
    }

Метод возвращает дату и время на серваке.
Вот обращение клиента к функции ServerDate на сервере


private final static String server_url =
            "http://localhost:8080";
XmlRpcClient server = new XmlRpcClient(server_url);
Vector params = new Vector();
              
long start=System.currentTimeMillis();
String result =(String) server.execute("sample.ServerDate", params);
System.out.println("Server`s date is"+result);

В общем в доках к пакету это всё можно вычитать. И о параметрах и о возвращаемых результатах. Мы поговорим о другом. Представьте ситуацию—к rpc-серверу коннектится клиент и надо знать его данные—ip+port. В пакете нет функции , которая нам бы их предоставила. Что ж, придётся создать её. Для этого будем модифицировать код пакета. Чтобы не перекомпилировать пакет apache xml-rpc, мы пойдём другим путём: создадим свой класс на базе WebServer из пакета. Все функции, которые нас устраивали — оставим, а остальные—бесщадно перелопатим. Приступим.

Для начала надо в своей IDE указать путь к самой библиотеке и исподникам пакета org.apache.xmlrpc (не забудьте скачать его себе). Далее указан примерный ход действий.

1. Если пакет уже добавлен в пути проекта. В ECLIPSE слева в Package Explorer правой кнопкой на пакете xml-rpc, properties—прописываем путь—получили доступ к исходникам пакета.
2. Создаём в нашем проекте класс MyServer производный от WebServer
3. Прописываем в нём 2 метода


public MyServer(int port, java.net.InetAddress addr)
 	{
 		super(port,addr);
p_address=addr;
 		p_port=port;
 	}
 	public ServerSocket GetServerSocket()
 	{
 		
 		return serverSocket;
 	}

Первый метод-конструктор—необходим для динамического создания сервера.
Второй метод – для доступа к сокету сервера (в WebServer он защищён).
Остальные методы-при необходимости наследуйте и дополняйте (мы этим также займёмся)

4. Открываем в исходниках пакета xml-rpc код метода run() класса WebServer и находим там строку (она на 19 строк ниже от начала метода run()) Socket socket = serverSocket.accept(); Этот самый socket—это ни что иное, как сокет со стороны клиента. Зная его, мы уже имеем инфу о клиенте (например его InetAdress). В оригинальном классе WebServer этот клиентский сокет также защищён. Это надо исправить. Для этого в класс MyServer добавляем метод run()—попросту вчистую копируем из WebServer (любимая моя CTRL+C & CTRL+V) но, внимание, строку


Socket socket = serverSocket.accept();
заменим на

socket = serverSocket.accept();
а в поля класса MyServer добавим переменную

Socket socket;
InetAddress p_address;
int p_port;
Однако это ещё не все. Также надо передрать и переделать из WebServer методы:

setupServerSocket
releaseRunner
getRunner—обзываем getMyRunner

Коды этих методов в переделанном виде: RPCServer.zip, RPCClient.zip.
Также передираем внутренние классы Runner, Connection. Класс Runner обзываем MyRunner. Все имена Runner заменим на MyRunner.

Кроме того, создаём новый класс MyServerInputStream. Его содержимое—просто калька с org.apache.xmlrpc.ServerInputStream, но с отличиями:
А. убираем директиву package
Б. объявляем класс как public
В. Все ServerInputStream заменяем на MyServerInputStream в пределах самого класса и в методе run() класса Connection

Также импортируем пакеты вначале


import java.io.*;
import java.util.*;
import java.net.*;
import org.apache.xmlrpc.*;
import java.net.*;
import java.io.*;
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpc;

5. Что пока имеем? Калька с класса WebServer, которая, в отличие от данного, предоставляет доступ к сокетам сервера и клиента. Это плохо из-за нарушения инкапсуляции (когда служебные переменные недоступны извне - для безопасности). Но в тоже время хорошо благодаря возможности подогнать мощность пакета под себя — ведь теперь, зная адрес клиента можно его, например, кэшировать, или что-ещё.

Сам код на серваке теперь выглядит чуть иначе:


MyServer server = new MyServer(8080,InetAddress.getLocalHost());
                server.addHandler("sample", new RPCServer());
                server.start();
                
System.out.println("SERVER STARTED");

public String ServerDate()
    {
    		System.out.println("Client connected");
 			ServerSocket ss=server.GetServerSocket();
 			
 			
 	 		System.out.println(server.socket.getInetAddress());
 	 		System.out.println(server.socket.getPort());
 	 	
    		return new Date().toString();
  	            
    }

Как видите — теперь уже мы полностью видим клиента по его сокету. Но это мелочь. Главное то, что, продолжая копать исходники пакета, можно полностью переделать его под себя. Разумеется, сам оригинальный пакет вы сможете выучить благодаря этому на 100%.

P.S. Основное неудобство в наследовании пакета — необходимость переделывать абсолютно неинтересные для нас методы (например класс ServerInputStream, Runner, Connection). Если таких методов у вас накопится очень много и их переделка вас затруднит, то используйте альтернативу—изменяйте сам код пакета. Но надо помнить: если вы изменили/убрали общедоступные поля/сигнатуру методов, то придётся изменять и те классы, которые эти методы вызывают. Поэтому никогда не удаляйте ничего в классах пакета, что могло бы отразится извне (не меняйте, например, количество аргументов в методе, лучше создайте его перегруженную копию). И главное, имейте всегда резервную копию пакета, с которым работаете.

В общем, при желании можно всё там перелопатить. Главное запомнить одну вещь—работа с чужим открытым кодом — бесценная вещь.

Автор: _cYclope

Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 11

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/books/show2b.php on line 30
Узнай о чем ты на самом деле сейчас думаешь тут.


[an error occurred while processing this directive]



Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 91

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/news/worldnews.php on line 95