Package com.sun.messaging.jmq.admin.jmsspi

Source Code of com.sun.messaging.jmq.admin.jmsspi.JMSAdminImpl$StreamGobbler

/*
* 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.
*/

/*
* @(#)JMSAdminImpl.java  1.39 07/11/07
*/

package com.sun.messaging.jmq.admin.jmsspi;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.ExceptionListener;
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TemporaryQueue;

import com.sun.messaging.AdministeredObject;
import com.sun.messaging.ConnectionConfiguration;
import com.sun.messaging.DestinationConfiguration;
import com.sun.messaging.QueueConnectionFactory;
import com.sun.messaging.jmq.ClientConstants;
import com.sun.messaging.jmq.Version;
import com.sun.messaging.jmq.admin.apps.broker.BrokerCmdOptions;
import com.sun.messaging.jmq.admin.bkrutil.BrokerConstants;
import com.sun.messaging.jmq.admin.resources.AdminResources;
import com.sun.messaging.jmq.admin.util.Globals;
import com.sun.messaging.jmq.admin.util.JMSObjFactory;
import com.sun.messaging.jmq.jmsclient.ConnectionImpl;
import com.sun.messaging.jmq.jmsclient.JMSXAWrappedConnectionFactoryImpl;
import com.sun.messaging.jmq.jmsspi.JMSAdmin;
import com.sun.messaging.jmq.jmsspi.PropertiesHolder;
import com.sun.messaging.jmq.util.BrokerExitCode;
import com.sun.messaging.jmq.util.DestType;
import com.sun.messaging.jmq.util.admin.DestinationInfo;
import com.sun.messaging.jmq.util.admin.MessageType;


public class JMSAdminImpl implements JMSAdmin, ExceptionListener {

  private static AdminResources ar = Globals.getAdminResources();

    public static final long            DEFAULT_TIMEOUT = 5000;

    private String adminuserName = null;
    private String adminPassword = null;
    private String fallbackDBPassword = null;
    private String hadbPassword=null;
    private String mysqlPassword = null;
    private String keystorePassword = null;
    private String ldapPassword=null;
    String bridgeAdminPassword=null;
   
    private long timeout = -1;

    private QueueConnectionFactory      qcf;
    private QueueConnection             connection;
    private QueueSession                session;
    private Queue                       requestQueue;
    private TemporaryQueue              replyQueue;
    private QueueSender                 sender;
    protected QueueReceiver             receiver;

    private AdministeredObject    tmpDestination = null;
    private AdministeredObject    tmpConnFactory = null;

    private boolean      secureTransportUsed = false;

    // When this class is used to start a broker, these properties are passed to the broker
  private PropertiesHolder brokerPropertiesHolder;
   
    // use this logger name as enabling Glassfish jms logging uses loggers of the form javax.resourceadapter.mqjmsra                           
    protected static transient final String loggerName = "javax.resourceadapter.mqjmsra.lifecycle";
    protected static transient final Logger logger = Logger.getLogger(loggerName);

    /*
     * This class should only be instantiated via JMSAdminFactoryImpl.
     * REVISIT: hard-coded error messages
     */
    protected JMSAdminImpl(Properties connectionProps, PropertiesHolder brokerPropertiesHolder, String username, String adminPassword)
      throws JMSException {

    this.timeout = DEFAULT_TIMEOUT;
    this.adminuserName = username;
    this.adminPassword = adminPassword;
    this.brokerPropertiesHolder = brokerPropertiesHolder;

    createFactory(connectionProps); // init the qcf !!

    String connType = connectionProps.getProperty(ConnectionConfiguration.imqConnectionType, "");

    if (connType.equals("TLS") || connType.equals("SSL")) {
      secureTransportUsed = true;
    }
  }

    /**
     * Return the SPI version
     */ 
    public String getVersion()  {
  Version version = new Version();
  return (version.getJMSAdminSpiVersion());
    }

    /**
     * Create a ConnectionFactory administered object
     *
     * @param type        Either QUEUE or TOPIC.
     * @param properties  Connection specific properties.
     * @return New created ConnectionFactory administered object.
     * @exception JMSException thrown if connectionFactory could not be created.
     */
    public Object createConnectionFactoryObject(int type,
            java.util.Map properties)
           throws JMSException {

  Object cf = null;
  Properties tmpProps = getProperties(properties);

  fillDefaultConnectionFactoryProperties(tmpProps);

  if (type == TOPIC) {
      cf = JMSObjFactory.createTopicConnectionFactory(tmpProps);
  } else if (type == QUEUE) {
      cf = JMSObjFactory.createQueueConnectionFactory(tmpProps);
  } else {
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_INVALID_DOMAIN_TYPE));
  }
  return cf;
    }

    /**
     * Create a XAConnectionFactory administered object
     *
     * @param type        Either QUEUE or TOPIC.
     * @param properties Connection specific properties.
     * @return New created JMSXAConnectionFactory administered object.
     *                     ^^^^^
     * @exception JMSException thrown if XAConnectionFactory could not be
     * created.
     */
    public Object createXAConnectionFactoryObject(int type,
              java.util.Map properties)
           throws JMSException {

        Object xcf = null;
        Properties tmpProps = getProperties(properties);

    fillDefaultConnectionFactoryProperties(tmpProps);

        if (type == TOPIC) {
      xcf = new
      com.sun.messaging.jmq.jmsclient.JMSXATopicConnectionFactoryImpl();
      setProperties((AdministeredObject)xcf, tmpProps);

  } else if (type == QUEUE) {
      xcf = new
      com.sun.messaging.jmq.jmsclient.JMSXAQueueConnectionFactoryImpl();
      setProperties((AdministeredObject)xcf, tmpProps);

  } else {
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_INVALID_DOMAIN_TYPE));
        }
        return xcf;
    }


    /**
     * Create a Destination administered object
     *
     * @param destinationName The destination name.
     * @param type        Either QUEUE or TOPIC.
     * @param properties destination specific properties.
     * @return New created Destination administered object.
     * @exception JMSException thrown if destination object could not be
     * created.
     */
    public Object createDestinationObject(String destinationName,
                                          int type,
                                          java.util.Map properties)
                                          throws JMSException {
        Map props = properties;
  if (props == null) props = new Properties();
  props.put(DestinationConfiguration.imqDestinationName, destinationName);
        return createDestinationObject(type, props);
    }

    /**
     * Create a Destination administered object. The destination name
     * is assumed in properties like imqDestinationName=xxxxx
     *
     * @param type        Either QUEUE or TOPIC.
     * @param properties destination specific properties.
     * @return New created Destination administered object.
     * @exception JMSException thrown if destination object could not be
     * created.
     */
    public Object createDestinationObject(int type,
                                          java.util.Map properties)
                                          throws JMSException {
  if (properties == null ||
            properties.get(DestinationConfiguration.imqDestinationName) == null)
            throw new JMSException(ar.getKString(ar.X_JMSSPI_NO_DESTINATION_NAME));
  Object dest = null;

        Properties tmpProps = getProperties(properties);

        if (type == TOPIC) {
      dest = JMSObjFactory.createTopic(tmpProps);

  } else if (type == QUEUE) {
      dest = JMSObjFactory.createQueue(tmpProps);

  } else {
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_INVALID_DOMAIN_TYPE));
  }
        return dest;
    }

    /**
     * Wrap a standard JMS ConnectionFactory administered object
     *
     * @param obj a XAQueue/TopicConnectionFactory or Queue/TopicConnectionFactory object  
     * @return a JMSXAConnectionFactory object
     *                     ^^^^^
     * @exception JMSException if fail to wrap
     */
    public Object wrapJMSConnectionFactoryObject(Object obj) throws JMSException {
        if (obj instanceof javax.jms.XAQueueConnectionFactory)
            return new JMSXAWrappedConnectionFactoryImpl((javax.jms.XAQueueConnectionFactory)obj);
        if (obj instanceof javax.jms.XATopicConnectionFactory)
            return new JMSXAWrappedConnectionFactoryImpl((javax.jms.XATopicConnectionFactory)obj);
        if (obj instanceof javax.jms.QueueConnectionFactory)
            return new JMSXAWrappedConnectionFactoryImpl((javax.jms.QueueConnectionFactory)obj);
        if (obj instanceof javax.jms.TopicConnectionFactory)
            return new JMSXAWrappedConnectionFactoryImpl((javax.jms.TopicConnectionFactory)obj);

        throw new JMSException(ar.getKString(ar.X_JMSSPI_INVALID_OBJECT_TYPE));
    }

    public void validateJMSSelector(String selector) throws JMSException {
        com.sun.messaging.jmq.jmsselector.JMSSelector jmsselector =
                      new com.sun.messaging.jmq.jmsselector.JMSSelector();
        try {
            jmsselector.validateSelectorPattern(selector);
        }
        catch (com.sun.messaging.jmq.jmsselector.InvalidJMSSelectorException e) {
            throw new InvalidSelectorException(e.getMessage());           
        }
        catch (Exception e) {
            throw new JMSException(e.getMessage());           
        }
    }

    /**
     * @return the client-id property name
     */
    public String clientIDPropertyName() {
        return ConnectionConfiguration.imqConfiguredClientID;
    }

    /**
     * Returns a map of all the properties that a destination
     * object has.
     * <P>
     * For each property name returned, a corresponding label that can
     * be used for output display purposes is also returned.
     * The Map returned contains the property names and property
     * labels as key-value pairs. This information can be used to display
     * more readable output containing property labels and not property
     * names.
     *
     * @param type Either QUEUE or TOPIC.
     * @return Map containing attribute value pairs of property names
     *    and their display labels.
     */
    public Map getAllDestinationObjectProperties(int type)
            throws JMSException  {
  Properties  ret;

  if (tmpDestination == null)  {
      tmpDestination = (AdministeredObject)JMSObjFactory.createTopic(new Properties());
  }

  ret = new Properties();

  for (Enumeration e = tmpDestination.enumeratePropertyNames(); e.hasMoreElements();) {
      String propName = (String)e.nextElement();
      String propLabel = tmpDestination.getPropertyLabel(propName);
      ret.setProperty(propName, propLabel);
  }

  return (ret);
    }

    /**
     * Returns a subset of all the properties that a destination
     * object has.
     * <P>
     * This collection of properties can be used to construct a user
     * interface where not all of the object's properties will be
     * displayed, and only a selected few (more important) ones are.
     * <P>
     * For each property name returned, a corresponding label that can
     * be used for output display purposes is also returned.
     * The Map returned contains the property names and property
     * labels as key-value pairs. This information can be used to display
     * more readable output containing property labels and not property
     * names.
     *
     * @param type Either QUEUE or TOPIC.
     * @return Map containing attribute value pairs of property names
     *    and their display labels.
     */
    public Map getDisplayedDestinationObjectProperties(int type)
            throws JMSException  {
  Properties  ret;
  String    propName, propLabel;

  if (tmpDestination == null)  {
      tmpDestination = (AdministeredObject)JMSObjFactory.createTopic(new Properties());
  }

  ret = new Properties();

  propName = DestinationConfiguration.imqDestinationName;
  propLabel = tmpDestination.getPropertyLabel(propName);
  ret.setProperty(propName, propLabel);

  return (ret);
    }

    /**
     * Returns a map of all the properties that a connection factory
     * object has.
     * <P>
     * For each property name returned, a corresponding label that can
     * be used for output display purposes is also returned.
     * The Map returned contains the property names and property
     * labels as key-value pairs. This information can be used to display
     * more readable output containing property labels and not property
     * names.
     *
     * @param type Either QUEUE or TOPIC.
     * @return Map containing attribute value pairs of property names
     *    and their display labels.
     */
    public Map getAllConnectionFactoryObjectProperies(int type)
            throws JMSException  {
  Properties  ret;

  if (tmpConnFactory == null)  {
      tmpConnFactory =
        (AdministeredObject)JMSObjFactory.createTopicConnectionFactory(new Properties());
  }

  ret = new Properties();

  for (Enumeration e = tmpConnFactory.enumeratePropertyNames(); e.hasMoreElements();) {
      String propName = (String)e.nextElement();
      String propLabel = tmpConnFactory.getPropertyLabel(propName);
      ret.setProperty(propName, propLabel);
  }

  return (ret);
    }

    /**
     * Returns a subset of all the properties that a connection factory
     * object has.
     * <P>
     * This collection of properties can be used to construct a user
     * interface where not all of the object's properties will be
     * displayed, and only a selected few (more important) ones are.
     * <P>
     * For each property name returned, a corresponding label that can
     * be used for output display purposes is also returned.
     * The Map returned contains the property names and property
     * labels as key-value pairs. This information can be used to display
     * more readable output containing property labels and not property
     * names.
     *
     * @param type Either QUEUE or TOPIC.
     * @return Map containing attribute value pairs of property names
     *    and their display labels.
     */
    public Map getDisplayedConnectionFactoryObjectProperies(int type)
            throws JMSException  {
  Properties  ret;
  String    propName, propLabel;

  if (tmpConnFactory == null)  {
      tmpConnFactory =
        (AdministeredObject)JMSObjFactory.createTopicConnectionFactory(new Properties());
  }

  ret = new Properties();

  propName = ConnectionConfiguration.imqBrokerHostName;
  propLabel = tmpConnFactory.getPropertyLabel(propName);
  ret.setProperty(propName, propLabel);

  propName = ConnectionConfiguration.imqBrokerHostPort;
  propLabel = tmpConnFactory.getPropertyLabel(propName);
  ret.setProperty(propName, propLabel);

  propName = ConnectionConfiguration.imqConfiguredClientID;
  propLabel = tmpConnFactory.getPropertyLabel(propName);
  ret.setProperty(propName, propLabel);

  return (ret);
    }



    /**
     * Connect to the provider.
     * @exception JMSException thrown if connection to the provider
     * cannot be established or if an error occurs
     */
    public void connectToProvider() throws JMSException {
        connection = qcf.createQueueConnection(adminuserName, adminPassword);
        connection.setExceptionListener(this);
        connection.start();
        session = connection.createQueueSession
            (false, Session.CLIENT_ACKNOWLEDGE);
        requestQueue = session.createQueue(MessageType.JMQ_ADMIN_DEST);
        replyQueue = session.createTemporaryQueue();
        sender = session.createSender(requestQueue);
        sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        receiver = session.createReceiver(replyQueue);

  hello();
    }

    /**
     * Disconnect from the provider.
     * @exception JMSException thrown if connection to the provider cannot
     * be closed or ir an error occurs
     */
    public void disconnectFromProvider() throws JMSException {
        sender.close();
        receiver.close();
        session.close();

  try  {
            connection.close();
  } catch (JMSException jmse)  {
      if (!secureTransportUsed)  {
    throw (jmse);
      }
  }
    }

    /**
     * Create a physical Destination within the JMS Provider using the provided
     * properties to define provider specific attributes.
     * Destination is not automatically bound into JNDI namespace.
     *
     * @param destinationName
     * @param destinationType QUEUE or TOPIC
     * @param properties creation properties.
     * @return Identifier for newly created Destination.
     * @exception JMSException thrown if Queue could not be created.
     */
    public void createProviderDestination(String destinationName,
                                          int destinationType,
                                          java.util.Map properties)
        throws JMSException {

        ObjectMessage requestMesg = null;
        Message replyMesg = null;

        // Create DestinationInfo.
        DestinationInfo di = new DestinationInfo();
        di.setName(destinationName);

  // REVISIT:
  // We only check for queueDeliveryPolicy in the properties
  // hard-coded string; left here because we are not sure
  // if we are going to expose this attribute yet
  String qPolicy = null;

  /*
   * Early initialization to be used in error messages
   */
  int typeMask = this.getDestTypeMask(destinationType, null);

  if (properties != null)  {
      if (properties.containsKey("queueDeliveryPolicy")) {
          qPolicy = (String)properties.get("queueDeliveryPolicy");
          typeMask = this.getDestTypeMask(destinationType, qPolicy);
      }

      if (properties.containsKey(
    BrokerCmdOptions.PROP_NAME_MAX_ACTIVE_CONSUMER_COUNT)) {
    Object tmp = null;
    String val = null;
    tmp = properties.get(
        BrokerCmdOptions.PROP_NAME_MAX_ACTIVE_CONSUMER_COUNT);

    if (tmp != null)  {
        if (!(tmp instanceof String))  {
            JMSException jmse;
            jmse = new JMSException(
                ar.getString(ar.E_SPI_DEST_CREATION_FAILED,
        DestType.toString(typeMask),
                    destinationName)
          + "\n"
          + ar.getString(ar.E_SPI_ATTR_TYPE_NOT_STRING,
                    BrokerCmdOptions.PROP_NAME_MAX_ACTIVE_CONSUMER_COUNT)
          );

            throw jmse;
        }

        val = (String)tmp;

            try  {
            di.setMaxActiveConsumers(Integer.parseInt(val));
        } catch (Exception e)  {
            JMSException jmse;
            jmse = new JMSException(
                ar.getString(ar.E_SPI_DEST_CREATION_FAILED,
        DestType.toString(typeMask),
                    destinationName)
          + "\n"
          + ar.getString(ar.E_INVALID_INTEGER_VALUE,
                    val,
                    BrokerCmdOptions.PROP_NAME_MAX_ACTIVE_CONSUMER_COUNT));
                        throw (jmse);
                    }
    }
      }
  }

  di.setType(typeMask);

        requestMesg = session.createObjectMessage();
        requestMesg.setJMSReplyTo(replyQueue);
        requestMesg.setIntProperty
            (MessageType.JMQ_MESSAGE_TYPE, MessageType.CREATE_DESTINATION);
        requestMesg.setObject(di);
        sender.send(requestMesg);

        replyMesg = receiver.receive(timeout);
        replyMesg.acknowledge();

        checkReplyTypeStatus(replyMesg,
                             MessageType.CREATE_DESTINATION_REPLY,
                             "CREATE_DESTINATION_REPLY");
    }

    /**
     * Delete a physical destination within the JMS Provider.
     * @param type        Either QUEUE or TOPIC.
     * @param destinationName
     * @exception JMSException thrown if Queue could not be deleted.
     */
    public void deleteProviderDestination(String destinationName,
                                          int type)
        throws JMSException {
        ObjectMessage requestMesg = null;
        Message replyMesg = null;

        requestMesg = session.createObjectMessage();
        requestMesg.setJMSReplyTo(replyQueue);
        requestMesg.setIntProperty
            (MessageType.JMQ_MESSAGE_TYPE, MessageType.DESTROY_DESTINATION);
        requestMesg.setStringProperty(MessageType.JMQ_DESTINATION,
              destinationName);
        requestMesg.setIntProperty(MessageType.JMQ_DEST_TYPE,
           this.getDestTypeMask(type, null));
        sender.send(requestMesg);

        replyMesg = receiver.receive(timeout);
        replyMesg.acknowledge();

        checkReplyTypeStatus(replyMesg,
            MessageType.DESTROY_DESTINATION_REPLY,
            "DESTROY_DESTINATION_REPLY");
    }

    /**
     * Get all provider destinations.
     *
     * @return A multi dimensional array containing information
     *         about the JMS destinations. array[0] is a String[]
     *         listing the destination names. array[1] is a
     *         String[] listing the destination types.
     * @exception JMSException thrown if array could not be obtained.
     */
    public String[][] getProviderDestinations() throws JMSException {
        ObjectMessage mesg = null;

        mesg = session.createObjectMessage();
        mesg.setJMSReplyTo(replyQueue);
        mesg.setIntProperty
            (MessageType.JMQ_MESSAGE_TYPE, MessageType.GET_DESTINATIONS);
        sender.send(mesg);

        mesg = (ObjectMessage)receiver.receive(timeout);
        mesg.acknowledge();
        checkReplyTypeStatus(mesg, MessageType.GET_DESTINATIONS_REPLY,
            "GET_DESTINATIONS_REPLY");

  Object obj;
        if ((obj = mesg.getObject()) != null) {
            if (obj instanceof Vector)  {
          Vector dests = (Vector)obj;

    /*
     * Remove temporary, internal and admin destinations
     * by creating a new Vector and adding all the valid
     * destinations into this new Vector.
     */
    Vector validDests = new Vector();
 
    for (int i = 0; i < dests.size(); i++) {
        DestinationInfo di = (DestinationInfo)dests.elementAt(i);
        if ((!MessageType.JMQ_ADMIN_DEST.equals(di.name)) &&
            (!MessageType.JMQ_BRIDGE_ADMIN_DEST.equals(di.name)) &&
      (!DestType.isInternal(di.fulltype)) &&
      (!DestType.isTemporary(di.type))) {
      validDests.add(di);
        }
    }

          int numElements = validDests.size();
          String[][] destinations = new String[2][numElements];

          for (int i = 0; i < numElements; i++) {
            DestinationInfo di = (DestinationInfo)validDests.get(i);
        destinations[0][i] = di.name;
        destinations[1][i] = this.getDestinationType(di.type);
          }
          return destinations;
            }
        }
        return null;
    }

    /**
     * Start the provider.
     *
     * @param iMQHome Location of the broker executable.
     * @param optArgs Array of optional broker command line arguments.
     * @param serverName Instance name of the server.
     * @exception IOException thrown if the server startup fails.
     */
    public void startProvider(String iMQHome, String optArgs[],
        String serverName) throws IOException, JMSException {
        String iMQBrokerPath;
        String append = null;

        if (java.io.File.separator.equals("\\")) {
            // Windows path
            //    <iMQHome>\\imqbrokersvc.exe -console
            iMQBrokerPath  = iMQHome +
                java.io.File.separator + "imqbrokersvc.exe";
            append = "-console";
        }
        else {
            // Unix path.
            //    <iMQHome>/bin/imqbrokerd
            iMQBrokerPath  = iMQHome +
                java.io.File.separator + "imqbrokerd";
        }

        String portStr =
            qcf.getProperty(ConnectionConfiguration.imqBrokerHostPort);

        // Important : Do not change the command line parameter order
        // unless you know what you are doing. Here are the
        // constraints -
        //
        // 1. The "-javahome" argument, if present, must be first.
        //    Otherwise it does not work on Windows. The caller (of
        //    this method) is responsible for making sure that the
        //    "-javahome" argument is first in the 'optArgs' string.
        //
        // 2. The -name, -port and -silent arguments must be at
        //    placed at the end, so that they override anything
        //    specified in the optArgs...
        //
        // 3. The -bgnd argument is required for proper signal
        //    handling on solaris.
        //

        Vector v = new Vector();
        v.add(iMQBrokerPath);

        if (optArgs != null) {
            for (int i = 0; i < optArgs.length; i++)
                v.add(optArgs[i]);
        }

        if (serverName != null) {
            v.add("-name");
            v.add(serverName);
        }

        if (append != null)
            v.add(append);

        v.add("-port");
        v.add(portStr);
        // CR 6944162 Disable use of -bgnd (used on Solaris)
        // because it prevents passwords being passed to the broker via standard input
        //v.add("-bgnd");
       
        // disable use of -errorwarn if FINE logging is enabled
        if (!logger.isLoggable(Level.FINE)){
          // normally we only want to see errors in stdout
          v.add("-ttyerrors");
        }
        v.add("-managed");
        v.add("-read-stdin");

        String[] cmdLine = (String[]) v.toArray(new String[0]);
       
        // Log the command line we are about to execute
        if (logger.isLoggable(Level.FINE)){
          String commandLineToLog = "";
          for (int i = 0; i < cmdLine.length; i++) {
            commandLineToLog = commandLineToLog + cmdLine[i] + " ";
      }
          logger.fine("MQJMSRA: Starting LOCAL broker with command line: "+commandLineToLog);
        }

        launchAndWatch(cmdLine);
            
        }

  private void launchAndWatch(String[] cmdLine) throws IOException {
        Process p = Runtime.getRuntime().exec(cmdLine);

        BrokerWatcher brokerWatcher = new BrokerWatcher(p,cmdLine);
        brokerWatcher.setDaemon(true);
        brokerWatcher.start();
       
       
        // start a thread to log any error messages from the new broker as a WARN message
        boolean isError=true;
        StreamGobbler errorGobbler = new
            StreamGobbler(p.getErrorStream(), isError,"Local broker: ");         
        errorGobbler.setDaemon(true);
        errorGobbler.start();
       
        // start a thread to log any output messages from the new broker as an INFO message
        isError=false;
        StreamGobbler outputGobbler = new
            StreamGobbler(p.getInputStream(), isError,"Local broker: ");
        outputGobbler.setDaemon(true);
        outputGobbler.start();
       
    // generate the broker properties afresh
    Properties brokerProps = brokerPropertiesHolder.getProperties();
       
        // write properties to the input stream of the new process 
    try {
      OutputStreamWriter osw = new OutputStreamWriter(p.getOutputStream());
      BufferedWriter bw = new BufferedWriter(osw);
      for (Enumeration e = brokerProps.propertyNames(); e.hasMoreElements();) {
        String thisPropertyName = (String) e.nextElement();
        String thisPropertyValue = brokerProps.getProperty(thisPropertyName);
        bw.write(thisPropertyName + "=" + thisPropertyValue);
        bw.newLine();
      }
      if (this.adminPassword!=null){
        // if set, override any admin password set via brokerProps
        bw.write("imq.imqcmd.password="+this.adminPassword);
        bw.newLine();
      }
      bw.close();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
    }

    /**
     * Ping the provider.
     * @exception JMSException thrown if ping fails
     */
  public void pingProvider() throws JMSException {

    // temporarily turn off logging because we do not want to log a message if the provider is not running
    // as this might not be an error.
    Logger rootLogger = Logger.getLogger(ConnectionImpl.ROOT_LOGGER_NAME);
    Level savedLevel = rootLogger.getLevel();
    rootLogger.setLevel(Level.SEVERE);

    Connection pingConn = null;
    try {
      pingConn = qcf.createQueueConnection(adminuserName, adminPassword);
    } finally {
      // re-enable logging logging
      rootLogger.setLevel(savedLevel);
    }

    pingConn.setExceptionListener(this);
    pingConn.start();
    try {
      pingConn.close();
    } catch (JMSException jmse) {
      if (!secureTransportUsed) {
        throw (jmse);
      }
    }
  }

    /**
     * Ping the provider using the specified parameters.
     *
     * @param username Administrator username
     * @param password Administrator password
     * @param port MQ broker port
     *
     * @exception JMSException thrown if ping fails
     */
    public void pingProvider(String username, String password, int port)
      throws JMSException {
        QueueConnectionFactory    pingQcf;
        Connection      pingConn;
  Properties      props;

  /*
   * Get configuration used to create 'real' admin connections.
   */
  props = qcf.getConfiguration();

  /*
   * Create new connection factory and apply the above configuration
   * to it.
   */
        pingQcf = new QueueConnectionFactory();
        pingQcf.setConnectionType(ClientConstants.CONNECTIONTYPE_ADMIN);

        for (Enumeration e = props.propertyNames();
                         e.hasMoreElements();) {
            String propName = (String)e.nextElement();
            String value  = props.getProperty(propName);

            if (value != null)  {
                pingQcf.setProperty(propName, value);
            }
        }

  /*
   * Use specified port in his new connection factory.
   */
  pingQcf.setProperty(ConnectionConfiguration.imqBrokerHostPort,
      String.valueOf(port));

  /*
   * Create new connection object using specified username/password.
   */
        pingConn = pingQcf.createQueueConnection(username, password);

  /*
   * Perform ping operation.
   */
        pingConn.setExceptionListener(this);
        pingConn.start();
  try  {
            pingConn.close();
  } catch (JMSException jmse)  {
      if (!secureTransportUsed)  {
    throw (jmse);
      }
  }
    }

    /**
     * Get the property value from a provider
     * @exception JMSException thrown if the get fails.
     */
    private String getProviderPropertyValue(String propName) throws JMSException {
        ObjectMessage requestMesg = null;
        ObjectMessage replyMesg = null;
  String  propVal = null;

        requestMesg = session.createObjectMessage();
        requestMesg.setJMSReplyTo(replyQueue);
  requestMesg.setIntProperty
      (MessageType.JMQ_MESSAGE_TYPE, MessageType.GET_BROKER_PROPS);

  sender.send(requestMesg);

  replyMesg = (ObjectMessage)receiver.receive(timeout);
        replyMesg.acknowledge();

        checkReplyTypeStatus(replyMesg,
                             MessageType.GET_BROKER_PROPS_REPLY,
                             "GET_BROKER_PROPS_REPLY");

        Object obj;
        
  if ((obj = replyMesg.getObject()) != null) {
      if (obj instanceof Properties)  {
    Properties  props = (Properties)obj;
    propVal = props.getProperty(propName);
      }
  }

  return (propVal);
    }

    /**
     * Get the instance name of the provider
     * @exception JMSException thrown if the get fails.
     */
    public String getProviderInstanceName() throws JMSException {
        return(getProviderPropertyValue(
    BrokerConstants.PROP_NAME_BKR_INSTANCE_NAME));
    }

    /**
     * Get the VARHOME directory of the provider
     * @exception JMSException thrown if the get fails.
     */
    public String getProviderVarHome() throws JMSException {
        return(getProviderPropertyValue(
    BrokerConstants.PROP_NAME_BKR_VARHOME));
    }


    /**
     * Shutdown the provider.
     * @exception JMSException thrown if the shutdown fails
     * @throws 
     */
    public void shutdownProvider() throws JMSException {       
        try {
          tryToShutdownProvider();
    } catch (JMSException jmse) {
      if ((com.sun.messaging.jmq.jmsclient.resources.ClientResources.X_CONSUMER_CLOSED.equals(jmse.getErrorCode())) |
                (com.sun.messaging.jmq.jmsclient.resources.ClientResources.X_SESSION_CLOSED.equals(jmse.getErrorCode()))) {
        // we seem to have lost the connection - try once to reconnect before giving up
          try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {}
          connectToProvider();
          tryToShutdownProvider();
      } else {
        // re-throw the exception if not X_CONSUMER_CLOSED or X_SESSION_CLOSED
        throw jmse;
      }   
    }
    }
   
  private void tryToShutdownProvider() throws JMSException {
    ObjectMessage requestMesg;
    Message replyMesg;
    requestMesg = session.createObjectMessage();
    requestMesg.setJMSReplyTo(replyQueue);
    requestMesg.setIntProperty(MessageType.JMQ_MESSAGE_TYPE,MessageType.SHUTDOWN);
    sender.send(requestMesg);
   
    // disable reconnect since we don't want the client to try to reconnect
    //ConnectionImpl ci = (ConnectionImpl)connection;
    //ci.setImqReconnect(false);
   
    replyMesg = receiver.receive(timeout);
    checkReplyTypeStatus(replyMesg, MessageType.SHUTDOWN_REPLY,"SHUTDOWN_REPLY");
  }

    /**
   * Restart the provider.
   *
   * @exception JMSException
   *                thrown if the restart fails
   */
    public void restartProvider() throws JMSException {
        ObjectMessage requestMesg = null;
        Message replyMesg = null;

        requestMesg = session.createObjectMessage();
        requestMesg.setJMSReplyTo(replyQueue);
        requestMesg.setIntProperty
            (MessageType.JMQ_MESSAGE_TYPE, MessageType.SHUTDOWN);
        requestMesg.setBooleanProperty(MessageType.JMQ_RESTART, true);
        sender.send(requestMesg);

        replyMesg = receiver.receive(timeout);
        checkReplyTypeStatus(replyMesg, MessageType.SHUTDOWN_REPLY,
             "SHUTDOWN_REPLY");
    }

    /**
     * Return the provider host name
     * @exception JMSException
     */
    public String getProviderHostName() throws JMSException {
        return qcf.getProperty(ConnectionConfiguration.imqBrokerHostName);
    }

    /**
     * Return the provider host port number
     * @exception JMSException
     */
    public String getProviderHostPort() throws JMSException {
        return qcf.getProperty(ConnectionConfiguration.imqBrokerHostPort);
    }

    /**
     * Delete provider instance.
     *
     * @param mqBinDir Location of MQ's bin directory, which contains
     * the broker executable.
     * @param optArgs Optional broker command line arguments.
     * @param serverName instance name of MQ broker to delete
     * @exception JMSException thrown if the delete fails.
     */
    public void deleteProviderInstance(String mqBinDir,
        String optArgs,
        String serverName) throws IOException, JMSException  {
        String iMQBrokerPath;
  int exitCode = 0;
  boolean interrupted = false;

        if (java.io.File.separator.equals("\\")) {
            // Windows path
            //    <mqBinDir>\\bin\\imqbrokerd.exe
            iMQBrokerPath  = mqBinDir +
                java.io.File.separator + "imqbrokerd.exe";
        }
        else {
            // Unix path.
            //    <mqBinDir>/bin/imqbrokerd
            iMQBrokerPath  = mqBinDir +
                java.io.File.separator + "imqbrokerd";
        }

        String portStr =
            qcf.getProperty(ConnectionConfiguration.imqBrokerHostPort);

        // Important : Do not change the command line parameter order
        // unless you know what you are doing. Here are the
        // constraints -
        //
        // 1. The "-javahome" argument, if present, must be first.
        //    Otherwise it does not work on Windoze. The caller (of
        //    this method) is responsible for making sure that the
        //    "-javahome" argument is first in the 'optArgs' string.
        //
        // 2. The -name, -port and -silent arguments must be at
        //    placed at the end, so that they override anything
        //    specified in the optArgs...
        //
        // 3. The -bgnd argument is required for proper signal
        //    handling on solaris.
        //

        String cmdLine = iMQBrokerPath;
        if (optArgs != null)
            cmdLine = cmdLine + " " + optArgs;
        if (serverName != null)
            cmdLine = cmdLine + " -name " + serverName;
        cmdLine = cmdLine + " -remove instance -silent -force";

        Process p = Runtime.getRuntime().exec(cmdLine);

        // Close the receiver end of stdout and stderr streams.
        // Otherwise the child process blocks while trying to
        // write...
        p.getInputStream().close();
        p.getErrorStream().close();

  try  {
      p.waitFor();
      exitCode = p.exitValue();
  } catch (InterruptedException iex)  {
      interrupted = true;
  }

  if (interrupted)  {
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_INT_PREM,
        serverName));
  }
 
  /*
   * Proper handling of exit codes will be done once the following
   * bug is fixed:
   * 4713518 - imqbrokerd -remove: Enhancements needed for app server
   *    integration
   */
  switch (exitCode)  {
  case BrokerExitCode.NORMAL:
  break;

  case BrokerExitCode.INSTANCE_NOT_EXISTS:
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_NOT_EXIST,
        serverName));

  case BrokerExitCode.INSTANCE_BEING_USED:
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_BEING_USED,
        serverName));

  case BrokerExitCode.NO_PERMISSION_ON_INSTANCE:
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_NO_PERM,
        serverName));

  case BrokerExitCode.PROBLEM_REMOVING_PERSISTENT_STORE:
      throw new javax.jms.JMSException(
    ar.getKString(ar.X_JMSSPI_DELETE_INST_PROB_RM_STORE, serverName));

  case BrokerExitCode.IOEXCEPTION:
      throw new javax.jms.JMSException(
    ar.getKString(ar.X_JMSSPI_DELETE_INST_IOEXCEPTION, serverName));

  default:
      throw new javax.jms.JMSException(
    ar.getKString(ar.X_JMSSPI_DELETE_INST_UNKNOWN, serverName));
  }
    }

    /**
     * Delete provider instance.
     *
     * @param mqBinDir Location of MQ's bin directory, which contains
     * the broker executable.
     * @param optArgs Array of optional broker command line arguments.
     * @param serverName instance name of MQ broker to delete
     * @exception JMSException thrown if the delete fails.
     */
    public void deleteProviderInstance(String mqBinDir,
        String optArgs[],
        String serverName) throws IOException, JMSException  {
        String iMQBrokerPath;
  int exitCode = 0;
  boolean interrupted = false;

        if (java.io.File.separator.equals("\\")) {
            // Windows path
            //    <mqBinDir>\\bin\\imqbrokerd.exe
            iMQBrokerPath  = mqBinDir +
                java.io.File.separator + "imqbrokerd.exe";
        }
        else {
            // Unix path.
            //    <mqBinDir>/bin/imqbrokerd
            iMQBrokerPath  = mqBinDir +
                java.io.File.separator + "imqbrokerd";
        }

        String portStr =
            qcf.getProperty(ConnectionConfiguration.imqBrokerHostPort);

        // Important : Do not change the command line parameter order
        // unless you know what you are doing. Here are the
        // constraints -
        //
        // 1. The "-javahome" argument, if present, must be first.
        //    Otherwise it does not work on Windoze. The caller (of
        //    this method) is responsible for making sure that the
        //    "-javahome" argument is first in the 'optArgs' string.
        //
        // 2. The -name, -port and -silent arguments must be at
        //    placed at the end, so that they override anything
        //    specified in the optArgs...
        //
        // 3. The -bgnd argument is required for proper signal
        //    handling on solaris.
        //

        Vector v = new Vector();
        v.add(iMQBrokerPath);

        if (optArgs != null) {
            for (int i = 0; i < optArgs.length; i++)
                v.add(optArgs[i]);
        }

        if (serverName != null) {
            v.add("-name");
            v.add(serverName);
        }

        v.add("-remove");
        v.add("instance");
        v.add("-silent");
        v.add("-force");

        String[] cmdLine = (String[]) v.toArray(new String[0]);
        Process p = Runtime.getRuntime().exec(cmdLine);

        // Close the receiver end of stdout and stderr streams.
        // Otherwise the child process blocks while trying to
        // write...
        p.getInputStream().close();
        p.getErrorStream().close();

  try  {
      p.waitFor();
      exitCode = p.exitValue();
  } catch (InterruptedException iex)  {
      interrupted = true;
  }

  if (interrupted)  {
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_INT_PREM,
        serverName));
  }
 
  /*
   * Proper handling of exit codes will be done once the following
   * bug is fixed:
   * 4713518 - imqbrokerd -remove: Enhancements needed for app server
   *    integration
   */
  switch (exitCode)  {
  case BrokerExitCode.NORMAL:
  break;

  case BrokerExitCode.INSTANCE_NOT_EXISTS:
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_NOT_EXIST,
        serverName));

  case BrokerExitCode.INSTANCE_BEING_USED:
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_BEING_USED,
        serverName));

  case BrokerExitCode.NO_PERMISSION_ON_INSTANCE:
      throw new javax.jms.JMSException(ar.getKString(ar.X_JMSSPI_DELETE_INST_NO_PERM,
        serverName));

  case BrokerExitCode.PROBLEM_REMOVING_PERSISTENT_STORE:
      throw new javax.jms.JMSException(
    ar.getKString(ar.X_JMSSPI_DELETE_INST_PROB_RM_STORE, serverName));

  case BrokerExitCode.IOEXCEPTION:
      throw new javax.jms.JMSException(
    ar.getKString(ar.X_JMSSPI_DELETE_INST_IOEXCEPTION, serverName));

  default:
      throw new javax.jms.JMSException(
    ar.getKString(ar.X_JMSSPI_DELETE_INST_UNKNOWN, serverName));
  }

    }

    private void hello() throws JMSException {
        ObjectMessage requestMesg = null;
        Message replyMesg = null;

        requestMesg = session.createObjectMessage();
        requestMesg.setJMSReplyTo(replyQueue);
        requestMesg.setIntProperty
            (MessageType.JMQ_MESSAGE_TYPE, MessageType.HELLO);
        sender.send(requestMesg);

        replyMesg = receiver.receive(timeout);
        replyMesg.acknowledge();
        checkReplyTypeStatus
            (replyMesg, MessageType.HELLO_REPLY, "HELLO_REPLY");
    }

    /*
     * Map is an interface and its implementation can be anything that
     * implements the Map interface.  Whatever it is, convert it to a
     * Properties object.
     */
    private Properties getProperties(java.util.Map properties) {

        Properties tmpProps = null;

        if (properties == null)
            tmpProps = new Properties();

        else if (properties instanceof Properties) {
            tmpProps = (Properties)properties;

        } else {
            tmpProps = new Properties();
            Iterator iterator = properties.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry)iterator.next();
                tmpProps.put(entry.getKey(), entry.getValue());
            }
        }
        return tmpProps;
    }

    /*
     * Set the properties on this object.
     */
    private static void setProperties(AdministeredObject obj,
                                Properties objProps)
                                throws JMSException {
        /*
         * Set the specified properties on the new object.
         */
        for (Enumeration e = objProps.propertyNames(); e.hasMoreElements();) {

            String propName = (String)e.nextElement();
            String value  = objProps.getProperty(propName);
            if (value != null)
                obj.setProperty(propName, value);
        }
    }

    private void createFactory(Properties connectionProps)
        throws JMSException {

        qcf = new QueueConnectionFactory();
        qcf.setConnectionType(ClientConstants.CONNECTIONTYPE_ADMIN);

        for (Enumeration e = connectionProps.propertyNames();
                         e.hasMoreElements();) {
            String propName = (String)e.nextElement();
            String value  = connectionProps.getProperty(propName);

            if (value != null)  {
                qcf.setProperty(propName, value);
            }
        }
    }

  private void fillDefaultConnectionFactoryProperties(Properties props)
    throws JMSException {

    String val;
    if (props.getProperty(ConnectionConfiguration.imqBrokerHostName) == null &&
      (val=qcf.getProperty(ConnectionConfiguration.imqBrokerHostName)) != null) {
      props.setProperty(ConnectionConfiguration.imqBrokerHostName, val);     
    }
    if (props.getProperty(ConnectionConfiguration.imqBrokerHostPort) == null &&
      (val=qcf.getProperty(ConnectionConfiguration.imqBrokerHostPort)) != null) {
      props.setProperty(ConnectionConfiguration.imqBrokerHostPort, val);     
    }
  }

    // REVISIT:
    // hard-coded string
    private static int getDestTypeMask(int type, String policy) {
        int mask = -1;

  if (type == TOPIC)
      mask = DestType.DEST_TYPE_TOPIC;
  else if (type == QUEUE)
      mask = DestType.DEST_TYPE_QUEUE;

  if (policy == null)
      return mask;

  if (type == QUEUE) {
            if (policy.equals("s")) {
                mask |= DestType.DEST_FLAVOR_SINGLE;
            } else if (policy.equals("f")) {
                mask |= DestType.DEST_FLAVOR_FAILOVER;
            } else if (policy.equals("r")) {
                mask |= DestType.DEST_FLAVOR_RROBIN;
      }
  }
  return mask;
    }

    private static String getDestinationType(int mask) {
        if (DestType.isTopic(mask))
            return String.valueOf(TOPIC);
        else if (DestType.isQueue(mask))
            return String.valueOf(QUEUE);
        else
            return String.valueOf(UNKNOWN);
    }

    private void checkReplyTypeStatus(Message mesg,
                    int msgType,
                    String msgTypeString)
  throws JMSException {

        int actualMsgType = -1,
            actualReplyStatus = -1;

        /* There is a timing problem in the protocol. 
           The GOODBYE message could be processed before the SHUTDOWN_REPLY
           message and therefore could be sending null as a value for 'mesg'
           when receive() returns.  We will assume that the SHUTDOWN operation
           was successful when we receive status == 200 or mesg == null.
         */
        if (mesg == null)  {
            if (msgType == MessageType.SHUTDOWN_REPLY) {
                return;
            }
        }

        actualMsgType = mesg.getIntProperty(MessageType.JMQ_MESSAGE_TYPE);
        actualReplyStatus = mesg.getIntProperty(MessageType.JMQ_STATUS);

        if ((msgType == actualMsgType) &&
            (actualReplyStatus == MessageType.OK))
            return;

        /*
         * Otherwise, report an error
         */
  String error = null;
  try {
            error = mesg.getStringProperty(MessageType.JMQ_ERROR_STRING);
  } catch (Exception e) {
  } 
  throw new JMSException(error);
    }

    /*
     * BEGIN INTERFACE ExceptionListener
     */
    public void onException(JMSException jmse) {
    }
    /*
     * END INTERFACE ExceptionListener
     */
   
    class BrokerWatcher extends Thread {
      Process p;
      String[] cmdLine;

    BrokerWatcher(Process p, String[] cmdLine) {
      this.p=p;
      this.cmdLine=cmdLine;
    }

    public void run() {
      logger.fine("BrokerWatcher started");
      try {
        int status = p.waitFor();
        logger.fine("BrokerWatcher: Broker returned with status="+status);
        if (status==255){
          // restart broker
          launchAndWatch(cmdLine);
          logger.fine("BrokerWatcher terminating after restarting broker");
        }
        logger.fine("BrokerWatcher terminating after normal exit");
      } catch (InterruptedException e) {
        logger.warning("InterruptedException watching broker: "+e.getMessage());
      } catch (IOException e) {
        logger.warning("Error restarting broker: "+e.getMessage());
      }

    }
    }
   
    class StreamGobbler extends Thread {
    InputStream is;
    boolean isError;
    String prefix;

    /**
     *
     * @param is
     * @param isError If true, log messages as a WARN message. Otherwise log messages as an INFO message
     * @param prefix
     */
    StreamGobbler(InputStream is, boolean isError, String prefix) {
      this.is = is;
      this.isError = isError;
      this.prefix = prefix;
    }

    public void run() {
      try {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line = null;
        String message = prefix;
        int noOfLines=0;
        while ((line = br.readLine()) != null) {
          noOfLines++;
          if (noOfLines>1) {
            message = message + "\n";
          }
          message = message  + line;
        }

        if (noOfLines>0) {
          if (isError) {
            logger.warning(message);
          } else {
            logger.info(message);
          }
        }
      } catch (IOException ioe) {
        ioe.printStackTrace();
      }
    }
    }

}
TOP

Related Classes of com.sun.messaging.jmq.admin.jmsspi.JMSAdminImpl$StreamGobbler

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.