/*
* 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.
*/
/*
* @(#)BrokerAddressImpl.java 1.40 07/02/07
*/
package com.sun.messaging.jmq.jmsserver.multibroker.fullyconnected;
import java.io.*;
import java.net.*;
import java.util.*;
import com.sun.messaging.jmq.util.UID;
import com.sun.messaging.jmq.util.log.Logger;
import com.sun.messaging.jmq.io.GPacket;
import com.sun.messaging.jmq.jmsserver.Globals;
import com.sun.messaging.jmq.jmsserver.resources.*;
import com.sun.messaging.jmq.jmsserver.resources.BrokerResources;
import com.sun.messaging.jmq.jmsserver.util.BrokerException;
import com.sun.messaging.jmq.jmsserver.util.LoopbackAddressException;
import com.sun.messaging.jmq.jmsserver.util.VerifyAddressException;
import com.sun.messaging.jmq.jmsserver.core.BrokerAddress;
import com.sun.messaging.jmq.jmsserver.core.BrokerMQAddress;
/**
* This class implements the <code>BrokerAddress</code> for the
* standard fully connected topology.
*/
public class BrokerAddressImpl extends BrokerAddress {
private static final Logger logger = Globals.getLogger();
private static final BrokerResources br = Globals.getBrokerResources();
// For compatibility with iMQ 2.0
static final long serialVersionUID = 2088198635383118304L;
private String hostName = null; //always IP address String
private String instName = null;
private boolean HAEnabled = false;
private String brokerID = null;
private UID brokerSessionUID = null;
private UID storeSessionUID = null;
private int port = -1; // Portmapper port.
private transient int clusterVersion = 0;
public static final int VERSION = 100;
public BrokerAddressImpl(BrokerMQAddress ba, String instName, boolean ha, String brokerID)
throws Exception {
this.hostName = ba.getHost().getHostAddress();
this.port = ba.getPort();
this.instName = (instName == null) ? "???":instName;
this.HAEnabled = ha;
if (ha) this.brokerID = brokerID;
this.brokerSessionUID = null;
this.storeSessionUID = null;
initialize(ba);
verifyAddress();
}
public BrokerAddressImpl(String hostName, String instName, int port,
boolean ha, String brokerID,
UID brokerSession, UID storeSession)
throws Exception {
initialize(hostName, port);
this.hostName = getMQAddress().getHost().getHostAddress();
this.instName = instName;
this.port = port;
this.HAEnabled = ha;
this.brokerID = brokerID;
this.brokerSessionUID = brokerSession;
this.storeSessionUID = storeSession;
verifyAddress();
}
/**
* Generate this broker's address.
*/
public BrokerAddressImpl() throws Exception {
this(Globals.getPortMapper().getHostname(),
Globals.getConfigName(),
Globals.getPortMapper().getPort(),
Globals.getHAEnabled(),
Globals.getBrokerID(),
Globals.getClusterManager().getBrokerSessionUID(),
Globals.getClusterManager().getStoreSessionUID());
}
public int getClusterVersion() {
return clusterVersion;
}
public void setClusterVersion(int clusterVersion) {
this.clusterVersion = clusterVersion;
}
/**
* Perform simple sanity checks on a broker address received
* from somewhere else. During one of the "test-o-thon" sessions
* one of the linux system was sending a LINK_INIT packet
* advertizing itself as "localhost". This method detects
* such bogus addresses..
*/
private void verifyAddress() throws Exception {
if (getMQAddress().getHost().isLoopbackAddress()) {
throw new LoopbackAddressException(Globals.getBrokerResources().getString(
BrokerResources.X_LOOPBACKADDRESS, this.toString()));
}
if (Globals.getHAEnabled() != getHAEnabled()) {
throw new VerifyAddressException(Globals.getBrokerResources().getString(
BrokerResources.X_ADDRESS_HAMODE_NOTMATCH, this.toString()));
}
if (getHAEnabled() && (brokerID == null)) {
throw new VerifyAddressException(Globals.getBrokerResources().getString(
BrokerResources.X_ADDRESS_NO_BROKERID, this.toString()));
}
}
public String getHostName() {
return getMQAddress().getHost().getHostAddress();
}
public String getInstanceName() {
return instName;
}
public int getPort() {
return port;
}
public InetAddress getHost() {
return getMQAddress().getHost();
}
public boolean getHAEnabled() {
return HAEnabled;
}
public String getBrokerID() {
return brokerID;
}
public UID getBrokerSessionUID() {
return brokerSessionUID;
}
public UID getStoreSessionUID() {
return storeSessionUID;
}
//only to be used with readBrokerAddress
public Object clone() {
BrokerAddressImpl copy;
try {
copy = (BrokerAddressImpl) super.getObjectClone();
} catch (CloneNotSupportedException e) {
// Should never get this, but don't fail silently
System.out.println("BrokerAddressImpl: Could not clone: " + e);
return null;
}
return copy;
}
public boolean equals(Object obj) {
if (! (obj instanceof BrokerAddressImpl))
return false;
BrokerAddressImpl addr = (BrokerAddressImpl) obj;
if (getHAEnabled() != addr.getHAEnabled()) return false;
if (getHAEnabled()) {
if (this.brokerID == null || addr.getBrokerID() == null) return false;
return this.brokerID.equals(addr.getBrokerID());
}
if (! this.instName.equals(addr.instName))
return false;
if (getMQAddress().getHost() == null ||
addr.getMQAddress().getHost() == null)
return false;
return getMQAddress().getHost().equals(addr.getMQAddress().getHost());
}
public int hashCode() {
return (31 * getMQAddress().getHost().hashCode()) + instName.hashCode();
}
/**
* @return what's used for equals
*/
public String toShortString() {
getMQAddress().getHost().getHostName();
StringBuffer buf = new StringBuffer();
InetAddress addr = getMQAddress().getHost();
buf.append((addr == null ? "null":addr.getHostAddress()));
buf.append("?");
if (getHAEnabled()) {
buf.append("brokerID=");
buf.append(getBrokerID());
buf.append("&");
buf.append("ha=true");
} else {
buf.append("instName="+getInstanceName());
buf.append("&");
buf.append("ha=false");
}
return buf.toString();
}
/**
* Returns a cluster protocol formated string
* XXX remaining work for HA!!!
*/
public String toProtocolString() {
StringBuffer buf = new StringBuffer();
buf.append(getMQAddress().toString());
buf.append("?");
buf.append("instName="+getInstanceName());
if (getBrokerID() != null) {
buf.append("&");
buf.append("brokerID=");
buf.append(getBrokerID());
}
buf.append("&");
buf.append("brokerSessionUID=");
buf.append(getBrokerSessionUID());
if (getHAEnabled()) {
buf.append("&");
buf.append("ha=true");
buf.append("&");
buf.append("storeSessionUID=");
buf.append(getStoreSessionUID());
}
return buf.toString();
}
public BrokerAddress fromProtocolString(String s) throws Exception {
BrokerMQAddress a = BrokerMQAddress.createAddress(s);
String ha = (String)a.getProperty("ha");
return new BrokerAddressImpl(a.getHostName(),
a.getProperty("instName"),
a.getPort(),
!(ha == null),
a.getProperty("brokerID"),
new UID(Long.valueOf(a.getProperty("brokerSessionUID")).longValue()),
((ha == null) ? null:
new UID(Long.valueOf(a.getProperty("storeSessionUID")).longValue())));
}
/**
* The 2 methods of marshal/unmarshal BrokerAddressImpl in GPacket props is
* to replace the old protocol write/read BrokerAddressImpl in GPacket body
*/
public void writeBrokerAddress(GPacket gp) {
gp.putProp("HA", Boolean.valueOf(getHAEnabled()));
if (brokerID != null) gp.putProp("brokerID", getBrokerID());
if (brokerSessionUID != null) gp.putProp("brokerSession", new Long(getBrokerSessionUID().longValue()));
if (storeSessionUID != null) gp.putProp("storeSession", new Long(getStoreSessionUID().longValue()));
gp.putProp("instanceName", getInstanceName());
gp.putProp("host", getHostName());
gp.putProp("port", new Integer(getPort()));
}
public static BrokerAddressImpl readBrokerAddress(GPacket gp) throws Exception {
if (gp.getProp("HA") == null) return null; //old protocol < 400
boolean ha = ((Boolean)gp.getProp("HA")).booleanValue();
String brokerID = (String)gp.getProp("brokerID");
String instName = (String)gp.getProp("instanceName");
String host = (String)gp.getProp("host");
int port = ((Integer)gp.getProp("port")).intValue();
Long brokerSession = (Long)gp.getProp("brokerSession");
Long storeSession = (Long)gp.getProp("storeSession");
UID buid = null;
UID suid = null;
if (brokerSession != null) buid = new UID(brokerSession.longValue());
if (storeSession != null) suid = new UID(storeSession.longValue());
BrokerAddressImpl ba = new BrokerAddressImpl(host, instName, port, ha, brokerID, buid, suid);
return ba;
}
public void writeBrokerAddress(DataOutputStream dos) throws IOException {
dos.writeInt(VERSION);
dos.writeUTF(hostName);
dos.writeUTF(instName);
dos.writeInt(port);
dos.flush();
}
public void readBrokerAddress(DataInputStream dis)
throws IOException {
int version = dis.readInt();
if (version > VERSION)
throw new IOException(Globals.getBrokerResources().getString(
BrokerResources.X_INTERNAL_EXCEPTION,"BrokerAddress version mismatch."));
hostName = dis.readUTF();
instName = dis.readUTF();
port = dis.readInt();
initialize(hostName, port);
HAEnabled = false;
brokerID = null;
brokerSessionUID = null;
storeSessionUID = null;
clusterVersion = 0;
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
initialize(hostName, port);
}
public String toString() {
// Force a reverse name lookup so that
// host.toString() output looks better.
getMQAddress().getHost().getHostName();
return toProtocolString();
}
}