/*
* 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.
*/
/*
* @(#)IMQEmbeddedConnection.java 10/28/08
*/
package com.sun.messaging.jmq.jmsserver.service.imq;
import com.sun.messaging.jmq.util.log.Logger;
import com.sun.messaging.jmq.jmsserver.util.BrokerException;
import com.sun.messaging.jmq.jmsserver.util.IMQBlockingQueue;
import com.sun.messaging.jmq.jmsserver.service.Connection;
import com.sun.messaging.jmq.jmsserver.service.ConnectionUID;
import com.sun.messaging.jmq.jmsserver.core.Session;
import com.sun.messaging.jmq.jmsserver.core.DestinationUID;
import com.sun.messaging.jmq.jmsserver.service.Service;
import com.sun.messaging.jmq.io.Status;
import com.sun.messaging.jmq.io.Packet;
import com.sun.messaging.jmq.io.PacketType;
import com.sun.messaging.jmq.io.ReadOnlyPacket;
import com.sun.messaging.jmq.io.ReadWritePacket;
import com.sun.messaging.jmq.jmsserver.data.PacketRouter;
import com.sun.messaging.jmq.jmsservice.DirectBrokerConnection;
import com.sun.messaging.jmq.jmsserver.Globals;
import java.util.*;
import java.io.*;
import java.net.*;
import java.security.Principal;
import com.sun.messaging.jmq.jmsservice.HandOffQueue;
import com.sun.messaging.jmq.net.IPAddress;
import com.sun.messaging.jmq.jmsserver.util.MetricManager;
import com.sun.messaging.jmq.util.lists.*;
import com.sun.messaging.jmq.jmsserver.resources.BrokerResources;
public abstract class IMQBasicConnection extends IMQConnection
{
String remoteConString = null;
String remoteHostString = null;
PacketRouter router = null;
protected int[] pktsOut = new int[PacketType.LAST];
protected int[] pktsIn = new int[PacketType.LAST];
protected static final int NO_VERSION=0;
public static final int CURVERSION = Packet.VERSION3;
public int packetVersion=NO_VERSION;
// Known data which may be tagged on a connection
public static final String CLIENT_ID = "client id";
public static final String TRANSACTION_LIST = "transaction";
public static final String TRANSACTION_IDMAP = "tidmap";
public static final String TRANSACTION_CACHE = "txncache";
public static final String USER_AGENT = "useragent";
protected static boolean DEBUG = Globals.getConfig().getBooleanProperty(
Globals.IMQ + ".packet.debug.info");
protected static boolean DUMP_PACKET =
Globals.getConfig().getBooleanProperty(
Globals.IMQ + ".packet.debug.all");
protected static boolean OUT_DUMP_PACKET =
Globals.getConfig().getBooleanProperty(
Globals.IMQ + ".packet.debug.out");
protected static boolean IN_DUMP_PACKET =
Globals.getConfig().getBooleanProperty(
Globals.IMQ + ".packet.debug.in");
public static boolean getDumpPacket() {
return DUMP_PACKET;
}
public static boolean getDumpInPacket() {
return IN_DUMP_PACKET;
}
public static boolean getDumpOutPacket() {
return OUT_DUMP_PACKET;
}
public static void dumpPacket(boolean on) {
DUMP_PACKET=on;
}
public static void dumpInPacket(boolean on) {
IN_DUMP_PACKET=on;
}
public static void dumpOutPacket(boolean on) {
OUT_DUMP_PACKET=on;
}
protected static byte[] ipAddress = null;
static {
try {
ipAddress = InetAddress.getLocalHost().getAddress();
} catch (Exception ex) {
Globals.getLogger().log(Logger.INFO,"Internal Error, could not "
+ " retrieve local address ", ipAddress);
ipAddress = new byte[0];
}
}
public boolean METRICS_ON = MetricManager.isEnabled();
public IMQBasicConnection(Service svc, PacketRouter router)
throws IOException, BrokerException
{
super(svc);
this.router = router;
}
public boolean setConnectionState(int state) {
this.state = state;
return true; //default impl
}
/**
* Count an incoming packet
*/
public void countInPacket(Packet pkt) {
if (pkt == null)
return;
if (pkt.getPacketType() <= PacketType.MESSAGE &&
pkt.getPacketType() >= PacketType.TEXT_MESSAGE) {
// It's a JMS message, update both packet and message counters
counters.updateIn(1, pkt.getPacketSize(), 1, pkt.getPacketSize());
} else {
// It's a control message. Only update packet counters
counters.updateIn(0, 0, 1, pkt.getPacketSize());
}
}
/**
* Count outgoing packet
*/
public void countOutPacket(Packet pkt) {
if (pkt == null)
return;
if (pkt.getPacketType() <= PacketType.MESSAGE &&
pkt.getPacketType() >= PacketType.TEXT_MESSAGE) {
// It's a JMS message, update both packet and message counters
counters.updateOut(1, pkt.getPacketSize(), 1, pkt.getPacketSize());
} else {
// It's a control message. Only update packet counters
counters.updateOut(0, 0, 1, pkt.getPacketSize());
}
}
public void flushControl(long timeout) {
//default does nothing
}
public int getLocalPort() {
return 0;
}
public void waitForRelease(long time) {
return;
}
protected void sayGoodbye(int reason, String reasonstr) {
sayGoodbye(false, reason, reasonstr);
}
protected void sayGoodbye(boolean force, int reason, String reasonStr) {
Packet goodbye_pkt = new Packet(useDirectBuffers());
goodbye_pkt.setPacketType(PacketType.GOODBYE);
Hashtable hash = new Hashtable();
hash.put("JMQExit", Boolean.valueOf(force));
hash.put("JMQGoodbyeReason", new Integer(reason));
hash.put("JMQGoodbyeReasonString", reasonStr);
goodbye_pkt.setProperties(hash);
sendControlMessage(goodbye_pkt);
}
protected void sendConsumerInfo(int requestType, String destName,
int destType, int infoType) {
if (state >= STATE_CLOSED) return;
Packet info_pkt = new Packet(useDirectBuffers());
info_pkt.setPacketType(PacketType.INFO);
Hashtable props = new Hashtable();
props.put("JMQRequestType", Integer.valueOf(requestType));
props.put("JMQStatus", Status.OK);
info_pkt.setProperties(props);
Hashtable hash = new Hashtable();
hash.put("JMQDestination", destName);
hash.put("JMQDestType", Integer.valueOf(destType));
hash.put("JMQConsumerInfoType", Integer.valueOf(infoType));
DestinationUID duid = null;
try {
duid = DestinationUID.getUID(destName, destType);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(hash);
oos.flush();
bos.flush();
info_pkt.setMessageBody(bos.toByteArray());
bos.close();
} catch (Throwable t) {
logger.log(Logger.WARNING,
"XXXI18N Error: Unable to send consumer info to client: "+duid, t);
return;
}
sendControlMessage(info_pkt);
}
/**
* Compares connections to each other or connections
* to connection ID's
*/
public boolean equals(Object obj) {
if (obj instanceof ConnectionUID) {
return obj.equals(this.getConnectionUID());
}
if (obj instanceof Connection) {
return ((Connection) obj).getConnectionUID().equals(
this.getConnectionUID());
}
return false;
}
/**
* default toString method, sub-classes should override
*/
public String toString() {
return "IMQConn[" +getConnectionStateString(state)
+","+getRemoteConnectionString() + ","
+ localsvcstring +"]";
}
/**
* methods used by debugging, subclasses should override
*/
public String toDebugString() {
return super.toString() + " state: " + state;
}
public String remoteHostString() {
if (remoteHostString == null) {
try {
InetAddress inetaddr = InetAddress.getByAddress(getRemoteIP());
remoteHostString = inetaddr.getHostName();
} catch (Exception e) {
remoteHostString=IPAddress.rawIPToString(getRemoteIP(), true, true);
}
}
return remoteHostString;
}
public String getRemoteConnectionString() {
if (remoteConString != null)
return remoteConString;
boolean userset = false;
String userString = "???";
if (state >= Connection.STATE_AUTHENTICATED) {
try {
Principal principal = getAuthenticatedName();
if (principal != null) {
userString = principal.getName();
userset = true;
}
} catch (BrokerException e) {
if (DEBUG)
logger.log(Logger.DEBUG,"Exception getting authentication name "
+ conId, e );
}
}
String retstr = userString + "@" +
"Direct2" + ":" +
getConnectionUID();
if (userset) remoteConString = retstr;
return retstr;
}
String localsvcstring = null;
protected String localServiceString() {
if (localsvcstring != null)
return localsvcstring;
localsvcstring = service.getName();
return localsvcstring;
}
}