乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Openfire插件開(kāi)發(fā)心得:基于XMPP實(shí)現(xiàn)類(lèi)Twitter

       WindySky 2016-02-18

      Openfire是XMPP協(xié)議最好的服務(wù)器軟件。最近修改了一個(gè)插件實(shí)現(xiàn)了類(lèi)Twitter功能,發(fā)出來(lái)分享

      Get started

      我用的是debian作為Openfire服務(wù)器
      下載Openfire,安裝JRE(Jaav運(yùn)行庫(kù)),把Openfire跑起來(lái)
      下載JDK 1.5,安裝到/opt/jdk1.5.0_14
      下載openfire源碼,準(zhǔn)備編譯。當(dāng)時(shí)我安裝的oenfire是3.4.1所以源碼也下載的是3.4.1版本。用tar -zxvf openfire_src_3_4_1.tar.gz解壓到/opt/openfire_src

      配置系統(tǒng)環(huán)境,聲明JDK的環(huán)境變量export JAVA_HOME=/opt/jdk1.5.0_14/
      下載ant編譯工具,apt-get install ant 呵呵,debian就是爽。

      編寫(xiě)Openfire插件

      這是一個(gè)及其痛苦的過(guò)程,由于我不會(huì)Java,所以報(bào)了本《Thinking in Java》然后對(duì)照著SUN的官方文檔邊學(xué)邊寫(xiě),最后還是鼓搗出來(lái)了,呵呵
      我的插件是基于Stefan Reuter的userstatus插件修改的

      User Status Plugin is a plugin for the Openfire XMPP server to save the user status to the database.

      This plugin automatically saves the last status (presence, IP address, logon and logoff time) per user and resource to userStatus table in the Openfire database.

      Optionally you can archive user status entries (IP address, logon and logoff time) for a specified time. History entries are stored in the userStatusHistory table. The settings for history archiving can be configured on the "User Status Settings" page that you'll find on the "Server" tab of the Openfire Admin Console.

      目錄結(jié)構(gòu)有些變化,我的修改版可以在這里下載 userstatus.rar
      目錄結(jié)構(gòu)是:

      
      E:\\DORMFORCE\\NUTALK\\OPENFIRE\\EST\\USER-STATUS
      │  changelog.html
      │  plugin.xml
      │  readme.html
      │
      ├─i18n
      │      user-status_i18n.properties
      │
      ├─META-INF
      │  │  MANIFEST.MF
      │  │
      │  └─maven
      │      └─com.reucon.openfire.plugins
      │          └─user-status
      │                  pom.properties
      │                  pom.xml
      │
      ├─src
      │  ├─database
      │  │      user-status_mysql.sql
      │  │
      │  ├─java
      │  │  └─com
      │  │      └─reucon
      │  │          └─openfire
      │  │              └─plugins
      │  │                  └─userstatus
      │  │                          UserStatusPlugin.java
      │  │
      │  └─web
      │          user-status-settings.jsp
      │
      └─web
      │  user-status-settings.jsp
      │
      └─WEB-INF
      web.xml
      
      

      修改了user-status_mysql.sql ,在userStatus表增加一個(gè)字段status TEXT,,然后修改UserStatusPlugin.java的源碼了
      [code:java]
      package com.reucon.openfire.plugins.userstatus;

      import org.jivesoftware.database.DbConnectionManager;
      import org.jivesoftware.database.SequenceManager;
      import org.jivesoftware.openfire.SessionManager;
      import org.jivesoftware.openfire.XMPPServer;
      import org.jivesoftware.openfire.container.Plugin;
      import org.jivesoftware.openfire.container.PluginManager;
      import org.jivesoftware.openfire.event.SessionEventDispatcher;
      import org.jivesoftware.openfire.event.SessionEventListener;
      import org.jivesoftware.openfire.session.ClientSession;
      import org.jivesoftware.openfire.session.Session;
      import org.jivesoftware.openfire.user.PresenceEventDispatcher;
      import org.jivesoftware.openfire.user.PresenceEventListener;
      import org.jivesoftware.util.*;
      import org.xmpp.packet.Presence;
      import org.xmpp.packet.JID;

      import java.io.File;
      import java.net.UnknownHostException;
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.SQLException;
      import java.util.Date;
      import java.util.Map;
      //by est
      import java.net.URL;
      import java.net.URLEncoder;
      import java.net.HttpURLConnection;

      /**
      * UserStatus plugin for Openfire. MOD by est
      */
      public class UserStatusPlugin implements Plugin, PropertyEventListener, SessionEventListener, PresenceEventListener
      {
      private static final int SEQ_ID = 510;

      private static final String ADD_USER_STATUS =
      "Insert INTO userStatus (username, resource, online, lastIpAddress, lastLoginDate) " +
      "VALUES (?, ?, 1, ?, ?)";

      private static final String UPDATE_USER_STATUS =
      "UPDATE userStatus SET online = 1, lastIpAddress = ?, lastLoginDate = ? " +
      "Where username = ? AND resource = ?";

      private static final String SET_PRESENCE =
      "UPDATE userStatus SET presence = ?, status = ? Where username = ? AND resource = ?"; //By est

      private static final String SET_OFFLINE =
      "UPDATE userStatus SET online = 0, lastLogoffDate = ? Where username = ? AND resource = ?";

      private static final String SET_ALL_OFFLINE =
      "UPDATE userStatus SET online = 0";

      private static final String ADD_USER_STATUS_HISTORY =
      "Insert INTO userStatusHistory (historyID, username, resource, lastIpAddress," +
      "lastLoginDate, lastLogoffDate) VALUES (?, ?, ?, ?, ?, ?)";

      private static final String DELETE_OLD_USER_STATUS_HISTORY =
      "DELETE From userStatusHistory Where lastLogoffDate < ?"; public static final String HISTORY_DAYS_PROPERTY = "user-status.historyDays"; public static final int DEFAULT_HISTORY_DAYS = -1; /** * Number of days to keep history entries.

      * 0 for now history entries, -1 for unlimited.
      */
      private int historyDays = DEFAULT_HISTORY_DAYS;

      public static final String strSynXCallHubUrlFormat = "http://www2./services/callhub.php?SynXPwd=___&username=%s&status=%s";

      public void initializePlugin(PluginManager manager, File pluginDirectory)
      {
      Connection con = null;
      PreparedStatement pstmt = null;

      historyDays = JiveGlobals.getIntProperty(HISTORY_DAYS_PROPERTY, DEFAULT_HISTORY_DAYS);
      PropertyEventDispatcher.addListener(this);

      try
      {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(SET_ALL_OFFLINE);
      pstmt.executeUpdate();
      }
      catch (SQLException e)
      {
      Log.error("Unable to clean up user status", e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }

      for (ClientSession session : SessionManager.getInstance().getSessions())
      {
      sessionCreated(session);
      }

      SessionEventDispatcher.addListener(this);
      PresenceEventDispatcher.addListener(this);
      }

      public void destroyPlugin()
      {
      PresenceEventDispatcher.removeListener(this);
      SessionEventDispatcher.removeListener(this);
      }

      public void sessionCreated(Session session)
      {
      Connection con = null;
      PreparedStatement pstmt = null;
      int rowsUpdated = 0;

      if (!XMPPServer.getInstance().getUserManager().isRegisteredUser(session.getAddress()))
      {
      return;
      }

      try
      {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(UPDATE_USER_STATUS);
      pstmt.setString(1, getHostAddress(session));
      pstmt.setString(2, StringUtils.dateToMillis(session.getCreationDate()));
      pstmt.setString(3, session.getAddress().getNode());
      pstmt.setString(4, session.getAddress().getResource());
      rowsUpdated = pstmt.executeUpdate();
      }
      catch (SQLException e)
      {
      Log.error("Unable to update user status for " + session.getAddress(), e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }

      if (rowsUpdated == 0)
      {
      try
      {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(ADD_USER_STATUS);
      pstmt.setString(1, session.getAddress().getNode());
      pstmt.setString(2, session.getAddress().getResource());
      pstmt.setString(3, getHostAddress(session));
      pstmt.setString(4, StringUtils.dateToMillis(session.getCreationDate()));
      pstmt.executeUpdate();
      }
      catch (SQLException e)
      {
      Log.error("Unable to Insert user status for " + session.getAddress(), e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }
      }
      }

      public void sessionDestroyed(Session session)
      {
      Connection con = null;
      PreparedStatement pstmt = null;
      final Date logoffDate;

      if (!XMPPServer.getInstance().getUserManager().isRegisteredUser(session.getAddress()))
      {
      return;
      }

      logoffDate = new Date();
      try
      {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(SET_OFFLINE);
      pstmt.setString(1, StringUtils.dateToMillis(logoffDate));
      pstmt.setString(2, session.getAddress().getNode());
      pstmt.setString(3, session.getAddress().getResource());
      pstmt.executeUpdate();
      }
      catch (SQLException e)
      {
      Log.error("Unable to update user status for " + session.getAddress(), e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }

      // write history entry
      if (historyDays != 0)
      {
      try
      {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(ADD_USER_STATUS_HISTORY);
      pstmt.setLong(1, SequenceManager.nextID(SEQ_ID));
      pstmt.setString(2, session.getAddress().getNode());
      pstmt.setString(3, session.getAddress().getResource());
      pstmt.setString(4, getHostAddress(session));
      pstmt.setString(5, StringUtils.dateToMillis(session.getCreationDate()));
      pstmt.setString(6, StringUtils.dateToMillis(logoffDate));
      pstmt.executeUpdate();
      }
      catch (SQLException e)
      {
      Log.error("Unable to add user status history for " + session.getAddress(), e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }
      }

      deleteOldHistoryEntries();
      }

      public void anonymousSessionCreated(Session session)
      {
      // we are not interested in anonymous sessions
      }

      public void anonymousSessionDestroyed(Session session)
      {
      // we are not interested in anonymous sessions
      }

      public void availableSession(ClientSession session, Presence presence)
      {
      updatePresence(session, presence);
      }

      public void unavailableSession(ClientSession session, Presence presence)
      {
      updatePresence(session, presence);
      }

      public void presencePriorityChanged(ClientSession session, Presence presence)
      {
      updatePresence(session, presence);
      }

      public void presenceChanged(ClientSession session, Presence presence)
      {
      updatePresence(session, presence);
      }

      public void subscribedToPresence(JID subscriberJID, JID authorizerJID)
      {
      // we are not interested in subscription updates
      }

      public void unsubscribedToPresence(JID unsubscriberJID, JID recipientJID)
      {
      // we are not interested in subscription updates
      }

      public void propertySet(String property, Map params)
      {
      if (HISTORY_DAYS_PROPERTY.equals(property))
      {
      final Object value = params.get("value");
      if (value != null)
      {
      try
      {
      historyDays = Integer.valueOf(value.toString());
      }
      catch (NumberFormatException e)
      {
      historyDays = DEFAULT_HISTORY_DAYS;
      }
      deleteOldHistoryEntries();
      }
      }
      }

      public void propertyDeleted(String property, Map params)
      {
      if (HISTORY_DAYS_PROPERTY.equals(property))
      {
      historyDays = DEFAULT_HISTORY_DAYS;
      deleteOldHistoryEntries();
      }
      }

      public void xmlPropertySet(String property, Map params)
      {
      // we don't use xml properties
      }

      public void xmlPropertyDeleted(String property, Map params)
      {
      // we don't use xml properties
      }

      private void updatePresence(ClientSession session, Presence presence)
      {
      Connection con = null;
      PreparedStatement pstmt = null;
      String presenceText="";
      String statusText="";

      if (!XMPPServer.getInstance().getUserManager().isRegisteredUser(session.getAddress()))
      {
      return;
      }

      if (Presence.Type.unavailable.equals(presence.getType()))
      {
      presenceText = presence.getType().toString();
      }
      else if (presence.getShow() != null)
      {
      presenceText = presence.getShow().toString();
      }
      else if (presence.isAvailable())
      {
      presenceText = "available";
      }
      else
      {
      return;
      }

      try
      {
      statusText = presence.getStatus();
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(SET_PRESENCE);
      pstmt.setString(1, presenceText);
      pstmt.setString(2, statusText); //By est, following numbers are added by 1.
      pstmt.setString(3, session.getAddress().getNode());
      pstmt.setString(4, session.getAddress().getResource());
      pstmt.executeUpdate();

      /*SynX CallHub by est*/
      URL url = new URL(String.format(strSynXCallHubUrlFormat,URLEncoder.encode( session.getAddress().getNode() ), URLEncoder.encode( statusText, "UTF-8" )));
      HttpURLConnection httpUrl = (HttpURLConnection)url.openConnection();
      httpUrl.connect();

      }
      catch (Exception e)
      {
      Log.error("Unable to update presence for " + session.getAddress(), e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }
      }

      private void deleteOldHistoryEntries()
      {
      Connection con = null;
      PreparedStatement pstmt = null;

      if (historyDays > 0)
      {
      final Date deleteBefore;

      deleteBefore = new Date(System.currentTimeMillis() - historyDays * 24L * 60L * 60L * 1000L);

      try
      {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(DELETE_OLD_USER_STATUS_HISTORY);
      pstmt.setString(1, StringUtils.dateToMillis(deleteBefore));
      pstmt.executeUpdate();
      }
      catch (SQLException e)
      {
      Log.error("Unable to delete old user status history", e);
      }
      finally
      {
      DbConnectionManager.closeConnection(pstmt, con);
      }
      }
      }

      private String getHostAddress(Session session)
      {
      try
      {
      return session.getHostAddress();
      }
      catch (UnknownHostException e)
      {
      return "";
      }
      }
      }
      [/code]
      代碼中 session.getAddress().getNode()); 的意思是獲得當(dāng)前的XMPP用戶(hù)名。XMPP協(xié)議規(guī)定,用戶(hù)名分三部份:
      someone @ domain.tld / clientname
       ^     ^      ^
      用戶(hù)名node 域domain 客戶(hù)端名字,又叫資源resource,用于區(qū)分一個(gè)ID多處同時(shí)登錄

      也就是說(shuō),用戶(hù)在XMPP客戶(hù)端更新了自己的status,Openfire會(huì)調(diào)用http://www2./services/callhub.php?SynXPwd=___&username=%s&status=%s 一次??梢园堰@個(gè)地址理解為一個(gè)WebService。例如我我們DormForce的官方客戶(hù)端里更新我的狀態(tài)
      14.jpg
      Openfire收到后會(huì)自動(dòng)調(diào)用這個(gè)網(wǎng)址:http://www2./services/callhub.php?SynXPwd=___&username=est&status=%E5%8F%AF%E4%BB%A5%E6%8A%8A%4E%55%54%61%6C%6B%E5%BD%93%74%77%69%74%74%65%72%E7%94%A8%E4%BA%86

      那么我們?cè)?code>callhub.php里編寫(xiě)任意代碼了,比如我們可以自己實(shí)現(xiàn)一個(gè)類(lèi)似Twitter的應(yīng)用,也可以直接調(diào)用API把消息發(fā)送到真實(shí)的Twitter或則國(guó)內(nèi)的fanfou

      編譯

      首先刪除 /opt/openfire_src/src/plugins/下的不需要的插件,然后把user-status文件夾上傳到plugins目錄下
      user-status/WEB-INF 復(fù)制到根 / 。也就是 /WEB-INF/ 。不要問(wèn)我為什么,我也不知道為什么,反正不這么做就是編譯不成功。
      然后cd /opt/openfire_src/build
      ant clean && ant plugins

      幾分鐘過(guò)后如果顯示BUILD SUCCESSFUL那么說(shuō)明編譯成功了!

      部署插件

      編譯好的插件在哪里呢?在/opt/openfire_src/target/openfire/plugins/user-status.jar
      上傳user-status.jar到openfire的安裝目錄下的plugins文件夾,到Openfire管理界面里看看,如果這個(gè)插件已經(jīng)啟用,那么說(shuō)明我們的twitter平臺(tái)已經(jīng)搭建起來(lái)了

      參考

      基本是一些e文文檔
      Openfire接口文檔 http://www./builds/openfire/docs/latest/documentation/javadoc/index.html
      JavaDoc 1.5 http://java./j2se/1.5.0/docs/api/
      user-status插件及其源碼 http://maven./public/com/reucon/openfire/plugins/user-status/1.0.2/
      Openfire開(kāi)發(fā)指南 http://www./projects/openfire/documentation.jsp

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多