Package com.sun.jini.qa.harness

Source Code of com.sun.jini.qa.harness.ActivatableServiceStarterAdmin

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.sun.jini.qa.harness;

import com.sun.jini.start.ServiceStarter;
import com.sun.jini.start.SharedActivatableServiceDescriptor;
import com.sun.jini.start.ServiceDescriptor;

import java.io.File;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.activation.ActivationGroup;
import java.rmi.activation.ActivationGroupID;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationException;
import java.rmi.MarshalledObject;
import java.rmi.NoSuchObjectException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Properties;

import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.Subject;

import net.jini.admin.Administrable;
import net.jini.admin.JoinAdmin;
import net.jini.config.Configuration;
import net.jini.config.ConfigurationProvider;
import net.jini.config.ConfigurationException;
import net.jini.config.NoSuchEntryException;
import net.jini.core.discovery.LookupLocator;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.lookup.DiscoveryAdmin;
import net.jini.security.ProxyPreparer;

/**
* An admin for an activatable service which uses {@link
* com.sun.jini.start.SharedActivatableServiceDescriptor} to start the service,
* and which uses {@link com.sun.jini.qa.harness.ServiceDestroyer} to stop the
* service. The parameters which define the service are obtained as described in
* {@link com.sun.jini.qa.harness.AbstractServiceAdmin} extended by this
* implementation. Additional parameter defined by this admin include:
* <p>
* <table align=center>
*    <tr><td>restart    <td>boolean value for the restart flag
* </table>
* <p>
*
* The logger named <code>com.sun.jini.qa.harness.service</code> is used
* to log debug information
*
* <table border=1 cellpadding=5>
*
*<tr> <th> Level <th> Description
*
*<tr> <td> FINE <td> parameter values used to start the service, and a
*                    message indicating whether shared VM mode is being used
*</table> <p>
*/
public class ActivatableServiceStarterAdmin
                             extends AbstractServiceAdmin
                             implements Admin
{

    /** the service proxy */
    private Object serviceRef;

    /** the admin for the group used by this service */
    private SharedGroupAdmin groupAdmin;

    /** the name of the shared group persistence directory */
    private String sharedLogDirName;

    /** the value of the activation restart parameter */
    private boolean restart;

    /** the created object returned by the service descriptor */
    private SharedActivatableServiceDescriptor.Created created;

    /** the admin manager */
    private AdminManager manager;

    /** flag indicating whether this service is running shared */
    private boolean privateGroup = false;

    /**
     * Construct an <code>ActivatableServiceStarterAdmin</code>.
     *
     * @param config         the property set object for the test run
     * @param serviceName    the prefix used to build the property
     *                       names needed to acquire service parameters
     * @param index       the instance number for this service
     * @param manager        the admin manager for this test
     */
    public ActivatableServiceStarterAdmin(QAConfig config,
                                          String serviceName,
                                          int index,
            AdminManager manager)
    {
  super(config, serviceName, index);
  this.groupAdmin = manager.getSharedGroupAdmin();
  this.manager = manager;
    }

    /**
     * Return the <code>ActivationGroupID</code> associated with the
     * service started by this admin.
     *
     * @return the group ID, or <code>null</code> if the service has
     *         not been started
     */
    public ActivationGroupID getGroupID() {
  return (created == null ? null : created.gid);
    }
   
    /**
     * Return the <code>ActivationID</code> associated with the
     * service started by this admin.
     *
     * @return the activation ID, or <code>null</code> if the service has
     *         not been started
     */
     public ActivationID getActivationID() {
  return (created == null ? null : created.aid);
    }

    /* inherit javadoc */
    public Object getProxy() {
  return serviceRef;
    }

    /**
     * Configures and starts an instance of the service described by the
     * <code>serviceName</code> provided in the constructor.
     * This method retrieves several parameters by constructing parameter
     * names using the prefix and a set of well-known tokens.
     * <p>
     * The option arguments for the service are generated, containing the name
     * of the service configuration file and overrides for the groups, locators
     * membergroups, and persistence log entries to be used by the service.
     * A <code>SharedActivatableServiceDescriptor</code> is created using these
     * arguments and other required parameters (i.e. classpath, codebase, etc).
     * If a descriptor transformer was registered with this admin, the
     * transformers <code>transform</code> method is called with the
     * descriptor before calling the descriptors <code>create</code> method.
     * <p>
     * If a <code>SharedGroupAdmin</code> was not provided in the constructor,
     * one is created and started when <code>getServiceSharedLogDir</code> is
     * called in the service descriptor constructor.  The
     * <code>serviceName</code> used to construct the admin for the shared group
     * is <code>"sharedGroup"</code>. If the shared group must be created and
     * the activation system is not running, the activation system will be
     * started.
     * <p>
     * After the service is started, the service proxy is prepared
     * using the prepared using the prepared name returned by the
     * <code>getServicePreparerName</code> method.
     * <p>
     * This admin administratively sets the lookup port, lookup group
     * and locators, and any member groups that were specified and
     * also passed as overrides. This behavior is considered <b>temporary</b>
     * until all services have been converted to honor the override
     * entry names.
     *
     * @throws TestException    if any of the mandatory service starter
     *                          parameters cannot be found. The mandatory
     *                          well-known tokens are: <code>impl,
     *                          codebase, classpath, policyfile</code>.
     *                          It is also thrown if any
     *                          exception is thrown while attempting to start
     *                          the service, or if generation of the
     *                          configuration file fails.
     * @throws RemoteException  never. Any <code>RemoteExceptions</code> which
     *                          occur while attempting to start the service
     *                          will be wrapped in a
     *                          {@link com.sun.jini.qa.harness.TestException}
     */
    public void start() throws RemoteException, TestException {
  try {
      // generate the overrides string array
      ArrayList optionsList = new ArrayList();
        addServiceConfigurationFileName(optionsList);
      addServiceGroupsAndLocators(optionsList);
      addServiceMemberGroups(optionsList);
      addServiceUnicastDiscoveryPort(optionsList);
      addServicePersistenceLog(optionsList);
      addServiceExporter(optionsList);
      addRegisteredOverrides(optionsList);
      String[] serviceConfigArgs =
    (String[]) optionsList.toArray(new String[optionsList.size()]);
      // if a sharedGroup does not exist for this service,
      // one will be created by getServiceSharedLogDir().
      // The check for the activation system being up is done there
      SharedActivatableServiceDescriptor desc =
    new SharedActivatableServiceDescriptor(
            getServiceCodebase(),
            getServicePolicyFile(),
            getServiceClasspath(),
            getServiceImpl(),
            getServiceSharedLogDir(),
            serviceConfigArgs,
            getServiceRestart(),
            getServiceActivationHost(),
            getServiceActivationPort());
                  
      // get starter config and preparer name now so it will
      // show up in the log
      Configuration starterConfig = getStarterConfiguration();
      getServicePreparerName();
      logServiceParameters(); // log debug output
      logOverrides(serviceConfigArgs);
      if (transformer != null) {
    desc = (SharedActivatableServiceDescriptor)
           transformer.transform(desc);
      }
      created = (SharedActivatableServiceDescriptor.Created)
          desc.create(starterConfig);
  } catch (ConfigurationException e) {
      throw new TestException("Configuration problem for "
                                   + serviceName, e);
  } catch (Exception e) {
      throw new TestException("Problem creating service for "
           + serviceName, e);
  }
        //XXX temporary work-around for jrmp dgc problem
  try {
      serviceRef = new MarshalledObject(created.proxy).get();
        } catch (IOException e) {
      throw new TestException("Problem unmarshalling proxy", e);
        } catch (ClassNotFoundException e) {
            throw new TestException("Problem unmarshalling proxy", e);
        }
  serviceRef = doProxyPreparation(serviceRef);
    }

    /**
     * Kill the service VM by calling the killVM method on the group admin.
     *
     * @throws RemoteException if a communications error occured while making
     *                         the remote call to the killVM backend server
     */
    public void killVM() throws RemoteException {
  groupAdmin.killVM();
    }

    /**
     * Administratively destroys the service managed by this admin, and waits
     * for up to <code>ServiceDestroyer.DEFAULT_N_SECS_WAIT</code> seconds for
     * the service to unregister its activation group from the activation
     * service. Failure to unregister is silently ignored. If the
     * activation group is private to this service, then the
     * activation group is also destroyed by calling the <code>stop</code>
     * method of it's admin.
     *
     * @throws RemoteException
     *         when a communication failure occurs between the front-end
     *         and the back-end of the service while attempting to destroy
     *         the service. When this exception does occur, the service may
     *         or may not have been successfully destroyed. If an
     *         <code>ActivationException</code> occurs, the exception is
     *         wrapped in a thrown <code>RemoteException</code>
     *
     */
    public void stop() throws RemoteException {
        try {
            stopAndWait(ServiceDestroyer.DEFAULT_N_SECS_WAIT);
        } catch (ActivationException e) {
            throw new RemoteException("Activation exception occurred "
                                    + "while stopping a service",
                                       e);
        }
    }
    /**
     * Administratively destroys the service managed by this admin.
     * This method attempts to verify that the desired service is actually
     * destroyed. If a private shared group is associated with this
     * service, this method will always attempt to destroy that group.
     * Failure to destroy the group will generate a stack trace but
     * will not affect the return semantics of the call.
     *
     * @param nSecsWait the number of seconds to wait for the service's
     *                  activation ID to be no longer registered with the
     *                  the activation system
     *
     * @return          <code>int</code> value that indicates either success or
     *                  one of a number of possible reasons for failure to
     *                  destroy the service. Possible values are:
     * <p><ul>
     *   <li> ServiceDestroyer.DESTROY_SUCCESS
     *   <li> ServiceDestroyer.SERVICE_NOT_ADMINISTRABLE - returned when
     *        the service to destroy is not an instance of
     *        net.jini.admin.Administrable
     *   <li> ServiceDestroyer.SERVICE_NOT_DESTROY_ADMIN - returned when
     *        the service to destroy is not an instance of
     *        com.sun.jini.admin.DestroyAdmin
     *   <li> ServiceDestroyer.DEACTIVATION_TIMEOUT - returned when the
     *        service's activation group is still registered with the
     *        activation system after the number of seconds to wait have passed
     *   <li> ServiceDestroyer.PERSISTENT_STORE_EXISTS - returned when the
     *        directory in which the service stores its persistent state
     *        still exists after the service has been successfully destroyed
     * </ul>
     *
     * @throws RemoteException
     *              typically, this exception occurs when
     *              there is a communication failure between the client and the
     *              service's backend. When this exception does occur, the
     *              service may or may not have been successfully destroyed.
     *
     * @throws ActivationException
     *              typically, this exception occurs when problems arise while
     *              attempting to interact with the activation system
     */
    public int stopAndWait(int nSecsWait)
               throws RemoteException, ActivationException
    {
  int destroyCode = ServiceDestroyer.DESTROY_SUCCESS;      
  try {
      if (created != null) {
    destroyCode =
        ServiceDestroyer.destroy(created,
               nSecsWait,
               config.getConfiguration());
      }
      return destroyCode;
  } catch (NoSuchObjectException e) {
      logger.log(Level.INFO,
           "Service Object is gone, presumed killed by test");
      return destroyCode;
  } finally {
      if (privateGroup) {
    logger.log(Level.FINE, "Destroying service-private group");
    try {
        groupAdmin.stop();
    } catch (Exception e) { // best effort
        logger.log(Level.INFO,
             "Attempt to stop private group failed",
             e);
    }
      }
  }
    }

    /**
     * Return the shared VM log directory name associated with this activatable
     * service. If a <code>SharedGroupAdmin</code> was not passed in the
     * constructor for this class, then if a global shared group is needed, that
     * group is created through the admin manager; otherwise, a
     * <code>SharedGroupAdmin</code> private to this service is created and its
     * <code>start</code> method is called.
     *
     * @return the shared vm log directory name
     * @throws TestException if this method attempts to start a shared
     *                       group and the attempt fails
     */
    protected String getServiceSharedLogDir() throws TestException {
  if (groupAdmin == null) {
      if (config.getBooleanConfigVal("com.sun.jini.qa.harness.shared",
             true))
      {
    Object group = null;
    try {
        group = manager.startService("sharedGroup");
    } catch (Exception e) {
        throw new TestException("Failed to start "
              + "global shared group", e);
    }
    groupAdmin = (SharedGroupAdmin) manager.getAdmin(group);
      } else {
    groupAdmin = new SharedGroupAdmin(config,
              "sharedGroup",
              index,
              getServiceOptions(),
              getServiceProperties(),
              manager);
    try {
        groupAdmin.start();
    } catch (Exception e) {
        throw new TestException("Failed to start shared group", e);
    }
    privateGroup = true;
      }
  }
  sharedLogDirName = groupAdmin.getSharedGroupLog().getAbsolutePath();
  return sharedLogDirName;
    }

    /**
     * Return the shared log directory name originally returned by the
     * <code>getServiceSharedLogDir</code> method.
     *
     * @return the service shared log directory name
     */
    public String getSharedLogDir() {
  return sharedLogDirName;
    }

    /**
     * Return the value of the restart parameter to use when registering
     * an activatable service. The environment is searched for a value
     * for the key <code>serviceName</code> + ".restart". The value
     * is interpreted as a boolean, and has the default value of
     * <code>true</code>.
     *
     * @return the value of the restart parameter
     */
    protected boolean getServiceRestart() {
  restart = config.getServiceBooleanProperty(serviceName,
               "restart",
               index,
               true);
  return restart;
    }

    /**
     * Return the restart value originally returned by the
     * <code>getServiceRestart</code> method.
     *
     * @return the service restart value
     */
    public boolean getRestart() {
  return restart;
    }

    /* inherit javadoc */
    protected void logServiceParameters() throws TestException {
  super.logServiceParameters();
        String val = getSharedLogDir();
  logger.logp(Level.FINE, null, null, "     shared log        : " + val);
        boolean bval = getRestart();
  logger.logp(Level.FINE, null, null, "     restart           : " + bval);
    }
}
TOP

Related Classes of com.sun.jini.qa.harness.ActivatableServiceStarterAdmin

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.