//
// JmsaD.java - JMS Adapter Destination base class
//
// JmsaDs are "administered" objects and can be registered in JNDI.
// Some JNDI implementation use serialization to do this.
// Other implementations (such as the filesystem one) use the Referenceable
// mechanism, and if this is used, we arrange that the Reference includes the
// name, and the name of an object factory able to reconstruct the object.
//

package nyangau.jmsadapter;

import java.util.Map;
import java.util.HashMap;
import java.util.Hashtable;
import java.io.*;
import javax.naming.*;
import javax.jms.*;

public class JmsaD implements Serializable, Referenceable
  {
  protected HashMap<String,Object> properties;
//...sJmsaD:2:
public JmsaD() {} // to allow deserialisation only
public JmsaD(Map<String,Object> map)
  {
  properties = new HashMap<String,Object>();
  if ( map != null )
    properties.putAll(map);
  }
public JmsaD(Map<String,Object> map, Map<String,Object> map2)
  {
  properties = new HashMap<String,Object>();
  if ( map != null )
    properties.putAll(map);
  if ( map2 != null )
    properties.putAll(map2);
  }
//...e
//...sgetReference:2:
public Reference getReference()
  throws NamingException
  {
  Reference r = new Reference( 
    getClass().getName(),
    JmsaDObjectFactory.class.getName(),
    null // factoryLocation
    );
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  try
    {
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(properties);
    oos.flush();
    }
  catch ( IOException e )
    {
    throw new NamingException("Cannot serialize properties to make a reference");
    }
  r.add(new BinaryRefAddr("properties", baos.toByteArray()));
  return r;
  }
//...e
//...sfindDest:2:
protected Destination findDest()
  throws JMSException
  {
  String n = (String) properties.get(Jmsa.UNDERLYING_DESTINATION);
  if ( n == null )
    throw new JMSException("undefined underlying destination");
  try
    {
    Hashtable<String,Object> env = new Hashtable<String,Object>(properties);
    Context ctx = new InitialContext(env);
    return (Destination) ctx.lookup(n);
    }
  catch ( NamingException e )
    {
    JMSException je = new JMSException("cannot lookup underlying destination " + n); 
    je.setLinkedException(e);
    throw je;
    }
  }
//...e
//...swrapDestination:2:
// We might be wrapping
//   destinations created through JmsaSession and subclasses
//   non-temporary destinations in received messages
//   foreign destinations in outbound messages

public static Destination wrapDestination(Destination d)
  throws JMSException
  {
  if ( d == null )
    return null;
  else if ( d instanceof JmsaD )
    return d; // already wrapped
  else if ( d instanceof TemporaryQueue )
    return new JmsaTemporaryQueue((TemporaryQueue) d, null, null);
  else if ( d instanceof TemporaryTopic )
    return new JmsaTemporaryTopic((TemporaryTopic) d, null, null);
  else if ( d instanceof Queue )
    return new JmsaQueue((Queue) d, null);
  else if ( d instanceof Topic )
    return new JmsaTopic((Topic) d, null);
  else
    throw new JMSException("weird Destination");
  }
//...e
//...sgetDest:2:
public Destination getDest()
  throws JMSException
  {
  throw new JMSException("should be calling getDest() on a subclass");
  }
//...e
//...stoString:2:
public String toString()
  { return getClass().getName() + ":" + properties.toString(); }
//...e
  }
