Package com.sun.messaging.jmq.jmsserver.service

Source Code of com.sun.messaging.jmq.jmsserver.service.Connection

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2000-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* @(#)Connection.java  1.66 06/29/07
*/

package com.sun.messaging.jmq.jmsserver.service;

import java.util.*;
import com.sun.messaging.jmq.jmsserver.service.*;

import com.sun.messaging.jmq.jmsserver.Globals;
import com.sun.messaging.jmq.jmsserver.core.DestinationUID;
import com.sun.messaging.jmq.util.log.Logger;
import com.sun.messaging.jmq.util.ServiceType;
import com.sun.messaging.jmq.jmsserver.resources.BrokerResources;

import java.security.Principal;
import com.sun.messaging.jmq.jmsserver.auth.AccessController;
import com.sun.messaging.jmq.jmsserver.auth.JMQAccessControlContext;
import com.sun.messaging.jmq.auth.api.server.AccessControlContext;

import com.sun.messaging.jmq.io.*;

import com.sun.messaging.jmq.net.IPAddress;
import com.sun.messaging.jmq.jmsserver.util.BrokerException;
import com.sun.messaging.jmq.jmsserver.net.*;


/**
* This interface class is responsible for the basic methods needed to
* send messages back to a client
*
* Each service will implement their own version of this
* Connection interface..
*/

public abstract class Connection
{

// XXX - lks - move to init method ?
    private static int clockSkewTime = Globals.getConfig().getIntProperty(
                           Globals.IMQ + ".clock.skew.interval", 300);

    private static int clockSkewCheck = Globals.getConfig().getIntProperty(
                           Globals.IMQ + ".clock.skew.checkCnt", 0);


    private int skewCheckCounter = 0;

    private long lastAccess = 0;
    private long lastResponse = 0;

    protected final Logger logger = Globals.getLogger();

    // VERSION STRINGS for PROTOCOL
    public static final int UNKNOWN_PROTOCOL = -1;
    public static final int SWIFT_PROTOCOL = 200;
    public static final int HUMMINGBIRD_PROTOCOL = 201;
    public static final int FALCON_PROTOCOL = 300;
    public static final int RAPTOR_PROTOCOL=PacketType.VERSION350;
    public static final int SHRIKE_PROTOCOL=PacketType.VERSION360;
    public static final int SHRIKE4_PROTOCOL=PacketType.VERSION364;
    public static final int HAWK_PROTOCOL=PacketType.VERSION400;
    public static final int V45_PROTOCOL=PacketType.VERSION450;


    // CONNECITON STATE STRINGS
    public static final int STATE_UNAVAILABLE = -1;
    public static final int STATE_CONNECTED = 0;
    public static final int STATE_INITIALIZED = 1;
    public static final int STATE_AUTH_REQUESTED = 2;
    public static final int STATE_AUTH_RESPONSED = 3;
    public static final int STATE_AUTHENTICATED = 4;
    public static final int STATE_CLEANED = 5;
    public static final int STATE_CLOSED = 6;
    public static final int STATE_DESTROYING = 7;
    public static final int STATE_DESTROYED = 8;

    /**
     * State of the connection
     */
    protected int state = Connection.STATE_UNAVAILABLE;

    /**
     * Service object
     */
    protected Service service = null;

    /**
   * Authentication/Authorization controller object
     */
    protected AccessController accessController = null;

    /**
     * Connection ID associated with this Connection
     */
    protected ConnectionUID conId = null;


    /**
     * for reconnectable connections, time to next reconnect
     */
    protected long reconnectInterval = 0;


    /**
     * What version of the protocol the client is speaking. This is
     * set when we process the HELLO message
     */
    protected int clientProtocolVersion = -1;

    /**
     * Additional data tagged onto the connection
     */
    protected Hashtable clientData = null;


    protected boolean isadmin = false;

    protected List consumerInfoRequests = Collections.synchronizedList(new ArrayList());
    protected List connCloseListeners = new ArrayList();

    public Connection(Service svc) throws BrokerException
    {
        setService(svc);
        isadmin = svc.getServiceType() == ServiceType.ADMIN;
    }


    /**
     * The debug state of this object
     */


    public Hashtable getDebugState() {
        Hashtable ht = new Hashtable();
        ht.put("uid", String.valueOf(conId.longValue()));
        ht.put("service", service.toString());
        ht.put("state", getConnectionStateString(state));
        if (clientData != null)
            ht.put("clientData", clientData.toString());
        else
            ht.put("clientData", "none");
        ht.put("clientProtocol", String.valueOf(clientProtocolVersion));
        ht.put("reconnectInterval", String.valueOf(reconnectInterval));
        ht.put("lastAccess", String.valueOf(lastAccess));
        ht.put("lastResponse", String.valueOf(lastResponse));
        return ht;
    }

    public void setReconnectInterval(long val)
    {
        reconnectInterval = val;
    }

    public long getReconnectInterval() {
        return reconnectInterval;
    }

    public boolean isAdminConnection() {
        return isadmin;
    }

    public static  int getHighestSupportedProtocol()
    {
        return V45_PROTOCOL;
    }

 
    public abstract void startConnection();
    public abstract void stopConnection();
    public abstract void cleanupConnection();
    public abstract void closeConnection(boolean force, int reason, String reasonStr);
    public abstract void shutdownConnection(String reasonStr);
    public void destroyConnection(boolean force, int reason, String reasonStr)
    {
        service.removeConnection(conId, reason, reasonStr);
    }

    public void notifyConnectionClosed() {
        synchronized(this) {
            Iterator itr = connCloseListeners.iterator();
            ConnectionClosedListener l = null;
            while (itr.hasNext()) {
                l = (ConnectionClosedListener)itr.next();
                l.connectionClosed(this);
            }
        }
    }
    public void addConnectionClosedListener(ConnectionClosedListener l) {
        synchronized(this) {
            connCloseListeners.add(l);
        }
    }

    public void removeConnectionClosedListener(ConnectionClosedListener l) {
        synchronized(this) {
            connCloseListeners.remove(l);
        }
    }

    public abstract void logConnectionInfo(boolean closing);
    public abstract String getRemoteConnectionString();


    /**
     * Gets the ConnectionUID for this connection.
     */
    public ConnectionUID getConnectionUID() {
        return this.conId;
    }

    public void setConnectionUID(ConnectionUID conId) {
        this.conId = conId;
    }

    /**
     * Sets the Service for this connection.
     */
    protected void setService(Service id) {
        this.service = id;
    }


    /**
     * Gets the Service for this connection.
     */
    public Service getService() {
        return this.service;
    }

    /**
     * Set what iMQ protocol version the client is using. This is
     * determined when we get the HELLO message.
     */
    public void setClientProtocolVersion(int version) {
        clientProtocolVersion = version;
    }


    /**
     * Get what iMQ protocol version the client is using
     */
    public int getClientProtocolVersion() {
        return clientProtocolVersion;
    }

    /**
     * Gets the AccessController for this connection.  An AccessController
     * encapsulates a AuthenticationProtocolHandler and AccessControlContext.
     * The later is obtained as result of authentication.
     */
    public AccessController getAccessController() {
        return accessController;
    }

    /**
     * The term, principal, represents a name associated with the
     * authenticated subject on this connection
     *
     * @exception BrokerException connection not authenticated
     */
    public Principal getAuthenticatedName() throws BrokerException {
  return accessController.getAuthenticatedName();
    }

    /**
     * retrieves the connection state
     * @return false if connection being destroyed
     */
    public boolean setConnectionState(int state)
    {
        if (state >= STATE_DESTROYED) return true;
        this.state =  state;
        return false;
    }

    public static String getConnectionStateString(int state) {
        switch (state) {
            case Connection.STATE_UNAVAILABLE:
                return "UNAVAILABLE";

            case Connection.STATE_CONNECTED:
                return "CONNECTED";

            case Connection.STATE_INITIALIZED:
                return "INITIALIZED";

            case Connection.STATE_AUTH_REQUESTED:
                return "AUTHENTICATION REQUESTED";

            case Connection.STATE_AUTH_RESPONSED:
                return "AUTHENTICATION RESPONSED";

            case Connection.STATE_AUTHENTICATED:
                return "AUTHENTICATED";

            case Connection.STATE_CLOSED:
                return "CLOSED";

            case Connection.STATE_CLEANED:
                return "CLEANED";

            case Connection.STATE_DESTROYING:
                return "DESTROYING";
            case Connection.STATE_DESTROYED:
                return "DESTROYED";
        }
        return "UNKNOWN";
    }

    /**
     * sets the connection state
     * @return false if connection being destroyed
     */
    public int getConnectionState() {
        return state;
    }

    /**
     * Place an object (by name) in the client data storage
     * section of the Connection object
     */
    public void addClientData(String name, Object data)
    {
        if (clientData == null)
            clientData = new Hashtable();
        clientData.put(name, data);
    }

    /**
     * remove client data object (by name)
     */
    public void removeClientData(String name) {
        if (clientData == null) return;
        clientData.remove(name);
    }

    /**
     * retrieve client data object (by name)
     */
    public Object getClientData(String name)
    {
        if (clientData == null) return null;
        return clientData.get(name);
    }


    // dont sync .. we dont care who won
    public void updateAccessTime(boolean received) {
        lastAccess = System.currentTimeMillis();
        if (received)
            lastResponse=lastAccess;
    }

    public long getAccessTime() {
        return lastAccess;
    }
    public long getLastResponseTime() {
        return lastResponse;
    }

    public void checkClockSkew(long receivetime, long sendtime,
         long expiretime)
    {
        // clockSkewCheck:
        //     -1 never check
        //      0 check once
        //      > 1 check every X requests

        if (clockSkewCheck < 0) {
            // never check
            return;
        }
        // if 0, just check once
        if (clockSkewCheck == 0 && skewCheckCounter > 0)
            return;
       
        skewCheckCounter ++;

        if (clockSkewCheck > 0 && (
              skewCheckCounter%clockSkewCheck != 0)) {
             // not the right iteration
             return;
        }


        // OK, if we are here, we are checking for skew
        long skewSecsMS = Math.abs(sendtime - receivetime);
        long skewSecs = skewSecsMS/1000;

        // OK, we also want to log something if the clock skew is
        // less than our counter but we are immediately expiring the
        // message
        // So:
        //    - if we receive the message before we sent it
        //           (receivetime > sendtime)
        //      and the expiration time is small (< clockSkewTime)
        //      and the expiration is less than twice the
        //             skew time
        //  log something

        long expirationMS = (expiretime == 0 ? 0
              : ( (receivetime > sendtime )
                   ? expiretime - sendtime : 0));

        long expirationSecs = expirationMS/1000;

        if (skewSecs >  clockSkewTime) {
            String msg = BrokerResources.W_CLOCK_SKEW_EARLY;
            // we received the message before we sent
            if (sendtime < receivetime) {
                 msg = BrokerResources.W_CLOCK_SKEW_LATE;
            }
            logger.log(Logger.WARNING, msg,
                  getRemoteConnectionString(), String.valueOf(clockSkewTime));
         } else if (expirationMS != 0 && expirationSecs < clockSkewTime &&
               expirationMS < 2*skewSecsMS) {
            logger.log(Logger.WARNING, BrokerResources.W_CLOCK_SKEW_EXPIRING,
                  getRemoteConnectionString());
         }
    }


    protected abstract void sayGoodbye(int reason, String reasonStr);
    protected abstract void flushConnection(long timeout);

    /**
     * verify if the connection still exists
     */
    protected abstract void checkConnection();

    public abstract void cleanupMemory(boolean persistent);


    public void debug(String prefix) {
    }

    public void sendConsumerInfo(int requestType,
                                 DestinationUID duid,
                                 int destType, int infoType,
                                 boolean sendToWildcard) {
        DestinationUID uid = null;
        synchronized(consumerInfoRequests) {
            Iterator itr = consumerInfoRequests.iterator();
            while (itr.hasNext()) {
                uid = (DestinationUID)itr.next();
                if (!uid.isWildcard()) {
                    if (duid.equals(uid)) {
                        sendConsumerInfo(requestType, uid.getName(),
                                         destType, infoType);
                        break;
                    }
                    continue;
                }
                if (duid.isWildcard() &&
                    uid.getName().equals(duid.getName()) &&
                    duid.isQueue() == uid.isQueue()) {
                    sendConsumerInfo(requestType, uid.getName(), destType, infoType);
                    break;
                }
                if (DestinationUID.match(duid, uid)) {
                    if (sendToWildcard) {
                        sendConsumerInfo(requestType, uid.getName(), destType, infoType);
                    } else {
                        Globals.getConnectionManager().getConsumerInfoNotifyManager().
                                 consumerInfoRequested(this, uid, destType, infoType);
                    }
                }
            }
        }
    }

    protected abstract void sendConsumerInfo(int requestType, String destName,
                                             int destType, int infoType);

    public void addConsumerInfoRequest(DestinationUID duid) {
        consumerInfoRequests.add(duid);
    }

    public void removeConsumerInfoRequest(DestinationUID duid) {
        consumerInfoRequests.remove(duid);
    }
}

TOP

Related Classes of com.sun.messaging.jmq.jmsserver.service.Connection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.