⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sync4jservlet.java

📁 实现了SyncML无线同步协议
💻 JAVA
字号:
/** * Copyright (C) 2003-2004 Funambol * *  This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */package sync4j.transport.http.server;import java.io.*;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.StringTokenizer;import java.util.logging.Logger;import java.util.logging.Level;import javax.naming.*;import javax.ejb.CreateException;import javax.ejb.EJBException;import javax.servlet.*;import javax.servlet.http.*;import sync4j.framework.core.Constants;import sync4j.framework.core.Util;import sync4j.framework.core.SyncML;import sync4j.framework.core.Sync4jException;import sync4j.framework.tools.Base64;import sync4j.framework.tools.WBXMLTools;import sync4j.framework.server.*;import sync4j.framework.transport.http.SyncHolder;import sync4j.framework.transport.http.SyncHolderCache;import sync4j.framework.protocol.ProtocolException;import org.apache.commons.lang.StringUtils;import org.jibx.runtime.*;import org.jibx.runtime.impl.*;/** *  Receives the HTTP request and does session management. * *  <b>Session Management</b> *  <p> *  If the url contains a parameter {PARAM_SESSION_ID}={SESSION_ID}, the session *  id is used to lookup in the <i>handlerCache</i> if there is already a *  <i>SyncHolder</i> associated with the given session id it is used to process *  the incoming request. Otherwise (either if the session parameter is not *  specified or not cached handler is found), a new session id is created and a *  new <i>SyncHolder</i> object is instantiated and stored in the cache.<br> *  The session id is created as followed: *  <p> *  <ol> *    <li> the first four bytes contains the IP address of the remote client *    <li> a dash ('-') is appended *    <li> the creation timestamp is appended *    <li> the resulting string is encoded base 64 *  </ol> *  Note that no session expiration is handled by this class. That is delegated *  to the <i>SyncHolderCache</i> object. * *  @author Stefano Fornari @ Funambol * *  @version $Id: Sync4jServlet.java,v 1.8 2004/05/28 16:15:14 luigiafassina Exp $ * */public final class Sync4jServlet extends javax.servlet.http.HttpServlet {        // --------------------------------------------------------------- Constants        public static final String LOG_NAME = "sync4j.transport.http";        public static final String PARAM_SESSION_ID       = "sid"                 ;    public static final String PARAM_SYNCHOLDER_CLASS = "sync-holder-class"   ;    public static final String PARAM_SESSION_TTL      = "session-time-to-live";    public static final String PARAM_SERVER_URI       = "server-uri"          ;        // ------------------------------------------------------------ Private data        private Logger log = Logger.getLogger(LOG_NAME);        private static String          syncHolderClass = null;    private static SyncHolderCache holderCache     = null;    private static String          serverUri       = null;        // ---------------------------------------------------------- Public methods        public void init() throws ServletException {        String value;        long timeToLive = 0;                ServletConfig config = getServletConfig();                value = config.getInitParameter(PARAM_SYNCHOLDER_CLASS);                if (StringUtils.isEmpty(value)) {            String msg = "The servlet configuration parameter "            + PARAM_SYNCHOLDER_CLASS            + " cannot be empty ("            + value            + ")"            ;            log(msg);            throw new ServletException(msg);        }        syncHolderClass = value;                value = config.getInitParameter(PARAM_SESSION_TTL);        if (!StringUtils.isEmpty(value)) {            try {                timeToLive = Long.parseLong(value);            } catch (NumberFormatException e) {                String msg = "The servlet configuration parameter "                + PARAM_SESSION_TTL                + " is not an integer number ("                + value                + ")"                ;                log.severe(msg);                throw new ServletException(msg);            }        }                holderCache = new SyncHolderCache(timeToLive);                value = config.getInitParameter(PARAM_SERVER_URI);        if (StringUtils.isEmpty(value)) {            String msg = "The servlet configuration parameter "            + PARAM_SERVER_URI            + " cannot be empty ("            + value            + ")"            ;            log(msg);            throw new ServletException(msg);        }                serverUri = value;    }            public void doPost(    final HttpServletRequest httpRequest,    final HttpServletResponse httpResponse)    throws ServletException, IOException {                final String contentType = httpRequest.getContentType().split(";")[0];        final int contentLength  = httpRequest.getContentLength();                if (log.isLoggable(Level.FINE)) {            log("contentType: " + contentType);            log("contentLength: " + contentLength);        }                if (contentLength < 1) {            throw new Error("Content length < 1 (" + contentLength + ")");        }                byte[] requestData = new byte[contentLength];                InputStream in = httpRequest.getInputStream();        int n = 0;        int bytesRead = 0;                try {            do {                n = in.read(requestData,                bytesRead,                requestData.length - bytesRead);                if (n > 0) {                    bytesRead += n;                }            } while (n != -1);        } catch (IOException ex) {            handleError(httpRequest, httpResponse, "Error reading the request", ex);            return;        } finally {            try {                if (in != null) {                    in.close();                }            } catch (Exception ex) {                handleError(httpRequest, httpResponse, ex.getClass().getName(), ex);                return;            }            in = null;        }                if (bytesRead != contentLength) {            handleError(httpRequest, httpResponse, "bytesRead != contentLength", null);            return;        }                //        // If the session id is not specified in the URL, a new remote object        // will be created. Otherwise the session id specifies which remote        // object shall handles the request.        //        SyncHolder holder = null;        try {            holder = createHolder(httpRequest);        } catch (Exception e) {            handleError(httpRequest, httpResponse, "Error creating SyncBean", e);            return;        }                SyncResponse resp = null;        try {            resp = holder.processMessage(requestData, contentType);        } catch (Exception e) {            Throwable cause = e.getCause();                        if (  (cause != null)            && (  (cause instanceof ProtocolException)            || (cause instanceof Sync4jException  )            )            ) {                handleError(httpRequest, httpResponse, "Protocol error", cause);                return;            } else {                throw new ServletException(e);            }        }                //        // Set the <RespURI> tag to the server uri plus the session id parameter        //        SyncML responseMessage = resp.getMessage();        responseMessage.getSyncHdr().setRespURI(        serverUri                    +        httpRequest.getContextPath() +        httpRequest.getServletPath() +        '?'                          +        PARAM_SESSION_ID             +        '='                          +        holder.getSessionId()        );                OutputStream out = null;        try {            out = httpResponse.getOutputStream();            httpResponse.setContentType(resp.getMimeType());                        byte[] response = null;            if (Constants.MIMETYPE_SYNCML_XML.equals(resp.getMimeType())) {                                if (log.isLoggable(Level.FINE)) {                    log.fine("Sending back XML");                }                                try {                                        if (log.isLoggable(Level.FINE)) {                        log.info("Marshalling response message SyncML");                    }                                        ByteArrayOutputStream bout = new ByteArrayOutputStream();                                        IBindingFactory f = BindingDirectory.getFactory(SyncML.class);                    IMarshallingContext c = f.createMarshallingContext();                    c.setIndent(0);                    c.marshalDocument(responseMessage, "UTF-8", null, bout);                                        String msgOut = new String(bout.toByteArray());                    response = msgOut.getBytes();                                    } catch(Exception e) {                    e.printStackTrace();                }                                            } else if (Constants.MIMETYPE_SYNCML_WBXML.equals(resp.getMimeType())){                if (log.isLoggable(Level.FINE)) {                    log.fine("Sending back WBXML");                }                                try {                    //                    // The marshalling is doing directly into WBXMLTools because                    // that method is calling in the other code too                    //                    response = WBXMLTools.toWBXML(responseMessage);                                    } catch(Exception e) {                    e.printStackTrace();                }            }                        httpResponse.setContentLength(response.length);            out.write(response);                        out.flush();        } finally {            if (log.isLoggable(Level.FINE)) {                log.fine("Finally");            }            if (out != null) out.close();        }                //        // If the message completed the SyncML communication, the holder        // must be closed and discarded.        //        if (resp.isCompleted()) {            releaseHolder(holder);        }    }        // --------------------------------------------------------- Private methods            /**     * Factory method for <i>SyncHolder</i> objects. If the session id is     * passed as a CGI parameter, it is transformed in a EJB handle. If the     * handle is not valid, it is considered expired. If the session id is not     * specified, a new EJB is created     *     * @param request the associated HTTP request object     *     * @return a new <i>SyncHolder</i>     *     */    private SyncHolder createHolder(HttpServletRequest request)    throws Exception {        String sessionId = request.getParameter(PARAM_SESSION_ID);                SyncHolder holder = null;                if (log.isLoggable(Level.FINE)) {            log.fine("cache: " + holderCache);        }                if (!StringUtils.isEmpty(sessionId)) {            holder = (SyncHolder)holderCache.get(sessionId);        }                if (holder == null) {            holder = (SyncHolder)getClass().forName(syncHolderClass).newInstance();                        sessionId = createSessionId(request);            holder.setSessionId(sessionId);            holderCache.put(holder);        }                return holder;    }        /**     * Closes the given <i>SyncHolder</i> and removes it from the cache.     *     * @param holder the holder to releases     */    private void releaseHolder(SyncHolder holder) {        try {            holder.close();        } catch (Exception e) {            log.severe(e.getMessage());            log.throwing(getClass().getName(), "releaseHolder", e.getCause());        }        holderCache.remove(holder.getSessionId());    }        /**     * Handles errors conditions returning an appropriate content to the client.     *     * @param request the request object     * @param response the response object     * @msg   a desctiptive message     * @t     a throwable object     *     */    private void handleError(final HttpServletRequest   request,    final HttpServletResponse response,    String                   msg,    final Throwable                  t) {                if (msg == null) {            msg = "";        }                if (t == null) {            log.severe(msg);        } else {            log.severe(msg);            log.throwing(getClass().getName(), "unknown", t);        }        try {            response.sendError(response.SC_BAD_REQUEST, msg);        } catch (IOException e) {            log.severe(e.getMessage());            log.throwing(getClass().getName(), "unknown", t);        }    }        /**     * Creates the session id (see the class description for details).     *     * @param request the HTTP request object     *     * @return a newly created session id     */    private String createSessionId(HttpServletRequest request) {        String clientIP  = request.getRemoteAddr()   ;        long   timestamp = System.currentTimeMillis();                StringBuffer sb = new StringBuffer();                byte[] ip = null;                try {            ip = InetAddress.getByName(clientIP).getAddress();        } catch (UnknownHostException e) {            ip = new byte[] {0, 0, 0, 0};        }                sb.append(ip).append('-').append(timestamp);                String stringSessionId = new String(Base64.encode(sb.toString().getBytes()));                //        // strips out tailing '='        //        int i = stringSessionId.lastIndexOf('=');                return ((i>0) ? stringSessionId.substring(0, i-1) : stringSessionId);    }        /**     * The same as <i>handleError(reqest, response, msg, t, null)</i>.     *     * @param request the request object     * @param response the response object     * @msg   a desctiptive message     * @t     a throwable object     *     */    private void handleError(final HttpServletRequest   request,    final HttpServletResponse response,    final String                   msg) {        this.handleError(request, response, msg, null);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -