package org.jboss.soa.esb.addressing.eprs;
/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author mark.little@jboss.com
*/
/**
* This class represents the endpoint reference for services.
*/
import org.apache.commons.codec.binary.Hex;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.addressing.XMLUtil;
import org.jboss.internal.soa.esb.assertion.AssertArgument;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.net.URI;
import java.net.URISyntaxException;
/**
* A helper class for using in-VM communication.
*
* EPR: invm://servicename[/pass-by-value][?lockstep[#waittime]]
*
* where lockstep can be either true or false and waittime is the lockstep wait
* time in milliseconds. If lockstep is false then any value specified for
* waittime will be ignored.
*
* e.g.,
*
* invm://myservice?true#20000 invm://myservice invm://myservice?false (same as
* invm://myservice) or invm://myservice/false?false (first false is pass-by-value
* value).
*
* You can have a lockstep service, where the sender thread is tied to the one
* that does the execution (equivalent to the sender thread doing the work
* within the receiver), or non-lockstep, whereby the sender thread is decoupled
* from the receiver and works as fast as it needs to in order to deliver
* messages. This is roughly equivalent to CORBA POA threading policies. (Maybe
* we'll implement it that way at some point in the future?)
*
* @author marklittle
*
*/
public class InVMEpr extends EPR
{
public static final long DEFAULT_LOCKSTEP_WAIT_TIME = 10000; // in
// millis,
// 10
// seconds
public static final String INVM_PROTOCOL = "invm";
public static final String LOCKSTEP_ENDPOINT_TAG = "lockstep";
public static final String LOCKSTEP_WAIT_TIME_TAG = "lockstepWait";
public static final String PASS_BY_VALUE = "passByValue";
public static final String TEMPORARY_EPR = "temporaryEPR";
public InVMEpr(EPR epr)
{
super(epr) ;
}
public InVMEpr(EPR epr, Element header)
{
this(epr);
NodeList nl = header.getChildNodes();
for (int i = 0; i < nl.getLength(); i++)
{
try
{
String prefix = nl.item(i).getPrefix();
String tag = nl.item(i).getLocalName();
if ((prefix != null)
&& (prefix.equals(XMLUtil.JBOSSESB_PREFIX)))
{
if (tag != null)
{
if (tag.equals(LOCKSTEP_ENDPOINT_TAG))
{
getAddr().addExtension(LOCKSTEP_ENDPOINT_TAG, nl.item(i).getTextContent());
}
else if (tag.equals(LOCKSTEP_WAIT_TIME_TAG))
{
getAddr().addExtension(LOCKSTEP_WAIT_TIME_TAG, nl.item(i).getTextContent());
}
else if (tag.equals(PASS_BY_VALUE))
{
getAddr().addExtension(PASS_BY_VALUE, nl.item(i).getTextContent());
}
else if (tag.equals(TEMPORARY_EPR))
{
getAddr().addExtension(TEMPORARY_EPR, nl.item(i).getTextContent());
}
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
public InVMEpr(URI uri) throws URISyntaxException
{
super(uri);
String serviceId = uri.getHost();
String lockstep = uri.getQuery();
String lockstepTime = uri.getFragment();
String passByReference = uri.getPath();
if (serviceId == null)
throw new URISyntaxException(uri.toString(),
"No serviceId specified!");
if ("true".equalsIgnoreCase(lockstep))
{
setLockstep(true);
if (lockstepTime != null)
{
try
{
setLockstepWaitTime(Long.parseLong(lockstepTime));
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
if ("/true".equalsIgnoreCase(passByReference)) {
setPassByValue(true);
} else {
setPassByValue(false);
}
}
public String getServiceId()
{
try
{
return new URI(getAddr().getAddress()).getHost();
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
}
public void setServiceId(String serviceId)
{
if (serviceId == null)
throw new IllegalArgumentException();
getAddr().setAddress(INVM_PROTOCOL + "://" + serviceId);
}
public boolean getLockstep()
{
String lockstep = getAddr().getExtensionValue(LOCKSTEP_ENDPOINT_TAG);
if ("true".equalsIgnoreCase(lockstep))
return true;
else
return false;
}
public void setLockstep(boolean lockstep)
{
getAddr().addExtension(LOCKSTEP_ENDPOINT_TAG, Boolean.toString(lockstep));
}
public long getLockstepWaitTime()
{
String waitTime = getAddr().getExtensionValue(LOCKSTEP_WAIT_TIME_TAG);
if (waitTime != null)
{
try
{
return Long.parseLong(waitTime);
}
catch (Exception ex)
{
_logger.warn("Failed to parse lockstep wait time", ex);
}
}
return DEFAULT_LOCKSTEP_WAIT_TIME;
}
public void setLockstepWaitTime(long waitTime)
{
getAddr().addExtension(LOCKSTEP_WAIT_TIME_TAG, Long.toString(waitTime));
}
public boolean getPassByValue()
{
String passByValue = getAddr().getExtensionValue(PASS_BY_VALUE);
if (passByValue == null) // default
return false;
if ("false".equalsIgnoreCase(passByValue))
return false;
else
return true;
}
public void setPassByValue(boolean val)
{
getAddr().addExtension(PASS_BY_VALUE, Boolean.toString(val));
}
public boolean isTemporaryEPR()
{
final String temporary = getAddr().getExtensionValue(TEMPORARY_EPR) ;
return Boolean.valueOf(temporary) ;
}
public void setTemporaryEPR(final boolean temporary)
{
getAddr().addExtension(TEMPORARY_EPR, Boolean.toString(temporary)) ;
}
public String toString()
{
return "InVMEpr [ " + super.getAddr().extendedToString() + " ]";
}
/**
* Create an encoded service ID from the supplied Service Cat and Name.
* <p/>
* The result is a simple hex encoding of the concatenated strings and is
* usable in the InVMEpr URI i.e. is uneffected by slashes etc in the
* Cat and Service name strings.
*
* @param catagory The Service Category.
* @param name The Service name.
* @return Hex encoded string.
*/
public static String createEncodedServiceId(String catagory, String name) {
AssertArgument.isNotNullAndNotEmpty(catagory, "catagory");
AssertArgument.isNotNullAndNotEmpty(name, "name");
byte[] bytes = (catagory.trim() + "$$$$$$$$$$$$" + name.trim()).getBytes();
return new String(Hex.encodeHex(bytes));
}
public EPR copy() {
return new InVMEpr(this);
}
private static URI _type;
public static URI type()
{
return _type;
}
static
{
_type = URI.create("urn:jboss/esb/epr/type/invm");
}
}