public class ASJMXAuthenticator implements JMXAuthenticator {

  private static final boolean _debug = false;

  private static Logger _logger = Logger.getLogger(AdminConstants.kLoggerName);

  private static StringManager _strings = StringManager.getManager(ASLoginDriverImpl.class);

  private String realmName;
  private LoginDriver loginDriver;

  public ASJMXAuthenticator() {}

  public ASJMXAuthenticator(String realmName) {
    setRealmName(realmName);
  }

  public void setRealmName(String realm) {
    // TODO: Add permission check.
    realmName = realm;
  }

  public String getRealmName() {
    return realmName;
  }

  public LoginDriver getLoginDriver() {
    return loginDriver;
  }

  public void setLoginDriver(LoginDriver driver) {
    // TODO: Add permission check.
    loginDriver = driver;
  }

  public Subject authenticate(Object credentials) {
    if (credentials == null) {
      if (_debug) {
        System.out.println("JMXAuthenticator: Null credentials sent from the client");
      }
      throwInvalidCredentialsException();
    }
    if (!(credentials instanceof String[])) {
      if (_debug) {
        System.out.println(
            "JMXAuthenticator: Invalid credentials sent from the client "
                + credentials.getClass().getName());
      }
      throwInvalidCredentialsException();
    }
    String[] userpass = (String[]) credentials;
    if (userpass.length != 2) {
      if (_debug) {
        System.out.println(
            "JMXAuthenticator: Invalid credentials sent from client, string array of length "
                + userpass.length);
      }
      throwInvalidCredentialsException();
    }
    if (_debug) {
      System.out.println(
          "JMX authentication request for user " + userpass[0] + " and password " + userpass[1]);
      System.out.println("Authentication realm is " + realmName);
    }

    Subject subject = null;
    if (loginDriver != null) {
      subject = loginDriver.login(userpass[0], userpass[1], realmName);
    } else {
      // TODO: WARNING message, JMX connector not protected
    }
    return subject;
  }

  private void throwInvalidCredentialsException() {
    throw new SecurityException(_strings.getString("admin.auth.invalid.credentials"));
  }
}
public class BaseElement {

  protected StringManager stringManager =
      StringManager.getManager(
          com.sun.enterprise.tools.upgrade.logging.LogService.UPGRADE_TRANSFORM_LOGGER);
  protected Logger logger =
      com.sun.enterprise.tools.upgrade.common.CommonInfoModel.getDefaultLogger();
  protected static CommonInfoModel commonInfoModel;

  /** Creates a new instance of Element */
  public BaseElement() {}

  public void transform(Element element, Element parentSource, Element parentResult) {
    NodeList childNodes = element.getChildNodes();
    logger.log(
        Level.FINE,
        stringManager.getString(
            "upgrade.transform.baseelemnt.transformingMSG", element.getTagName()));
    for (int index = 0; index < childNodes.getLength(); index++) {
      Node aNode = childNodes.item(index);
      try {
        if (aNode.getNodeType() == Node.ELEMENT_NODE) {
          BaseElement baseElement =
              ElementToObjectMapper.getMapper().getElementObject(aNode.getNodeName());
          baseElement.transform((Element) aNode, element, parentResult);
        }
      } catch (Exception ex) {
        // ****** LOG MESSAGE *************
        ex.printStackTrace();
        logger.log(
            Level.WARNING,
            stringManager.getString(
                "upgrade.transform.baseelement.transformexception",
                new String[] {element.getTagName(), ex.getMessage()}));
        // -logger.log(Level.WARNING,
        // stringManager.getString("upgrade.transform.baseelement.transformexception"), ex);
      }
    }
  }

  protected void transferAttributes(
      Element source, Element result, java.util.List nonTransferList) {
    boolean debug = false;
    NamedNodeMap sourceAttrNodeMap = source.getAttributes();
    if (sourceAttrNodeMap == null) return;

    NamedNodeMap resultAttrNodeMap = result.getAttributes();

    for (int index = 0; index < sourceAttrNodeMap.getLength(); index++) {
      Node sourceAttrNode = sourceAttrNodeMap.item(index);
      if (!this.canTransferAttribute(sourceAttrNode.getNodeName(), nonTransferList)) continue;
      if (!isValidAttributeToTransfer(
          sourceAttrNode.getNodeName(), getAttributeListForElement(result.getTagName()))) continue;
      if (resultAttrNodeMap == null) {
        Attr addAttr = result.getOwnerDocument().createAttribute(sourceAttrNode.getNodeName());
        addAttr.setValue(sourceAttrNode.getNodeValue());
        result.setAttributeNode(addAttr);
      } else {
        Node resultAttrNode = resultAttrNodeMap.getNamedItem(sourceAttrNode.getNodeName());
        if (resultAttrNode != null) {
          resultAttrNode.setNodeValue(sourceAttrNode.getNodeValue());
          // result.setAttributeNode((Attr)resultAttrNode);
        } else {
          Attr addAttr = result.getOwnerDocument().createAttribute(sourceAttrNode.getNodeName());
          addAttr.setValue(sourceAttrNode.getNodeValue());
          result.setAttributeNode(addAttr);
        }
      }
    }
  }

  private boolean canTransferAttribute(String attr, java.util.List attrList) {
    if (attrList == null || attrList.isEmpty()) return true;
    for (java.util.Iterator it = attrList.iterator(); it.hasNext(); ) {
      if (it.next().equals(attr)) return false;
    }
    return true;
  }

  public static void setCommonInfoModel(CommonInfoModel cim) {
    commonInfoModel = cim;
  }

  /*
   * Returns the key mapped in mapper for the element
   * This key is used for comparing source and target elements
   * Returns NULL if no key is mapped.  This is quite common for elements that have only child elements but no attributes to transfer
   */
  protected String getKeyToCompare(String elementTagName) {
    return ElementToObjectMapper.getMapper().getKeyForElement(elementTagName);
  }

  protected java.util.List getInsertElementStructure(Element element, Element parentEle) {
    // Sub classes can override this method to return a different list if needed.
    // parentEle is not used in this method.  But sub classes can use it to make certain decision on
    // structure
    return ElementToObjectMapper.getMapper().getInsertElementStructure(element.getTagName());
  }

  public void appendElementToParent(Element parentEle, Element element) {
    java.util.List eleStructureList = this.getInsertElementStructure(element, parentEle);
    if (eleStructureList == null) {
      // insert the element at the end
      parentEle.appendChild(element);
      return;
    }
    if (eleStructureList.isEmpty()) {
      // insert the element in the beginning.
      parentEle.insertBefore(element, parentEle.getFirstChild());
      return;
    }
    String insertBeforeElementName = null;
    Node insertBeforeNode = null;
    for (int eleIndex = 0; eleIndex < eleStructureList.size(); eleIndex++) {
      insertBeforeElementName = (String) eleStructureList.get(eleIndex);
      Node lNode = parentEle.getFirstChild();
      while (lNode != null) {
        if (lNode instanceof Element) {
          Element lElement = (Element) lNode;
          if (lElement.getNodeName().equals(insertBeforeElementName)) {
            // if match is found, break and insert
            insertBeforeNode = lNode;
            break;
          }
        }
        // go to next sibling in order
        lNode = lNode.getNextSibling();
      }
      if (insertBeforeNode != null) {
        break;
      }
    }
    // if match is not found, node will be place at the end
    parentEle.insertBefore(element, insertBeforeNode);
  }

  protected boolean isValidAttributeToTransfer(String attrName, java.util.List attrList) {
    for (java.util.Iterator it = attrList.iterator(); it.hasNext(); ) {
      if (((String) it.next()).equals(attrName)) {
        return true;
      }
    }
    return false;
  }

  protected java.util.List getAttributeListForElement(String elementName) {
    // String dtdFileName =
    // this.commonInfoModel.getTargetInstallDir()+File.separator+"lib"+File.separator+"dtds"+File.separator+"sun-domain_1_1.dtd";
    // Domain dtd changed for AS9.0
    String dtdName = null;
    if (UpgradeConstants.VERSION_91.equals(commonInfoModel.getTargetVersion())) {
      dtdName = "sun-domain_1_3.dtd";
    } else {
      dtdName = "sun-domain_1_2.dtd";
    }
    String dtdFileName =
        this.commonInfoModel.getTargetInstallDir()
            + File.separator
            + "lib"
            + File.separator
            + "dtds"
            + File.separator
            + dtdName;
    return AttributeExtracter.getExtracter(dtdFileName).getAttributeList(elementName);
  }
}
/**
 * Provides the implementation for an MBean that represents a node to give statistical data in the
 * form of its attributes.
 *
 * @author <a href="mailto:[email protected]">Kedar Mhaswade</a>
 * @since S1AS8.0
 * @version $Revision: 1.6 $
 */
class StatsHolderMBeanImpl implements DynamicMBean, StatsHolderMBean, MBeanRegistration {

  private static Logger logger = Logger.getLogger(AdminConstants.kLoggerName);
  private static StringManager sm = StringManager.getManager(StatsHolderMBeanImpl.class);
  private final StatsHolder delegate;
  private final StatsMediator mediator;
  private DottedNameRegistrar registrar;
  private MBeanInfo mi;
  private int state;
  private Object lock = new Object();
  public static final int INITIALIZED = 0;
  public static final int REGISTERED = 1;
  public static final int MBEANINFO_DONE = 2;
  public static final String JTA_FREEZE = "freeze";
  public static final String JTA_UNFREEZE = "unfreeze";
  public static final String JTA_ROLLBACK = "rollback";
  public static final String JTA_ACTIVE_TRANSACTIONS = "listActiveTransactions";
  public static final String JTA_RUNTIME_RECOVERY_REQUIRED = "isRecoveryRequired";
  public static final String DOTTED_NAME = "dotted-name";

  StatsHolderMBeanImpl(StatsHolder delegate) {
    assert (delegate != null);
    this.delegate = delegate;
    this.mediator = new StatsMediatorImpl(delegate.getStats(), delegate.getStatsClass());
    changeState(INITIALIZED);
  }

  public Object getAttribute(String name)
      throws AttributeNotFoundException, MBeanException, ReflectionException {
    if (name.equals(DOTTED_NAME)) return delegate.getDottedName();
    else return (mediator.getAttribute(name));
  }

  public AttributeList getAttributes(String[] names) {
    final AttributeList list = new AttributeList();
    for (int i = 0; i < names.length; i++) {
      try {
        final Attribute a = new Attribute(names[i], this.getAttribute(names[i]));
        list.add(a);
      } catch (Exception e) {
        if (logger.isLoggable(Level.FINEST)) {
          logger.finest("Error while accessing an attribute named: " + names[i]);
        }
        // The exception SHOULD BE squelched per the contract of this method
      }
    }
    return (list);
  }

  public MBeanInfo getMBeanInfo() {
    synchronized (lock) {
      if (state == MBEANINFO_DONE) {
        return mi;
      }
    }
    build();
    changeState(MBEANINFO_DONE);
    return (mi);
  }

  private void build() {
    final String name = StatsHolderMBeanImpl.class.getName();
    final String desc = getDescription();
    final MBeanAttributeInfo[] mais = mediator.getAttributeInfos();
    final MBeanConstructorInfo[] mcis = this.getConstructorInfos();
    final MBeanOperationInfo[] mois = this.getOperationInfos();
    final MBeanNotificationInfo[] mnis = this.getNotificationInfos();
    mi = new MBeanInfo(name, desc, mais, mcis, mois, mnis);
  }

  private String getDescription() {
    return "StatsHolder MBean for: " + StatsHolderMBeanImpl.class.getName();
  }

  private MBeanConstructorInfo[] getConstructorInfos() {
    final MBeanConstructorInfo[] cis = new MBeanConstructorInfo[0];
    return (cis); // we don't want management applications to create instances of this MBean
  }

  private MBeanOperationInfo[] getOperationInfos() {

    final ArrayList opInfo = new ArrayList();

    opInfo.add(getChildrenInfo());
    opInfo.add(getNameInfo());
    opInfo.add(getTypeInfo());
    // Add the additional ops only for StatsHolders that have an actual Stats object
    // associated with them
    if (delegate.getStats() != null) {
      opInfo.add(getStatisticNameInfo());
      opInfo.add(getStatsInfo());
    }

    MBeanOperationInfo[] mos = new MBeanOperationInfo[opInfo.size()];
    mos = (MBeanOperationInfo[]) opInfo.toArray(mos);

    // if we are dealing with JTAStats, we need to add the additional
    // operations freeze, unfreeze & rollback to the MBeanOerationInfo
    if (isJta()) return (getJTAOperationInfo(mos));

    return (mos);
  }

  public Object invoke(String method, Object[] params, String[] sign)
      throws MBeanException, ReflectionException {
    if ("getChildren".equals(method)) {
      return (this.getChildren());
    } else if ("getName".equals(method)) {
      return (this.getName());
    } else if ("getType".equals(method)) {
      return (this.getType());
    } else if ("getStatisticNames".equals(method)) {
      return (this.getStatisticNames());
    } else if ("getStatistics".equals(method)) {
      return (this.getStatistics());
    } else if (isJTAMethod(method)) {
      return (mediator.invoke(method, params, sign));
    } else {
      final String msg = sm.getString("smi.no_such_method", method);
      final Exception ae = new UnsupportedOperationException(msg);
      throw new MBeanException(ae);
    }
  }

  public void setAttribute(Attribute attribute)
      throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException,
          ReflectionException {
    throw new UnsupportedOperationException("NYI");
  }

  public AttributeList setAttributes(AttributeList attributes) {
    throw new UnsupportedOperationException("NYI");
  }

  public ObjectName[] getChildren() {
    final Collection c = delegate.getAllChildren();
    final ObjectName[] names = new ObjectName[c.size()];
    final Iterator it = c.iterator();
    int i = 0;
    while (it.hasNext()) {
      final StatsHolder s = (StatsHolder) it.next();
      names[i++] = s.getObjectName();
    }
    assert (names.length == i) : "Sizes don't match";
    return (names);
  }

  private MBeanOperationInfo getChildrenInfo() {
    final MBeanOperationInfo info =
        new MBeanOperationInfo(
            "getChildren",
            "Gets the children of this StatsHolder",
            null,
            ObjectName[].class.getName(),
            MBeanOperationInfo.INFO);
    return (info);
  }

  private MBeanNotificationInfo[] getNotificationInfos() {
    final MBeanNotificationInfo[] mns = new MBeanNotificationInfo[0];
    return (mns);
  }

  private boolean isJta() {
    boolean isJta = false;
    final Class cl = delegate.getStatsClass();
    if (cl != null) {
      if (com.sun.enterprise.admin.monitor.stats.JTAStats.class.getName().equals(cl.getName())) {
        isJta = true;
      }
    }
    return (isJta);
  }

  private boolean isJTAMethod(String methodName) {
    return ((JTA_FREEZE.equals(methodName))
        || (JTA_UNFREEZE.equals(methodName))
        || (JTA_ACTIVE_TRANSACTIONS.equals(methodName))
        || (JTA_RUNTIME_RECOVERY_REQUIRED.equals(methodName))
        || (JTA_ROLLBACK.equals(methodName)));
  }

  // Implementation of MBeanRegistration - start
  public void postDeregister() {}

  public void postRegister(Boolean registered) {
    if (registered.equals(Boolean.TRUE)) {
      registrar.registerDottedName(delegate.getDottedName(), delegate.getObjectName());
      changeState(REGISTERED);
    }
  }

  public void preDeregister() throws Exception {
    registrar.unregisterDottedName(delegate.getDottedName());
  }

  public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception {
    this.registrar = new DottedNameRegistrar(mBeanServer);
    return objectName;
  }
  // Implementation of MBeanRegistration - end

  private void changeState(int to) {
    synchronized (lock) {
      state = to;
    }
  }

  private MBeanOperationInfo[] getJTAOperationInfo(MBeanOperationInfo[] mos) {
    ArrayList opInfo = new ArrayList();
    for (int i = 0; i < mos.length; i++) opInfo.add(mos[i]);
    // not performing any reflection for now, as it is assumed that
    // only 3 methods will be added to the MBeanOperationInfo and
    // their names and signatures are fixed.
    MBeanOperationInfo mInfo =
        new MBeanOperationInfo(
            JTA_FREEZE,
            "Freezes the transaction service",
            null,
            void.class.getName(),
            MBeanOperationInfo.ACTION);

    opInfo.add(mInfo);

    mInfo =
        new MBeanOperationInfo(
            JTA_UNFREEZE,
            "Unfreezes the transaction service",
            null,
            void.class.getName(),
            MBeanOperationInfo.ACTION);

    opInfo.add(mInfo);
    mInfo =
        new MBeanOperationInfo(
            JTA_ROLLBACK,
            "Rollsback a given transaction",
            new MBeanParameterInfo[] {
              new MBeanParameterInfo(
                  "txnId", String.class.getName(), "Id of the transaction to be rolled back")
            },
            void.class.getName(),
            MBeanOperationInfo.ACTION);
    opInfo.add(mInfo);
    mInfo =
        new MBeanOperationInfo(
            JTA_ACTIVE_TRANSACTIONS,
            "Gets Active Transactions in a Map",
            null,
            List.class.getName(),
            MBeanOperationInfo.ACTION_INFO);
    opInfo.add(mInfo);
    mInfo =
        new MBeanOperationInfo(
            JTA_RUNTIME_RECOVERY_REQUIRED,
            "Returns if the recovery is required",
            null,
            Boolean.class.getName(),
            MBeanOperationInfo.ACTION_INFO);
    opInfo.add(mInfo);
    MBeanOperationInfo[] jtaOpInfo = new MBeanOperationInfo[opInfo.size()];
    return (MBeanOperationInfo[]) opInfo.toArray(jtaOpInfo);
  }

  public String getName() {
    return delegate.getName();
  }

  public String getType() {
    return delegate.getType().getTypeName();
  }

  private MBeanOperationInfo getNameInfo() {
    MBeanOperationInfo mInfo =
        new MBeanOperationInfo(
            "getName",
            "Gets the name of this StatsHolder",
            null,
            String.class.getName(),
            MBeanOperationInfo.INFO);
    return mInfo;
  }

  private MBeanOperationInfo getTypeInfo() {
    MBeanOperationInfo mInfo =
        new MBeanOperationInfo(
            "getType",
            "Gets the type of this StatsHolder",
            null,
            String.class.getName(),
            MBeanOperationInfo.INFO);
    return mInfo;
  }

  public String[] getStatisticNames() {
    Stats stats = delegate.getStats();
    if (stats != null) {
      return stats.getStatisticNames();
    } else {
      return null;
    }
  }

  public Statistic[] getStatistics() {
    Stats stats = delegate.getStats();
    if (stats == null) {
      return null;
    }

    Statistic[] statArray = stats.getStatistics();
    boolean isSerializable = checkSerializability(statArray);
    if (isSerializable) {
      final Statistic[] hackedArray = StatisticWorkaround.populateDescriptions(statArray);
      return hackedArray;
    } else return null;
  }

  private MBeanOperationInfo getStatisticNameInfo() {
    MBeanOperationInfo mInfo =
        new MBeanOperationInfo(
            "getStatisticNames",
            "Gets the names of all the statistics in the given Stats Object",
            null,
            String[].class.getName(),
            MBeanOperationInfo.INFO);
    return mInfo;
  }

  private MBeanOperationInfo getStatsInfo() {
    MBeanOperationInfo mInfo =
        new MBeanOperationInfo(
            "getStatistics",
            "returns the results of all the getXXX methods, in the given Stats object",
            null,
            Statistic[].class.getName(),
            MBeanOperationInfo.INFO);
    return mInfo;
  }

  private boolean checkSerializability(Object[] objArray) {
    boolean isSerializable = true;
    for (int i = 0; i < objArray.length; i++) {
      isSerializable = (isSerializable) && (objArray[i] instanceof java.io.Serializable);
    }
    return isSerializable;
  }
}
/** @author mvatkina */
public class TransactionServiceProperties {

  private static Logger _logger =
      LogDomains.getLogger(TransactionServiceProperties.class, LogDomains.TRANSACTION_LOGGER);

  private static StringManager localStrings =
      StringManager.getManager(TransactionServiceProperties.class);

  private static final String JTS_XA_SERVER_NAME = "com.sun.jts.xa-servername";
  private static final String J2EE_SERVER_ID_PROP = "com.sun.enterprise.J2EEServerId";
  private static final String JTS_SERVER_ID = "com.sun.jts.persistentServerId";
  private static final String HABITAT = "HABITAT";
  private static final int DEFAULT_SERVER_ID = 100;

  private static Properties properties = null;
  private static volatile boolean orbAvailable = false;
  private static volatile boolean recoveryInitialized = false;

  public static synchronized Properties getJTSProperties(
      ServiceLocator serviceLocator, boolean isORBAvailable) {
    if (orbAvailable == isORBAvailable && properties != null) {
      // We will need to update the properties if ORB availability changed
      return properties;
    }

    Properties jtsProperties = new Properties();
    if (serviceLocator != null) {
      jtsProperties.put(HABITAT, serviceLocator);
      ProcessEnvironment processEnv = serviceLocator.getService(ProcessEnvironment.class);
      if (processEnv.getProcessType().isServer()) {
        TransactionService txnService =
            serviceLocator.getService(
                TransactionService.class, ServerEnvironment.DEFAULT_INSTANCE_NAME);

        if (txnService != null) {
          jtsProperties.put(Configuration.HEURISTIC_DIRECTION, txnService.getHeuristicDecision());
          jtsProperties.put(Configuration.KEYPOINT_COUNT, txnService.getKeypointInterval());

          String automaticRecovery = txnService.getAutomaticRecovery();
          boolean isAutomaticRecovery =
              (isValueSet(automaticRecovery) && "true".equals(automaticRecovery));
          if (isAutomaticRecovery) {
            _logger.log(Level.FINE, "Recoverable J2EE Server");
            jtsProperties.put(Configuration.MANUAL_RECOVERY, "true");
          }

          boolean disable_distributed_transaction_logging = false;
          String dbLoggingResource = null;
          for (Property prop : txnService.getProperty()) {
            String name = prop.getName();
            String value = prop.getValue();

            if (name.equals("disable-distributed-transaction-logging")) {
              if (isValueSet(value) && "true".equals(value)) {
                disable_distributed_transaction_logging = true;
              }

            } else if (name.equals("xaresource-txn-timeout")) {
              if (isValueSet(value)) {
                _logger.log(Level.FINE, "XAResource transaction timeout is" + value);
                TransactionManagerImpl.setXAResourceTimeOut(Integer.parseInt(value));
              }

            } else if (name.equals("db-logging-resource")) {
              dbLoggingResource = value;
              _logger.log(Level.FINE, "Transaction DB Logging Resource Name" + dbLoggingResource);
              if (dbLoggingResource != null
                  && (" ".equals(dbLoggingResource) || "".equals(dbLoggingResource))) {
                dbLoggingResource = "jdbc/TxnDS";
              }

            } else if (name.equals("xa-servername")) {
              if (isValueSet(value)) {
                jtsProperties.put(JTS_XA_SERVER_NAME, value);
              }

            } else if (name.equals("pending-txn-cleanup-interval")) {
              if (isValueSet(value)) {
                jtsProperties.put("pending-txn-cleanup-interval", value);
              }

            } else if (name.equals(Configuration.COMMIT_ONE_PHASE_DURING_RECOVERY)) {
              if (isValueSet(value)) {
                jtsProperties.put(Configuration.COMMIT_ONE_PHASE_DURING_RECOVERY, value);
              }
            } else if (name.equals("add-wait-point-during-recovery")) {
              if (isValueSet(value)) {
                try {
                  FailureInducer.setWaitPointRecovery(Integer.parseInt(value));
                } catch (Exception e) {
                  _logger.log(Level.WARNING, e.getMessage());
                }
              }
            }
          }

          if (dbLoggingResource != null) {
            disable_distributed_transaction_logging = true;
            jtsProperties.put(Configuration.DB_LOG_RESOURCE, dbLoggingResource);
          }

          /**
           * JTS_SERVER_ID needs to be unique for each for server instance. This will be used as
           * recovery identifier along with the hostname for example: if the hostname is 'tulsa' and
           * iiop-listener-port is 3700 recovery identifier will be tulsa,P3700
           */
          int jtsServerId = DEFAULT_SERVER_ID; // default value

          if (isORBAvailable) {
            jtsServerId =
                serviceLocator
                    .<GlassFishORBHelper>getService(GlassFishORBHelper.class)
                    .getORBInitialPort();
            if (jtsServerId == 0) {
              // XXX Can this ever happen?
              jtsServerId = DEFAULT_SERVER_ID; // default value
            }
          }
          jtsProperties.put(JTS_SERVER_ID, String.valueOf(jtsServerId));

          /* ServerId is an J2SE persistent server activation
            API.  ServerId is scoped at the ORBD.  Since
            There is no ORBD present in J2EE the value of
            ServerId is meaningless - except it must have
            SOME value if persistent POAs are created.
          */

          // For clusters - all servers in the cluster MUST
          // have the same ServerId so when failover happens
          // and requests are delivered to a new server, the
          // ServerId in the request will match the new server.

          String serverId = String.valueOf(DEFAULT_SERVER_ID);
          System.setProperty(J2EE_SERVER_ID_PROP, serverId);

          ServerContext ctx = serviceLocator.getService(ServerContext.class);
          String instanceName = ctx.getInstanceName();

          /**
           * if the auto recovery is true, always transaction logs will be written irrespective of
           * disable_distributed_transaction_logging. if the auto recovery is false, then
           * disable_distributed_transaction_logging will be used to write transaction logs are
           * not.If disable_distributed_transaction_logging is set to false(by default false) logs
           * will be written, set to true logs won't be written.
           */
          if (!isAutomaticRecovery && disable_distributed_transaction_logging) {
            Configuration.disableFileLogging();
          } else {

            // if (dbLoggingResource == null) {
            Domain domain = serviceLocator.getService(Domain.class);
            Server server = domain.getServerNamed(instanceName);

            // Check if the server system property is set
            String logdir = getTXLogDir(server);

            // if not, check if the cluster system property is set
            if (logdir == null) {
              Cluster cluster = server.getCluster();
              if (cluster != null) {
                logdir = getTXLogDir(cluster);
              }
            }

            // No system properties are set - get tx log dir from transaction service
            if (logdir == null) {
              logdir = txnService.getTxLogDir();
            }

            if (logdir == null) {
              logdir = domain.getLogRoot();
              if (logdir == null) {
                // logdir = FileUtil.getAbsolutePath(".." + File.separator + "logs");
                logdir = ".." + File.separator + "logs";
              }
            } else if (!(new File(logdir)).isAbsolute()) {
              if (_logger.isLoggable(Level.FINE)) {
                _logger.log(
                    Level.FINE,
                    "Relative pathname specified for transaction log directory : " + logdir);
              }
              String logroot = domain.getLogRoot();
              if (logroot != null) {
                logdir = logroot + File.separator + logdir;
              } else {
                // logdir = FileUtil.getAbsolutePath(".." + File.separator + "logs"
                // + File.separator + logdir);
                logdir = ".." + File.separator + "logs" + File.separator + logdir;
              }
            }
            logdir += File.separator + instanceName + File.separator + "tx";

            if (_logger.isLoggable(Level.FINE)) {
              _logger.log(Level.FINE, "JTS log directory: " + logdir);
              _logger.log(Level.FINE, "JTS Server id " + jtsServerId);
            }

            jtsProperties.put(Configuration.LOG_DIRECTORY, logdir);
          }
          jtsProperties.put(Configuration.COMMIT_RETRY, txnService.getRetryTimeoutInSeconds());
          jtsProperties.put(Configuration.INSTANCE_NAME, instanceName);
        }
      }
    }

    properties = jtsProperties;
    orbAvailable = isORBAvailable;

    return properties;
  }

  public static void initRecovery(boolean force) {
    if (_logger.isLoggable(Level.FINE)) {
      _logger.log(Level.FINE, "initRecovery:recoveryInitialized: " + recoveryInitialized);
    }

    if (recoveryInitialized) {
      // Only start initial recovery if it wasn't started before
      return;
    }

    if (_logger.isLoggable(Level.FINE)) {
      _logger.log(Level.FINE, "initRecovery:properties: " + properties);
    }
    if (properties == null) {
      if (force) {
        _logger.log(Level.WARNING, "", new IllegalStateException());
      }
      return;
    }

    // Start if force is true or automatic-recovery is set
    String value = properties.getProperty(Configuration.MANUAL_RECOVERY);
    if (_logger.isLoggable(Level.FINE)) {
      _logger.log(Level.FINE, "initRecovery:Configuration.MANUAL_RECOVERY: " + value);
    }
    if (force || (isValueSet(value) && "true".equals(value))) {
      recoveryInitialized = true;

      ServiceLocator serviceLocator = (ServiceLocator) properties.get(HABITAT);
      if (serviceLocator != null) {
        ProcessEnvironment processEnv = serviceLocator.getService(ProcessEnvironment.class);
        if (processEnv.getProcessType().isServer()) {
          // Start ResourceManager if it hadn't started yet
          serviceLocator.getAllServices(BuilderHelper.createNameFilter("ResourceManager"));
          value = properties.getProperty("pending-txn-cleanup-interval");
          int interval = -1;
          if (isValueSet(value)) {
            interval = Integer.parseInt(value);
          }
          new RecoveryHelperThread(serviceLocator, interval).start();
        }
        // Release all locks
        RecoveryManager.startResyncThread();
        if (_logger.isLoggable(Level.FINE)) _logger.log(Level.FINE, "[JTS] Started ResyncThread");
      }
    }
  }

  private static boolean isValueSet(String value) {
    return (value != null && !value.equals("") && !value.equals(" "));
  }

  private static String getTXLogDir(SystemPropertyBag bag) {
    for (SystemProperty prop : bag.getSystemProperty()) {
      String name = prop.getName();
      if (name.equals("TX-LOG-DIR")) {
        return prop.getValue();
      }
    }

    return null;
  }

  private static class RecoveryHelperThread extends Thread {
    private int interval;
    private ServiceLocator serviceLocator;

    RecoveryHelperThread(ServiceLocator serviceLocator, int interval) {
      setName("Recovery Helper Thread");
      setDaemon(true);
      this.serviceLocator = serviceLocator;
      this.interval = interval;
    }

    public void run() {
      ResourceRecoveryManager recoveryManager =
          serviceLocator.getService(ResourceRecoveryManager.class);
      if (interval <= 0) {
        // Only start the recovery thread if the interval value is set, and set to a positive value
        return;
      }

      if (_logger.isLoggable(Level.INFO)) {
        _logger.log(
            Level.INFO,
            "Asynchronous thread for incomplete " + "tx is enabled with interval " + interval);
      }
      int prevSize = 0;
      try {
        while (true) {
          Thread.sleep(interval * 1000L);
          if (!RecoveryManager.isIncompleteTxRecoveryRequired()) {
            if (_logger.isLoggable(Level.FINE))
              _logger.log(
                  Level.FINE,
                  "Incomplete transaction recovery is "
                      + "not requeired,  waiting for the next interval");
            continue;
          }
          if (RecoveryManager.sizeOfInCompleteTx() <= prevSize) {
            if (_logger.isLoggable(Level.FINE))
              _logger.log(
                  Level.FINE,
                  "Incomplete transaction recovery is "
                      + "not required,  waiting for the next interval SIZE");
            continue;
          }
          prevSize = RecoveryManager.sizeOfInCompleteTx();
          recoveryManager.recoverIncompleteTx(false, null);
        }
      } catch (Exception ex) {
        if (_logger.isLoggable(Level.FINE))
          _logger.log(Level.FINE, " Exception occurred in recoverInCompleteTx ");
      }
    }
  }
}
/**
 * @author bnevins
 * @version
 */
public class DeployableObjectType {
  public boolean isEJB() {
    return this == EJB;
  }

  ///////////////////////////////////////////////////////////////////////////

  public boolean isWEB() {
    return this == WEB;
  }

  ///////////////////////////////////////////////////////////////////////////

  public boolean isAPP() {
    return this == APP;
  }

  ///////////////////////////////////////////////////////////////////////////

  public boolean isCONN() {
    return this == CONN;
  }

  ///////////////////////////////////////////////////////////////////////////

  public boolean isCAR() {
    return this == CAR;
  }

  public boolean isLCM() {
    return this == LCM;
  }

  public boolean isCMB() {
    return this == CMB;
  }

  ///////////////////////////////////////////////////////////////////////////

  public String toString() {
    return name;
  }

  ///////////////////////////////////////////////////////////////////////////

  public ModuleType getModuleType() {
    return jsr88Type;
  }

  ///////////////////////////////////////////////////////////////////////////

  private DeployableObjectType(
      String theName, String theDDName, String theRuntimeDD, String ext, ModuleType type) {

    name = theName;
    ddName = theDDName;
    runtimeDD = theRuntimeDD;
    extension = ext;
    jsr88Type = type;
    allTypes.add(this);
  }

  ///////////////////////////////////////////////////////////////////////////

  public static final DeployableObjectType APP;
  public static final DeployableObjectType EJB;
  public static final DeployableObjectType WEB;
  public static final DeployableObjectType CONN;
  public static final DeployableObjectType CAR;
  public static final DeployableObjectType LCM;
  public static final DeployableObjectType CMB;
  private final String name;
  private final String ddName;
  private final String runtimeDD;
  private final String extension;
  private final ModuleType jsr88Type;
  private static StringManager localStrings = StringManager.getManager(DeployableObjectType.class);
  private static List allTypes;

  static {
    allTypes = new ArrayList(7);
    APP =
        new DeployableObjectType(
            "Application",
            "META-INF/application.xml",
            "META-INF/sun-application.xml",
            ".ear",
            ModuleType.EAR);

    WEB =
        new DeployableObjectType(
            "Web Module", "WEB-INF/web.xml", "WEB-INF/sun-web.xml", ".war", ModuleType.WAR);

    CONN =
        new DeployableObjectType(
            "Connector Module", "META-INF/ra.xml", "META-INF/sun-ra.xml", ".rar", ModuleType.RAR);

    CAR =
        new DeployableObjectType(
            "AppClient Module",
            "META-INF/application-client.xml",
            "META-INF/sun-application-client.xml",
            ".jar",
            ModuleType.CAR);

    EJB =
        new DeployableObjectType(
            "EJB Module",
            "META-INF/ejb-jar.xml",
            "META-INF/sun-ejb-jar.xml",
            ".jar",
            ModuleType.EJB);

    LCM = new DeployableObjectType("Lifecycle Module", null, null, ".jar", XModuleType.LCM);

    CMB = new DeployableObjectType("Custom MBean Module", null, null, ".jar", XModuleType.CMB);
  }

  ///////////////////////////////////////////////////////////////////////////

  public static void main(String[] args) {
    String[] files =
        new String[] {
          "pkgingEApp.ear",
          "foof.rar",
          "hello.war",
          "foo.jar",
          "nothere",
          "junk.ear",
          "ear",
          "ejb",
          "rar",
          "war"
        };

    for (int i = 0; i < files.length; i++) {
      File f = new File("C:/ias8samples/" + files[i]);

      try {
        // used to display (f.getName() + " is a: " + valueOf(f));
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }
}
/**
 * This interface implements basic deployment related facilities such as deploying any j2ee modules
 * on a Domain Admin Server or target servers as well as retrieving non portable artifacts for
 * successful runs in a client mode configuration.
 */
public class DeploymentFacilityImpl implements DeploymentFacility {

  protected ConnectionSource dasConnection = null;
  protected ServerConnectionIdentifier serverId = null;
  protected SunTarget domain = null;
  protected Boolean localConnection = Boolean.FALSE;

  private static final String DAS = "server";
  private static StringManager localStrings =
      StringManager.getManager(DeploymentFacilityImpl.class);

  public DeploymentFacilityImpl() {}

  /**
   * Connects to a particular instance of the domain adminstration server using the provided
   * connection information
   */
  public boolean connect(ServerConnectionIdentifier targetDAS) {
    try {
      TLSParams tlsParams = null;
      if (targetDAS.isSecure()) {
        X509TrustManager trustManager =
            (X509TrustManager)
                targetDAS
                    .getConnectionEnvironment()
                    .get(DefaultConfiguration.TRUST_MANAGER_PROPERTY_NAME);
        tlsParams = new TLSParams(trustManager, null);
      }

      dasConnection =
          new AppserverConnectionSource(
              AppserverConnectionSource.PROTOCOL_HTTP,
              targetDAS.getHostName(),
              targetDAS.getHostPort(),
              targetDAS.getUserName(),
              targetDAS.getPassword(),
              tlsParams,
              null);
    } catch (IllegalArgumentException illEx) {
      return false;
    }
    serverId = targetDAS;
    domain = new SunTarget(targetDAS);
    domain.setConnectionSource(dasConnection);
    domain.setTargetType(TargetType.DOMAIN);
    return true;
  }

  /** @return true if we are connected to a domain adminstration server */
  public boolean isConnected() {
    if (dasConnection == null) {
      return false;
    }
    return true;
  }

  /** Disconnects from a domain administration server and releases all associated resouces. */
  public boolean disconnect() {
    dasConnection = null;
    return true;
  }

  /**
   * Initiates a deployment operation on the server, using a source archive abstraction and an
   * optional deployment plan if the server specific information is not embedded in the source
   * archive. The deploymentOptions is a key-value pair map of deployment options for this
   * operations. Once the deployment is successful, the targets server instances
   *
   * @param source is the j2ee module abstraction (with or without the server specific artifacts).
   * @param deploymenPlan is the optional deployment plan is the source archive is portable.
   * @param the deployment options
   * @return a JESProgressObject to receive deployment events.
   */
  public JESProgressObject deploy(
      Target[] targets, Archive source, Archive deploymentPlan, Map deploymentOptions) {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }

    SunTarget[] targetList = getSunTargets(targets);
    ProgressObjectImpl progressObject = new DeployAction(targetList);
    Object args[] = new Object[8];
    args[0] = dasConnection;
    args[1] = source;
    args[2] = deploymentPlan;
    args[3] =
        (deploymentOptions == null)
            ? new HashMap()
            : DeploymentProperties.propsToMap((Properties) deploymentOptions);
    args[4] = targetList;
    args[5] = domain;
    args[6] = localConnection;
    args[7] = serverId;
    progressObject.setCommand(CommandType.DISTRIBUTE, args);
    Thread newThread = new Thread(progressObject);
    newThread.start();
    return progressObject;
  }

  /**
   * Initiates a undeployment operation on the server
   *
   * @param module ID for the component to undeploy
   * @return a JESProgress to receive undeployment events
   */
  // FIXME - this should go once admin-cli changes it code
  public JESProgressObject undeploy(Target[] targets, String moduleID) {
    return (undeploy(targets, moduleID, null));
  }

  public JESProgressObject undeploy(Target[] targets, String moduleID, Map options) {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }
    SunTarget[] targetList = getSunTargets(targets);
    ProgressObjectImpl progressObject = new UndeployAction(targetList);
    Object args[] = new Object[6];
    args[0] = dasConnection;
    args[1] = moduleID;
    args[2] =
        (options == null) ? new HashMap() : DeploymentProperties.propsToMap((Properties) options);
    args[3] = targetList;
    args[4] = domain;
    args[5] = localConnection;
    progressObject.setCommand(CommandType.UNDEPLOY, args);
    Thread newThread = new Thread(progressObject);
    newThread.start();
    return progressObject;
  }

  /** Enables a deployed component on the provided list of targets. */
  public JESProgressObject enable(Target[] targets, String moduleID) {
    return (changeState(targets, moduleID, CommandType.START));
  }

  /** Disables a deployed component on the provided list of targets */
  public JESProgressObject disable(Target[] targets, String moduleID) {
    return (changeState(targets, moduleID, CommandType.STOP));
  }

  private JESProgressObject changeState(Target[] targets, String moduleID, CommandType cmd) {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }
    SunTarget[] targetList = getSunTargets(targets);
    ProgressObjectImpl progressObject = new ChangeStateAction(targetList);
    Object args[] = new Object[5];
    args[0] = dasConnection;
    args[1] = targetList;
    args[2] = moduleID;
    args[3] = cmd;
    args[4] = domain;
    progressObject.setCommand(cmd, args);
    Thread newThread = new Thread(progressObject);
    newThread.start();
    return progressObject;
  }

  /** Add an application ref on the selected targets */
  public JESProgressObject createAppRef(Target[] targets, String moduleID, Map options) {
    return (doApplicationReferenceAction(targets, moduleID, options, CommandType.DISTRIBUTE));
  }

  /** remove the application ref for the provided list of targets. */
  public JESProgressObject deleteAppRef(Target[] targets, String moduleID, Map options) {
    return (doApplicationReferenceAction(targets, moduleID, options, CommandType.UNDEPLOY));
  }

  private JESProgressObject doApplicationReferenceAction(
      Target[] targets, String moduleID, Map options, CommandType cmd) {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }
    SunTarget[] targetList = getSunTargets(targets);
    ProgressObjectImpl progressObject = new ApplicationReferenceAction(targetList);
    Object args[] = new Object[5];
    args[0] = dasConnection;
    args[1] = targetList;
    args[2] = moduleID;
    args[3] = cmd;
    args[4] =
        (options == null) ? new HashMap() : DeploymentProperties.propsToMap((Properties) options);
    progressObject.setCommand(cmd, args);
    Thread newThread = new Thread(progressObject);
    newThread.start();
    return progressObject;
  }

  /** list all application refs that are present in the provided list of targets */
  public TargetModuleID[] listAppRefs(String[] targets) throws IOException {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }
    Vector tmpVector = new Vector();
    DomainConfig domainCfg =
        ProxyFactory.getInstance(dasConnection).getDomainRoot().getDomainConfig();
    Map serverProxies = domainCfg.getStandaloneServerConfigMap();
    Map clusterProxies = domainCfg.getClusterConfigMap();
    Map clusteredServerProxies = domainCfg.getClusteredServerConfigMap();
    for (int i = 0; i < targets.length; i++) {
      Set proxySet = null;
      if (serverProxies.get(targets[i]) != null) {
        StandaloneServerConfig tgtProxy =
            (StandaloneServerConfig)
                domainCfg.getContainee(XTypes.STANDALONE_SERVER_CONFIG, targets[i]);
        proxySet = tgtProxy.getContaineeSet(XTypes.DEPLOYED_ITEM_REF_CONFIG);
      } else if (clusterProxies.get(targets[i]) != null) {
        ClusterConfig tgtProxy =
            (ClusterConfig) domainCfg.getContainee(XTypes.CLUSTER_CONFIG, targets[i]);
        proxySet = tgtProxy.getContaineeSet(XTypes.DEPLOYED_ITEM_REF_CONFIG);
      } else if (clusteredServerProxies.get(targets[i]) != null) {
        ClusteredServerConfig tgtProxy =
            (ClusteredServerConfig)
                domainCfg.getContainee(XTypes.CLUSTERED_SERVER_CONFIG, targets[i]);
        proxySet = tgtProxy.getContaineeSet(XTypes.DEPLOYED_ITEM_REF_CONFIG);
      } else if (TargetType.DOMAIN.equals(targets[i])) {
        StandaloneServerConfig tgtProxy =
            (StandaloneServerConfig) domainCfg.getContainee(XTypes.STANDALONE_SERVER_CONFIG, DAS);
        proxySet = tgtProxy.getContaineeSet(XTypes.DEPLOYED_ITEM_REF_CONFIG);
      } else {
        return null;
      }
      Object[] appRefs = proxySet.toArray();
      for (int k = 0; k < appRefs.length; k++) {
        SunTarget aTarget = new SunTarget(serverId);
        aTarget.setAppServerInstance(targets[i]);
        aTarget.setConnectionSource(dasConnection);
        DeployedItemRefConfig item = (DeployedItemRefConfig) appRefs[k];
        SunTargetModuleID tgtId = new SunTargetModuleID(item.getRef(), aTarget);
        tmpVector.add(tgtId);
      }
    }
    SunTargetModuleID[] result = new SunTargetModuleID[tmpVector.size()];
    return (TargetModuleID[]) tmpVector.toArray(result);
  }

  /** Create SunTarget[] from given Target[] */
  private SunTarget[] getSunTargets(Target[] givenTargets) throws IllegalArgumentException {
    SunTarget[] result = new SunTarget[givenTargets.length];
    for (int i = 0; i < givenTargets.length; i++) {
      if (givenTargets[i] instanceof SunTarget) {
        result[i] = new SunTarget((SunTarget) givenTargets[i]);
      } else {
        throw new IllegalArgumentException(
            localStrings.getString(
                "enterprise.deployment.client.notASunTarget",
                givenTargets[i].getClass().getName()));
      }
    }
    return result;
  }

  /**
   * Downloads a particular file from the server repository. The filePath is a relative path from
   * the root directory of the deployed component identified with the moduleID parameter. The
   * resulting downloaded file should be placed in the location directory keeping the relative path
   * constraint. Note that the current implementation only supports the download of the appclient
   * jar file.
   *
   * @param location is the root directory where to place the downloaded file
   * @param moduleID is the moduleID of the deployed component to download the file from
   * @param moduleURI is the relative path to the file in the repository
   * @return the downloaded local file absolute path.
   */
  public String downloadFile(File location, String moduleID, String moduleURI) throws IOException {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }

    return DeploymentClientUtils.downloadClientStubs(
        moduleID, location.getAbsolutePath(), dasConnection);
  }

  /**
   * Wait for a Progress object to be in a completed state (sucessful or failed) and return the
   * DeploymentStatus for this progress object.
   *
   * @param the progress object to wait for completion
   * @return the deployment status
   */
  public DeploymentStatus waitFor(JESProgressObject po) {
    DeploymentStatus status = null;
    do {
      try {
        Thread.currentThread().sleep(100);
      } catch (InterruptedException ie) {
        // Exception swallowed deliberately
      }
      status = po.getCompletedStatus();
    } while (status == null);
    return status;
  }

  public Target[] createTargets(String[] targets) {
    if (!isConnected()) {
      throw new IllegalStateException(
          localStrings.getString("enterprise.deployment.client.disconnected_state"));
    }
    Target[] targetsArray = new Target[targets.length];
    Map serverProxies = null;
    Map clusterProxies = null;

    try {
      // parse through given targets
      for (int i = 0; i < targets.length; i++) {

        // if this is "domain" add a domain target
        if (TargetType.DOMAIN.equals(targets[i])) {
          // Add a domain target
          SunTarget dom = new SunTarget(serverId);
          dom.setAppServerInstance(TargetType.DOMAIN);
          dom.setConnectionSource(dasConnection);
          dom.setTargetType(TargetType.DOMAIN);
          targetsArray[i] = dom;
          continue;
        }
        // if this is "server" add a server target
        if (DAS.equals(targets[i])) {
          // Add a target for default server
          SunTarget serv = new SunTarget(serverId);
          serv.setAppServerInstance(DAS);
          serv.setConnectionSource(dasConnection);
          serv.setTargetType(TargetType.STAND_ALONE_SERVER);
          targetsArray[i] = serv;
          continue;
        }
        // for PE, it will not come here at all; go ahead and get proxies and server/cluster keysets
        // from the proxies
        if (serverProxies == null || clusterProxies == null) {
          DomainConfig domainCfg =
              ProxyFactory.getInstance(dasConnection).getDomainRoot().getDomainConfig();
          serverProxies = domainCfg.getStandaloneServerConfigMap();
          clusterProxies = domainCfg.getClusterConfigMap();
        }
        // check if ctarget is a stand alone server
        if (serverProxies.get(targets[i]) != null) {
          SunTarget aTarget = new SunTarget(serverId);
          aTarget.setAppServerInstance(targets[i]);
          aTarget.setConnectionSource(dasConnection);
          aTarget.setTargetType(TargetType.STAND_ALONE_SERVER);
          targetsArray[i] = aTarget;
          continue;
        }
        // check if ctarget is a cluster
        if (clusterProxies.get(targets[i]) != null) {
          SunTarget aTarget = new SunTarget(serverId);
          aTarget.setAppServerInstance(targets[i]);
          aTarget.setConnectionSource(dasConnection);
          aTarget.setTargetType(TargetType.CLUSTER);
          targetsArray[i] = aTarget;
          continue;
        }
        // if we are here, it means given target does not exist at all - return null
        return null;
      }
    } catch (Throwable ex) {
      // it's too late to change the DeploymentFacility.createTargets
      // interface to throw approriate exceptions as this point,
      // but let's at least re-throw the RuntimeException so
      // connection failure (for example, due to wrong user/password)
      // could be reported back to user.
      if (ex instanceof RuntimeException) {
        throw (RuntimeException) ex;
      }
      return null;
    }
    return targetsArray;
  }
}
public class DomainXmlTransformer {

  private File in;
  private File out;
  private final XMLEventFactory xmlEventFactory = XMLEventFactory.newInstance();
  private final XMLOutputFactory xof = XMLOutputFactory.newInstance();

  private Logger _logger =
      Logger.getAnonymousLogger("com.sun.logging.enterprise.system.container.ejb.LogStrings");

  private static final String VIRTUAL_SERVER = "virtual-server";
  private static final String NETWORK_LISTENERS = "network-listeners";
  private static final String IIOP_LISTENER = "iiop-listener";
  private static final String PROTOCOLS = "protocols";
  private static final String APPLICATIONS = "applications";
  private static final String CLUSTERS = "clusters";
  private static final String JMS_HOST = "jms-host";
  private static final String JMX_CONNECTOR = "jmx-connector";
  private static final String LAZY_INIT_ATTR = "lazy-init";
  private static final String ADMIN_SERVICE = "admin-service";
  private static final String DAS_CONFIG = "das-config";
  private static final String DYNAMIC_RELOAD_ENABLED = "dynamic-reload-enabled";
  private static final String JAVA_CONFIG = "java-config";
  private static final String JVM_OPTIONS = "jvm-options";
  private static final String INITIALIZE_ON_DEMAND = "-Dorg.glassfish.jms.InitializeOnDemand=true";
  private static final String ENABLED = "enabled";
  private static final String FALSE = "false";
  private static final String TRUE = "true";

  private static final Set<String> SKIP_ELEMENTS = new HashSet(Arrays.asList(VIRTUAL_SERVER));
  private static final Set<String> SKIP_ELEMENTS_KEEP_PORTS = new HashSet();
  private static final Set<String> EMPTY_ELEMENTS =
      new HashSet(Arrays.asList(NETWORK_LISTENERS, PROTOCOLS, APPLICATIONS, CLUSTERS));
  private static final Set<String> EMPTY_ELEMENTS_KEEP_PORTS =
      new HashSet(Arrays.asList(APPLICATIONS));
  private static final Set<String> SKIP_SETTINGS_ELEMENTS =
      new HashSet(Arrays.asList(IIOP_LISTENER));
  private static final Set<String> DISABLE_ELEMENTS = new HashSet(Arrays.asList(JMX_CONNECTOR));
  private static final Set<String> DISABLE_SUB_ELEMENTS =
      new HashSet(Arrays.asList(LAZY_INIT_ATTR));

  private static final StringManager localStrings =
      StringManager.getManager(DomainXmlTransformer.class);

  public DomainXmlTransformer(File domainXml) {
    in = domainXml;
  }

  public DomainXmlTransformer(File domainXml, Logger logger) {
    in = domainXml;
    _logger = logger;
  }

  public File transform(boolean keepPorts) {
    FileInputStream fis = null;
    FileOutputStream fos = null;
    XMLEventReader parser = null;
    XMLEventWriter writer = null;
    XMLInputFactory xif =
        (XMLInputFactory.class.getClassLoader() == null)
            ? XMLInputFactory.newInstance()
            : XMLInputFactory.newInstance(
                XMLInputFactory.class.getName(), XMLInputFactory.class.getClassLoader());

    Set<String> empty_elements = (keepPorts) ? EMPTY_ELEMENTS_KEEP_PORTS : EMPTY_ELEMENTS;
    Set<String> skip_elements = (keepPorts) ? SKIP_ELEMENTS_KEEP_PORTS : SKIP_ELEMENTS;
    try {
      fis = new FileInputStream(in);
      out = File.createTempFile("domain", "xml");
      if (_logger.isLoggable(Level.FINE)) {
        _logger.fine("[DomainXmlTransformer] Creating temp domain file: " + out);
      }

      if (System.getProperty(EJBContainerProviderImpl.KEEP_TEMPORARY_FILES) == null) {
        out.deleteOnExit();
      }

      fos = new FileOutputStream(out);
      parser = xif.createXMLEventReader(fis);

      writer = xof.createXMLEventWriter(fos);
      boolean fixedDasConfig = false;
      while (parser.hasNext()) {
        XMLEvent event = parser.nextEvent();
        if (event.isStartElement()) {
          String name = event.asStartElement().getName().getLocalPart();
          if (skip_elements.contains(name)) {
            if (_logger.isLoggable(Level.FINE)) {
              _logger.fine("[DomainXmlTransformer] Skipping all of: " + name);
            }
            getEndEventFor(parser, name);
            continue;
          }

          boolean skip_to_end = false;
          if (empty_elements.contains(name)) {
            if (_logger.isLoggable(Level.FINE)) {
              _logger.fine("[DomainXmlTransformer] Skipping details of: " + name);
            }
            skip_to_end = true;
          } else if (SKIP_SETTINGS_ELEMENTS.contains(name)) {
            // Make sure lazy init is not enabled by creating a new start element
            // based on the original but that never includes the lazy init attribute
            event = getSkippedElementStartEvent(event);
            skip_to_end = true;
          } else if (DISABLE_ELEMENTS.contains(name)) {
            // Disable this element
            event = getReplaceAttributeInStartEvent(event, ENABLED, FALSE);
            skip_to_end = true;
          } else if (JMS_HOST.equals(name)) {
            // Set lazy-init to false
            event = getReplaceAttributeInStartEvent(event, LAZY_INIT_ATTR, FALSE);
            skip_to_end = true;
          } else if (DAS_CONFIG.equals(name)) {
            // Set dynamic-reload-enabled to false
            event = getReplaceAttributeInStartEvent(event, DYNAMIC_RELOAD_ENABLED, FALSE);
            fixedDasConfig = true;
            skip_to_end = true;
          } else if (JAVA_CONFIG.equals(name)) {
            // Add jvm-options
            writer.add(event);
            event = getAddedEvent(event, writer, JVM_OPTIONS, INITIALIZE_ON_DEMAND);
          }

          if (skip_to_end) {
            writer.add(event);
            event = getEndEventFor(parser, name);
          }
        } else if (event.isEndElement()) {
          String name = event.asEndElement().getName().getLocalPart();
          if (ADMIN_SERVICE.equals(name)) {
            if (!fixedDasConfig) {
              writer.add(
                  getAddedEventBeforeEndElement(
                      event, writer, DAS_CONFIG, DYNAMIC_RELOAD_ENABLED, FALSE));
            }
            fixedDasConfig = false; // for the next config
          }
        }
        if (_logger.isLoggable(Level.FINEST)) {
          _logger.finest("[DomainXmlTransformer] Processing: " + event);
        }
        writer.add(event);
      }
      writer.flush();
      writer.close();

    } catch (Exception e) {
      _logger.log(Level.SEVERE, "ejb.embedded.tmp_file_create_error", e.getMessage());
      _logger.log(Level.FINE, e.getMessage(), e);
      return null;
    } finally {
      try {
        if (parser != null) {
          parser.close();
        }
      } catch (Exception e) {
      }
      try {
        if (fis != null) {
          fis.close();
        }
      } catch (Exception e) {
      }
      try {
        if (writer != null) {
          writer.close();
        }
      } catch (Exception e) {
      }
      try {
        if (fos != null) {
          fos.close();
        }
      } catch (Exception e) {
      }
    }

    if (_logger.isLoggable(Level.FINE)) {
      _logger.fine("[DomainXmlTransformer] Created temp domain file: " + out);
    }
    return out;
  }

  private XMLEvent getEndEventFor(XMLEventReader parser, String name)
      throws XMLStreamException, EOFException {
    while (parser.hasNext()) {
      XMLEvent event = parser.nextEvent();
      if (event.isEndElement() && event.asEndElement().getName().getLocalPart().equals(name)) {
        if (_logger.isLoggable(Level.FINEST)) {
          _logger.finest("[DomainXmlTransformer] END: " + name);
        }
        return event;
      }
    }

    throw new EOFException(localStrings.getString("ejb.embedded.no_matching_end_element", name));
  }

  /** Create a new start element based on the original but that does not include any attributes. */
  private StartElement getEmptyStartEvent(XMLEvent event) {
    StartElement oldStartEvent = event.asStartElement();
    return xmlEventFactory.createStartElement(
        oldStartEvent.getName(), null, oldStartEvent.getNamespaces());
  }

  /**
   * Create a new start element based on the original but that does not include the specified
   * attribute.
   */
  private StartElement getSkippedElementStartEvent(XMLEvent event) {
    Set attributes = new HashSet();

    for (java.util.Iterator i = event.asStartElement().getAttributes(); i.hasNext(); ) {
      Attribute a = (Attribute) i.next();
      if (!DISABLE_SUB_ELEMENTS.contains(a.getName().getLocalPart())) {
        attributes.add(a);
      }
    }

    StartElement oldStartEvent = event.asStartElement();
    return xmlEventFactory.createStartElement(
        oldStartEvent.getName(), attributes.iterator(), oldStartEvent.getNamespaces());
  }

  /**
   * Write a new element with the specified name and text
   *
   * @return the end element
   */
  private XMLEvent getAddedEvent(
      XMLEvent event, XMLEventWriter writer, String elementName, String text)
      throws XMLStreamException {
    StartElement oldStartEvent = event.asStartElement();
    StartElement newStartEvent =
        xmlEventFactory.createStartElement(
            new QName(elementName), null, oldStartEvent.getNamespaces());

    writer.add(newStartEvent);
    writer.add(xmlEventFactory.createCharacters(text));
    return xmlEventFactory.createEndElement(newStartEvent.getName(), newStartEvent.getNamespaces());
  }

  /**
   * Write a new element with the specified name and attribute before the end element is written out
   *
   * @return the end element
   */
  private XMLEvent getAddedEventBeforeEndElement(
      XMLEvent event,
      XMLEventWriter writer,
      String elementName,
      String attributeName,
      String attributeValue)
      throws XMLStreamException {
    Attribute newAttribute = xmlEventFactory.createAttribute(attributeName, attributeValue);
    Set attributes = new HashSet();
    attributes.add(newAttribute);

    EndElement oldEvent = event.asEndElement();
    StartElement newStartEvent =
        xmlEventFactory.createStartElement(
            new QName(elementName), attributes.iterator(), oldEvent.getNamespaces());

    writer.add(newStartEvent);
    return xmlEventFactory.createEndElement(newStartEvent.getName(), newStartEvent.getNamespaces());
  }

  /** Create a new start element based on the original but that replaces attribute value */
  private StartElement getReplaceAttributeInStartEvent(
      XMLEvent event, String attr_name, String attr_value) {
    Set attributes = new HashSet();

    for (java.util.Iterator i = event.asStartElement().getAttributes(); i.hasNext(); ) {
      Attribute a = (Attribute) i.next();
      if (!a.getName().getLocalPart().equals(attr_name)) {
        attributes.add(a);
      }
    }

    Attribute newAttribute = xmlEventFactory.createAttribute(attr_name, attr_value);
    attributes.add(newAttribute);

    StartElement oldStartEvent = event.asStartElement();
    return xmlEventFactory.createStartElement(
        oldStartEvent.getName(), attributes.iterator(), oldStartEvent.getNamespaces());
  }
}
/**
 * Represents a concrete implementation of a command that processes the synchronization response.
 *
 * @author Nazrul Islam
 * @since JDK1.4
 */
class ResponseProcessCommand implements Command {

  private static Logger _logger = Logger.getLogger(EELogDomains.SYNCHRONIZATION_LOGGER);

  private static final StringManager _localStrMgr =
      StringManager.getManager(ResponseProcessCommand.class);

  /**
   * Initializes the arguments.
   *
   * @param req synchronization request
   * @param res synchronization response
   */
  ResponseProcessCommand(SynchronizationRequest req, SynchronizationResponse res) {

    _request = req;
    _response = res;
  }

  /**
   * Renders the response zip into the local file system.
   *
   * @throws SynchronizationException if an error while processing the zip
   */
  public void execute() throws SynchronizationException {

    try {
      _logger.log(Level.FINE, "synchronization.process_command", _request.getMetaFileName());

      String baseDir = _request.getBaseDirectory();
      Unzipper z = new Unzipper(baseDir);
      byte[] zipBytes = _response.getZipBytes();
      long checksum = 0;

      // if byte exists in response
      if (zipBytes != null) {

        // render the zip bytes
        checksum = z.writeZipBytes(zipBytes);

      } else { // handle a re-direct
        File tempZip = null;

        // DAS and server instance are running on the same machine
        // skips download and uses the zip directly
        if (isSameHost()) {
          String dasZipLoc = _response.getZipLocation();
          tempZip = new File(dasZipLoc);
        } else {
          // download the zip file
          tempZip = downloadZip();
        }

        // render the zip file
        if (tempZip != null && tempZip.exists()) {

          // ignore response entry for http based impl
          z.ignoreEntry(ServletProcessor.RESPONSE_ENTRY_NAME);

          checksum = z.writeZipFile(tempZip.getCanonicalPath());
        }
      }

      // assert(_response.getChecksum() == checksum);

      _logger.log(Level.FINE, "synchronization.check_sum", new Long(checksum).toString());
    } catch (Exception e) {
      String msg = _localStrMgr.getString("syncResponseError", _request.getMetaFileName());
      throw new SynchronizationException(msg, e);
    }
  }

  /**
   * Returns true if DAS and remote server is running in the same machine. This allows to perform
   * same host optimization during zip download.
   *
   * @return true if DAS and remote server runs on the same machine
   */
  private boolean isSameHost() {

    boolean tf = false;

    String dasZipLoc = _response.getZipLocation();
    File zip = new File(dasZipLoc);

    // the zip file name after the time stamp exists in the remote
    // server instance
    if (zip.exists()) {
      long dasLastModified = _response.getLastModifiedOfZip();
      long localLastModified = zip.lastModified();

      // last modified of zip is the same
      if (dasLastModified == localLastModified) {

        // host name of DAS
        String dasHostName = _response.getDasHostName();
        try {
          InetAddress host = InetAddress.getLocalHost();
          // host name of DAS is same is this server instance
          if ((dasHostName != null) && (dasHostName.equals(host.getHostName()))) {

            tf = true;
          }
        } catch (UnknownHostException uhe) {
          // ignore
        }
      }
    }

    return tf;
  }

  /**
   * Downloads the zip file from DAS.
   *
   * @return temporary location of the local zip file where zip is being down loaded
   * @throws SynchronizationException if an error during zip download
   * @throws IOException if an i/o error during zip download
   */
  private File downloadZip() throws SynchronizationException, IOException {

    File zipfile = null;
    String dasZipLoc = _response.getZipLocation();

    // zip size is too big to stream in byte array
    // download the zip using chunking
    if (dasZipLoc != null) {

      // synchronization client to DAS
      SynchronizationClientImpl sClient =
          new SynchronizationClientImpl(SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME);

      // temp file in the remote sever
      zipfile = Utils.getTempZipFile();

      // connects to DAS
      sClient.connect();

      // down loads the zip file
      sClient.getAbsolute(dasZipLoc, zipfile);

      // closes the connection to DAS
      sClient.disconnect();
    }

    return zipfile;
  }

  /**
   * Returns the name of this command.
   *
   * @return the name of this command
   */
  public String getName() {
    return NAME;
  }

  /** No-op. */
  public Object getResult() {
    return null;
  }

  // ---- VARIABLE(S) - PRIVATE -------------------------------
  private SynchronizationRequest _request = null;
  private SynchronizationResponse _response = null;
  private static final String ZIP_SUFFIX = ".zip";
  private static final String NAME = "Synchronization-Response-Process-Command";
}
Exemple #9
0
public class PEFileLayout {
  private static final StringManager _strMgr = StringManager.getManager(PEFileLayout.class);

  public static final String DEFAULT_INSTANCE_NAME =
      SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME;
  /* above field is taken from a central place */
  protected final RepositoryConfig _config;

  public PEFileLayout(RepositoryConfig config) {
    _config = config;
  }

  public void createRepositoryDirectories() throws RepositoryException {
    createDirectory(getRepositoryRootDir());
    createDirectory(getRepositoryDir());
    createDirectory(getConfigRoot());
    createDirectory(getBinDir());
    createDirectory(getLogsDir());
    createDirectory(getDocRoot());
    createDirectory(getApplicationsRootDir());
    createDirectory(getAutoDeployDir());
    createDirectory(getAutoDeployStatusDir());
    createDirectory(getAutoDeployOSGiBundlesDir());

    createDirectory(getLibDir());
    createDirectory(getClassesDir());
    createDirectory(getExtLibDir());
    createDirectory(getAppLibsDir());
    createDirectory(getTimerDatabaseDir());

    /*
    createDirectory(getAddonRoot());
    createDirectory(getJavaWebStartRoot());

    createDirectory(getGeneratedDir());
    createDirectory(getJspRootDir());
    createDirectory(getEjbRootDir());
    createDirectory(getXmlRootDir());
    createDirectory(getJ2EEAppsDir());
    createDirectory(getJ2EEModulesDir());
    createDirectory(getLifecycleModulesDir());
    createDirectory(getMbeansDir());
    createDirectory(getSessionStore());

     */
  }

  protected RepositoryConfig getConfig() {
    return _config;
  }

  public void createRepositoryRoot() throws RepositoryException {
    createDirectory(getRepositoryRootDir());
  }

  public void createJBIDirectories() throws RepositoryException {
    createDirectory(getJbiInstanceDir());
  }

  public void createJBIDomainDirectories() throws RepositoryException {
    createJBIDirectories();
    createDirectory(getJbiAuotoInstallDir());
    createDirectory(getJbiConfigDir());
    createDirectory(getJbiConfigPrivateDir());
    createJbiSystemComponentsLayout();
  }

  protected void createDirectory(File dir) throws RepositoryException {
    if (!dir.exists()) {
      try {
        if (!dir.mkdirs()) {
          throw new RepositoryException(_strMgr.getString("directoryCreationError", dir));
        }
      } catch (Exception e) {
        throw new RepositoryException(_strMgr.getString("directoryCreationError", dir), e);
      }
    }
  }

  public static final String ADDON_DIR = "addons";

  public File getAddonRoot() {
    return new File(getRepositoryDir(), ADDON_DIR);
  }

  public static final String CONFIG_DIR = "config";

  public File getConfigRoot() {
    return new File(getRepositoryDir(), CONFIG_DIR);
  }

  public static final String CONFIG_BACKUP_DIR = "backup";

  public File getRepositoryBackupRoot() {
    return new File(getConfigRoot(), CONFIG_BACKUP_DIR);
  }

  public static final String DOC_ROOT_DIR = "docroot";

  public File getDocRoot() {

    return new File(getRepositoryDir(), DOC_ROOT_DIR);
  }

  public static final String JAVA_WEB_START_DIR = "java-web-start";

  public File getJavaWebStartRoot() {

    return new File(getRepositoryDir(), JAVA_WEB_START_DIR);
  }

  public static final String LIB_DIR = "lib";

  public File getLibDir() {
    return new File(getRepositoryDir(), LIB_DIR);
  }

  public File getBinDir() {
    return new File(getRepositoryDir(), BIN_DIR);
  }

  public static final String CLASSES_DIR = "classes";

  public File getClassesDir() {
    return new File(getLibDir(), CLASSES_DIR);
  }

  public static final String APPLIBS_DIR = "applibs";

  public File getAppLibsDir() {
    return new File(getLibDir(), APPLIBS_DIR);
  }

  public static final String EXTLIB_DIR = "ext";

  public File getExtLibDir() {
    return new File(getLibDir(), EXTLIB_DIR);
  }

  public static final String TIMERDB_DIR = "databases";

  public File getTimerDatabaseDir() {
    return new File(getLibDir(), TIMERDB_DIR);
  }

  public static final String LOGS_DIR = "logs";

  public File getLogsDir() {
    return new File(getRepositoryDir(), LOGS_DIR);
  }

  public static final String APPS_ROOT_DIR = "applications";

  public File getApplicationsRootDir() {
    return new File(getRepositoryDir(), APPS_ROOT_DIR);
  }

  public static final String J2EE_APPS_DIR = "j2ee-apps";

  public File getJ2EEAppsDir() {
    return new File(getApplicationsRootDir(), J2EE_APPS_DIR);
  }

  public static final String J2EE_MODULES_DIR = "j2ee-modules";

  public File getJ2EEModulesDir() {
    return new File(getApplicationsRootDir(), J2EE_MODULES_DIR);
  }

  public static final String LIFECYCLE_MODULES_DIR = "lifecycle-modules";

  public File getLifecycleModulesDir() {
    return new File(getApplicationsRootDir(), LIFECYCLE_MODULES_DIR);
  }

  public static final String MBEAN_FOLDER_NAME = "mbeans";

  public File getMbeansDir() {
    return new File(getApplicationsRootDir(), MBEAN_FOLDER_NAME);
  }

  public static final String GENERATED_DIR = "generated";

  public File getGeneratedDir() {
    return new File(getRepositoryDir(), GENERATED_DIR);
  }

  // Begin EE: 4946914 - cluster deployment support

  public static final String POLICY_DIR = "policy";
  public static final String POLICY_FILE_EXT = "granted.policy";

  public File getPolicyDir() {
    return new File(getGeneratedDir(), POLICY_DIR);
  }

  // End EE: 4946914 - cluster deployment support

  public static final String JSP_DIR = "jsp";

  public File getJspRootDir() {
    return new File(getGeneratedDir(), JSP_DIR);
  }

  public static final String EJB_DIR = "ejb";

  public File getEjbRootDir() {
    return new File(getGeneratedDir(), EJB_DIR);
  }

  public static final String XML_DIR = "xml";

  public File getXmlRootDir() {
    return new File(getGeneratedDir(), XML_DIR);
  }

  public File getRepositoryDir() {
    return new File(getRepositoryRootDir(), getConfig().getRepositoryName());
  }

  public static final String DOMAIN_XML_FILE = "domain.xml";

  public File getDomainConfigFile() {
    return new File(getConfigRoot(), DOMAIN_XML_FILE);
  }

  public File getDomainConfigBackupFile() {
    return new File(getRepositoryBackupRoot(), DOMAIN_XML_FILE);
  }

  public static final String IMQ = "imq";

  public File getImqDir() {
    return new File(getInstallRootDir(), IMQ);
  }

  public static final String JBI_DIR = "jbi";

  public File getJbiDir() {
    return new File(getInstallRootDir(), JBI_DIR);
  }

  public static final String JBI_LIB_DIR = "lib";

  public File getJbiLibDir() {
    return new File(getJbiDir(), JBI_LIB_DIR);
  }

  public static final String JBI_LIB_INSTALL_DIR = "install";

  public File getJbiLibInstallDir() {
    return new File(getJbiLibDir(), JBI_LIB_INSTALL_DIR);
  }

  public static final String JBI_TEMPLATE_DIR = "templates";

  public File getJbiTemplateDir() {
    return new File(getJbiLibInstallDir(), JBI_TEMPLATE_DIR);
  }

  public static final String JBI_TEMPLATE_FILE = "jbi-registry.xml.template";

  public File getJbiTemplateFile() {
    return new File(getJbiTemplateDir(), JBI_TEMPLATE_FILE);
  }

  public static final String JBI_INSTANCE_DIR = "jbi";

  public File getJbiInstanceDir() {
    return new File(getRepositoryDir(), JBI_INSTANCE_DIR);
  }

  public static final String JBI_COMPONENTS_DIR = "components";

  public File getJbiComponentsDir() {
    return new File(getJbiInstanceDir(), JBI_COMPONENTS_DIR);
  }

  public static final String JAVAEE_SE_DIR = "sun-javaee-engine";

  public File getJavaEESEDir() {
    return new File(getJbiComponentsDir(), JAVAEE_SE_DIR);
  }

  public static final String HTTP_BC_DIR = "sun-http-binding";

  public File getHttpBcDir() {
    return new File(getJbiComponentsDir(), HTTP_BC_DIR);
  }

  public static final String JBI_COMPONENT_WS = "install_root" + File.separator + "workspace";

  public File getJavaEESEWorkSpace() {
    return new File(getJavaEESEDir(), JBI_COMPONENT_WS);
  }

  public File getHttpBcWorkSpace() {
    return new File(getHttpBcDir(), JBI_COMPONENT_WS);
  }

  public static final String JBI_SHAREDLIB_DIR = "shared-libraries";

  public File getJbiSharedLibDir() {
    return new File(getJbiInstanceDir(), JBI_SHAREDLIB_DIR);
  }

  public static final String JBI_CONFIG_DIR = "config";

  public File getJbiConfigDir() {
    return new File(getJbiInstanceDir(), JBI_CONFIG_DIR);
  }

  public static final String JBI_AUTOINSTALL_DIR = "autoinstall";

  public File getJbiAuotoInstallDir() {
    return new File(getJbiInstanceDir(), JBI_AUTOINSTALL_DIR);
  }

  public static final String JBI_CONFIG_PRIVATE_DIR = "private";

  public File getJbiConfigPrivateDir() {
    return new File(getJbiConfigDir(), JBI_CONFIG_PRIVATE_DIR);
  }

  public static final String JBI_REGISTRY_FILE = "jbi-registry.xml";

  public File getJbiRegistryFile() {
    return new File(getJbiConfigDir(), JBI_REGISTRY_FILE);
  }

  public static final String HTTP_BC_CONFIG = "config.properties";

  public File getHttpBcConfigTemplate() {
    return new File(getJbiTemplateDir(), HTTP_BC_CONFIG);
  }

  public File getHttpBcConfigFile() {
    return new File(getHttpBcWorkSpace(), HTTP_BC_CONFIG);
  }

  public static final String IMQ_VAR_DIR = "imq";

  public File getImqVarHome() {
    return new File(getRepositoryDir(), IMQ_VAR_DIR);
  }

  public static final String BIN_DIR = "bin";

  public File getImqBinDir() {
    return new File(getImqDir(), BIN_DIR);
  }

  public File getImqLibDir() {
    return new File(getImqDir(), LIB_DIR);
  }

  public File getInstallRootDir() {
    return getCanonicalFile(new File(getConfig().getInstallRoot()));
  }

  public File getRepositoryRootDir() {
    return getCanonicalFile(new File(getConfig().getRepositoryRoot()));
  }

  public static final String SHARE = "share";

  public File getShareDir() {
    return new File(getInstallRootDir(), SHARE);
  }

  public File getWebServicesLibDir() {
    return new File(getShareDir(), LIB_DIR);
  }

  // $INSTALL_ROOT/lib/install/templates
  public static final String INSTALL_DIR = "install";
  public static final String TEMPLATES_DIR = "templates";
  public static final String COMMON_DIR = "common";
  public static final String PROFILE_PROPERTIES = "profile.properties";
  private static final String TEMPLATE_CONFIG_XML = "default-config.xml";

  public File getTemplatesDir() {
    final File lib = new File(getInstallRootDir(), LIB_DIR);
    // final File install = new File(lib, INSTALL_DIR);
    final File templates = new File(lib, TEMPLATES_DIR);
    return templates;
  }

  public File getProfileFolder(final String profileName) {
    /* Commented out for V3, till things can be more finalized. For
     * now there is only one profile and the template is in the
     * common template directory */

    assert profileName != null : "Name of the profile can't be null";
    final File pf = new File(getTemplatesDir(), profileName);
    return pf;
  }

  public File getProfilePropertiesFile(final String profileName) {
    return (new File(getProfileFolder(profileName), PROFILE_PROPERTIES));
  }

  public File getPreExistingDomainXmlTemplateForProfile(final String profileName) {
    return (new File(getProfileFolder(profileName), DOMAIN_XML_FILE));
  }

  public File getTemplateConfigXml() {
    return (new File(getTemplatesDir(), TEMPLATE_CONFIG_XML));
  }

  // $INSTALL_ROOT/lib/install/applications

  public static final String APPLICATIONS_DIR = "applications";

  public File getInstallApplicationsDir() {
    final File lib = new File(getInstallRootDir(), LIB_DIR);
    final File install = new File(lib, INSTALL_DIR);
    return new File(install, APPLICATIONS_DIR);
  }

  // $INSTALL_ROOT/lib/install/databases

  public static final String DATABASES_DIR = "databases";

  public File getInstallDatabasesDir() {
    final File lib = new File(getInstallRootDir(), LIB_DIR);
    final File install = new File(lib, INSTALL_DIR);
    return new File(install, DATABASES_DIR);
  }

  // $INSTALL_ROOT/lib/dtds

  public static final String DTDS_DIR = "dtds";

  public File getDtdsDir() {
    final File lib = new File(getInstallRootDir(), LIB_DIR);
    return new File(lib, DTDS_DIR);
  }

  // $INSTALL_ROOT/lib/dtds

  public static final String DOMAIN_DTD = "sun-domain_1_3.dtd";

  public File getDtdFile() {
    return new File(getDtdsDir(), DOMAIN_DTD);
  }

  public static final String DOMAIN_XML_TEMPLATE = "default-domain.xml.template";

  public File getDomainXmlTemplate() {
    return new File(getTemplatesDir(), DOMAIN_XML_TEMPLATE);
  }

  public File getDomainXmlTemplate(String templateName) {
    // check to see if the user has specified a template file to be used for
    // domain creation. Assumed that the user specified template file
    // exists in the INSTALL_ROOT/lib/install/templates if path is not absolute.
    if (new File(templateName).isAbsolute()) return new File(templateName);
    else return new File(getTemplatesDir(), templateName);
  }

  public static final String IMQBROKERD_UNIX = "imqbrokerd";
  public static final String IMQBROKERD_WIN = "imqbrokerd.exe";
  public static final String IMQBROKERD = isWindows() ? IMQBROKERD_WIN : IMQBROKERD_UNIX;

  public File getImqBrokerExecutable() {
    return new File(getImqBinDir(), IMQBROKERD);
  }

  public static final String START_SERV_UNIX = "startserv";
  public static final String START_SERV_WIN = "startserv.bat";
  public static final String START_SERV_OS = isWindows() ? START_SERV_WIN : START_SERV_UNIX;

  public File getStartServ() {
    return new File(getBinDir(), START_SERV_OS);
  }

  public static final String START_SERV_TEMPLATE_UNIX = "startserv.tomcat.template";
  public static final String START_SERV_TEMPLATE_WIN = "startserv.tomcat.bat.template";
  public static final String START_SERV_TEMPLATE_OS =
      isWindows() ? START_SERV_TEMPLATE_WIN : START_SERV_TEMPLATE_UNIX;

  public File getStartServTemplate() {
    return new File(getTemplatesDir(), START_SERV_TEMPLATE_OS);
  }

  public static final String STOP_SERV_UNIX = "stopserv";
  public static final String STOP_SERV_WIN = "stopserv.bat";
  public static final String STOP_SERV_OS = isWindows() ? STOP_SERV_WIN : STOP_SERV_UNIX;

  public File getStopServ() {
    return new File(getBinDir(), STOP_SERV_OS);
  }

  public static final String KILL_SERV_UNIX = "killserv";
  public static final String KILL_SERV_WIN = "killserv.bat";
  public static final String KILL_SERV_OS = isWindows() ? KILL_SERV_WIN : KILL_SERV_UNIX;

  public File getKillServ() {
    return new File(getBinDir(), KILL_SERV_OS);
  }

  public File getKillServTemplate() {
    return new File(getTemplatesDir(), KILL_SERV_OS);
  }

  public static final String STOP_SERV_TEMPLATE_UNIX = "stopserv.tomcat.template";
  public static final String STOP_SERV_TEMPLATE_WIN = "stopserv.tomcat.bat.template";
  public static final String STOP_SERV_TEMPLATE_OS =
      isWindows() ? STOP_SERV_TEMPLATE_WIN : STOP_SERV_TEMPLATE_UNIX;

  public File getStopServTemplate() {
    return new File(getTemplatesDir(), STOP_SERV_TEMPLATE_OS);
  }

  public static final String POLICY_FILE = "server.policy";

  public File getPolicyFileTemplate() {
    return new File(getTemplatesDir(), POLICY_FILE);
  }

  public File getPolicyFile() {
    return new File(getConfigRoot(), POLICY_FILE);
  }

  public static final String STUB_FILE = "admch";

  public File getStubFile() {
    return new File(getConfigRoot(), STUB_FILE);
  }

  public static final String SEED_FILE = "admsn";

  public File getSeedFile() {
    return new File(getConfigRoot(), SEED_FILE);
  }

  public File getInstallConfigRoot() {
    return new File(getInstallRootDir(), CONFIG_DIR);
  }

  public static final String ACC_XML_TEMPLATE = "sun-acc.xml";

  public File getAppClientContainerXmlTemplate() {
    return new File(getTemplatesDir(), ACC_XML_TEMPLATE);
  }

  public static final String ACC_XML = "sun-acc.xml";

  public File getAppClientContainerXml() {
    return new File(getConfigRoot(), ACC_XML);
  }

  public static final String SESSION_STORE = "session-store";

  public File getSessionStore() {
    return new File(getRepositoryDir(), SESSION_STORE);
  }

  public static final String AUTO_DEPLOY = "autodeploy";

  public File getAutoDeployDir() {
    return new File(getRepositoryDir(), AUTO_DEPLOY);
  }

  public static final String AUTO_DEPLOY_STATUS = ".autodeploystatus";

  public File getAutoDeployStatusDir() {
    return new File(getAutoDeployDir(), AUTO_DEPLOY_STATUS);
  }

  private static final String AUTO_DEPLOY_OSGI_BUNDLES_DIR = "bundles";

  private File getAutoDeployOSGiBundlesDir() {
    return new File(getAutoDeployDir(), AUTO_DEPLOY_OSGI_BUNDLES_DIR);
  }

  public static final String KEY_FILE_TEMPLATE = "keyfile";

  public File getKeyFileTemplate() {
    return new File(getTemplatesDir(), KEY_FILE_TEMPLATE);
  }

  public static final String KEY_FILE = "keyfile";

  public File getKeyFile() {
    return new File(getConfigRoot(), KEY_FILE);
  }

  public static final String ADMIN_KEY_FILE = "admin-keyfile";

  public File getAdminKeyFile() {
    return new File(getConfigRoot(), ADMIN_KEY_FILE);
  }

  public File getBackupKeyFile() {
    return new File(getRepositoryBackupRoot(), KEY_FILE);
  }

  public static final String INDEX_FILE = "index.html";
  public static final String DOC_ROOT = "docroot";

  public File getIndexFileTemplate() {
    final File docRoot = new File(getTemplatesDir(), DOC_ROOT);
    return new File(docRoot, INDEX_FILE);
  }

  private static final String LOCALES = "locales";

  public File getNonEnglishIndexFileTemplate(Locale locale) {
    File locales = new File(getTemplatesDir(), LOCALES);
    File givenLocale = new File(locales, locale.toString());
    return new File(givenLocale, INDEX_FILE);
  }

  public File getIndexFile() {
    return new File(getDocRoot(), INDEX_FILE);
  }

  private static final String ENGLISH_INDEX_FILE = "index_en.html";

  public File getEnglishIndexFile() {
    return new File(getDocRoot(), ENGLISH_INDEX_FILE);
  }

  public static final String DEFAULT_WEB_XML = "default-web.xml";

  public File getDefaultWebXmlTemplate() {
    return new File(getTemplatesDir(), DEFAULT_WEB_XML);
  }

  public File getDefaultWebXml() {
    return new File(getConfigRoot(), DEFAULT_WEB_XML);
  }

  public static final String LOGGING_PROPERTIES_FILE = "logging.properties";

  public File getLoggingPropertiesTemplate() {
    return new File(getTemplatesDir(), LOGGING_PROPERTIES_FILE);
  }

  public File getLoggingProperties() {
    return new File(getConfigRoot(), LOGGING_PROPERTIES_FILE);
  }

  public static final String LOGIN_CONF = "login.conf";

  public File getLoginConfTemplate() {
    return new File(getTemplatesDir(), LOGIN_CONF);
  }

  public File getLoginConf() {
    return new File(getConfigRoot(), LOGIN_CONF);
  }

  public static final String WSSSERVERCONFIGOLD = "wss-server-config-1.0.xml";

  public File getWssServerConfigOldTemplate() {
    return new File(getTemplatesDir(), WSSSERVERCONFIGOLD);
  }

  public File getWssServerConfigOld() {
    return new File(getConfigRoot(), WSSSERVERCONFIGOLD);
  }

  public static final String WSSSERVERCONFIG = "wss-server-config-2.0.xml";

  public File getWssServerConfigTemplate() {
    return new File(getTemplatesDir(), WSSSERVERCONFIG);
  }

  public File getWssServerConfig() {
    return new File(getConfigRoot(), WSSSERVERCONFIG);
  }

  public static final String KEYSTORE = "keystore.jks";

  public File getKeyStore() {
    return new File(getConfigRoot(), KEYSTORE);
  }

  public static final String TRUSTSTORE_TEMPLATE = "cacerts.jks";

  public File getTrustStoreTemplate() {
    return new File(getTemplatesDir(), TRUSTSTORE_TEMPLATE);
  }

  /**
   * Should be used only in the cases where the actual keystore creation fails. The idea is when we
   * are unable to create the JKS-keystore, we should copy the keystore in templates folder into the
   * domain's config folder. This keystore is by no means a keystore for public use. It's just a
   * keystore with a primary key "changeit" and associated certificate with signature:
   * -------------------------------------------------------------- Keystore type: jks Keystore
   * provider: SUN
   *
   * <p>Your keystore contains 1 entry
   *
   * <p>Alias name: s1as Creation date: Sep 11, 2008 Entry type: keyEntry Certificate chain length:
   * 1 Certificate[1]: Owner: CN=localhost, OU=GlassFish, O=Sun Microsystems, L=Santa Clara,
   * ST=California, C=US Issuer: CN=localhost, OU=GlassFish, O=Sun Microsystems, L=Santa Clara,
   * ST=California, C=US Serial number: 48c9e075 Valid from: Thu Sep 11 20:22:29 PDT 2008 until: Sun
   * Sep 09 20:22:29 PDT 2018 Certificate fingerprints: MD5:
   * 00:E5:5D:1F:07:CC:99:9F:CF:68:0E:AD:29:43:E0:48 SHA1:
   * 1B:62:3E:B2:3D:D7:0B:63:80:92:EE:9A:59:F7:D5:9F:97:A3:FD:98
   * --------------------------------------------------------------
   *
   * @return File representing the keystore path. Does not check if the path actually exists.
   */
  public File getKeyStoreTemplate() {
    return new File(getTemplatesDir(), KEYSTORE);
  }

  public static final String TRUSTSTORE = "cacerts.jks";

  public File getTrustStore() {
    return new File(getConfigRoot(), TRUSTSTORE);
  }

  public static final String MASTERPASSWORD_FILE = "master-password";

  public File getMasterPasswordFile() {
    return new File(getRepositoryDir(), MASTERPASSWORD_FILE);
  }

  public static final String PASSWORD_ALIAS_KEYSTORE = PasswordAdapter.PASSWORD_ALIAS_KEYSTORE;

  public File getPasswordAliasKeystore() {
    return new File(getConfigRoot(), PASSWORD_ALIAS_KEYSTORE);
  }

  public static final String TIMERDB_WAL_TEMPLATE = "ejbtimer$1.wal";

  public File getTimerWalTemplate() {
    return new File(getInstallDatabasesDir(), TIMERDB_WAL_TEMPLATE);
  }

  public static final String TIMERDB_WAL = "ejbtimer$1.wal";

  public File getTimerWal() {
    return new File(getTimerDatabaseDir(), TIMERDB_WAL);
  }

  public static final String TIMERDB_DBN_TEMPLATE = "ejbtimer.dbn";

  public File getTimerDbnTemplate() {
    return new File(getInstallDatabasesDir(), TIMERDB_DBN_TEMPLATE);
  }

  public static final String TIMERDB_DBN = "ejbtimer.dbn";

  public File getTimerDbn() {
    return new File(getTimerDatabaseDir(), TIMERDB_DBN);
  }

  public static final String DERBY_SQL_FILE = "ejbtimer_derby.sql";
  public static final String EJB_TIMER_TABLE_NAME = "EJB__TIMER__TBL"; // comes from sql file

  public File getDerbyEjbTimerSqlFile() {
    return new File(getInstallDatabasesDir(), DERBY_SQL_FILE);
  }

  public static final String DERBY_DATABASE_DIRECTORY = "ejbtimer";

  public File getDerbyEjbTimerDatabaseDirectory() {
    return new File(getTimerDatabaseDir(), DERBY_DATABASE_DIRECTORY);
    // this directory must not exist before creating the derby database
  }

  protected static boolean isWindows() {
    return OS.isWindows();
  }

  File getCanonicalFile(File f) {
    return FileUtils.safeGetCanonicalFile(f);
  }

  /**
   * This method is used to create the file layout for JBI system components, HttpSoapBC, JavaEESE,
   * WSDLSL
   */
  public void createJbiSystemComponentsLayout() throws RepositoryException {
    try {
      createDirectory(getHttpBcDir());
      createDirectory(getHttpBcInstallRoot());
      createDirectory(getJavaEESEDir());
      createDirectory(getJavaEESEInstallRoot());
      createDirectory(getWSDLSLDir());
      createDirectory(getWSDLSLInstallRoot());
      createDirectory(getHttpBcWorkSpace());
      createDirectory(getJavaEESEWorkSpace());
    } catch (Exception e) {
      throw new RepositoryException(e);
    }
  }

  /** This method is used to create WSDLSL install root */
  public void createWSDLSLInstallRoot() throws Exception {
    createDirectory(getWSDLSLDir());
    createDirectory(getWSDLSLInstallRoot());
  }

  public static final String JBI_COMPONENTS = "components";

  public File getJbiComponents() {
    return new File(getJbiDir(), JBI_COMPONENTS);
  }

  public static final String HTTP_BC_ARCHIVE = "httpbc.jar";

  public File getHttpBcArchiveSource() {
    File bcDir = new File(getJbiComponents(), HTTP_BC_DIR);
    return new File(bcDir, HTTP_BC_ARCHIVE);
  }

  public File getHttpBcArchiveDestination() {
    return new File(getHttpBcDir(), HTTP_BC_ARCHIVE);
  }

  public static final String JBI_COMPONENTS_INSTALL_ROOT = "install_root";

  public File getHttpBcInstallRoot() {
    return new File(getHttpBcDir(), JBI_COMPONENTS_INSTALL_ROOT);
  }

  public static final String JAVAEE_SE_ARCHIVE = "appserv-jbise.jar";

  public File getJavaEESEArchiveSource() {
    File seDir = new File(getJbiComponents(), JAVAEE_SE_DIR);
    return new File(seDir, JAVAEE_SE_ARCHIVE);
  }

  public File getJavaEESEArchiveDestination() {
    return new File(getJavaEESEDir(), JAVAEE_SE_ARCHIVE);
  }

  public File getJavaEESEInstallRoot() {
    return new File(getJavaEESEDir(), JBI_COMPONENTS_INSTALL_ROOT);
  }

  public static final String JBI_SHARED_LIBRARIES = "shared-libraries";

  public File getJbiSharedLibraries() {
    return new File(getJbiDir(), JBI_SHARED_LIBRARIES);
  }

  public static final String WSDLSL_DIR = "sun-wsdl-library";

  public File getWSDLSLDir() {
    return new File(getJbiSharedLibDir(), WSDLSL_DIR);
  }

  public static final String WSDLSL_ARCHIVE = "wsdlsl.jar";

  public File getWSDLSLArchiveSource() {
    File slDir = new File(getJbiSharedLibraries(), WSDLSL_DIR);
    return new File(slDir, WSDLSL_ARCHIVE);
  }

  public File getWSDLSLArchiveDestination() {
    return new File(getWSDLSLDir(), WSDLSL_ARCHIVE);
  }

  public File getWSDLSLInstallRoot() {
    return new File(getWSDLSLDir(), JBI_COMPONENTS_INSTALL_ROOT);
  }
}
@Service
@ResourceDeployerInfo(JdbcConnectionPool.class)
@Singleton
public class JdbcConnectionPoolDeployer implements ResourceDeployer {

  @Inject private ConnectorRuntime runtime;

  @Inject @Optional // we need it only in server mode
  private Domain domain;

  private static StringManager sm = StringManager.getManager(JdbcConnectionPoolDeployer.class);
  private static String msg = sm.getString("resource.restart_needed");

  private static Logger _logger = LoggerFactory.getLogger(JdbcConnectionPoolDeployer.class);

  private static final Locale locale = Locale.getDefault();

  private ExecutorService execService =
      Executors.newSingleThreadExecutor(
          new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
              return new Thread(r);
            }
          });

  /** {@inheritDoc} */
  @Override
  public void deployResource(Object resource, String applicationName, String moduleName)
      throws Exception {
    // deployResource is not synchronized as there is only one caller
    // ResourceProxy which is synchronized

    // intentional no-op
    // From 8.1 PE/SE/EE, JDBC connection pools are no more resources and
    // they would be available only to server instances that have a resoruce-ref
    // that maps to a pool. So deploy resource would not be called during
    // JDBC connection pool creation. The actualDeployResource method
    // below is invoked by JdbcResourceDeployer when a resource-ref for a
    // resource that is pointed to this pool is added to a server instance
    JdbcConnectionPool jcp = (JdbcConnectionPool) resource;
    PoolInfo poolInfo = new PoolInfo(jcp.getName(), applicationName, moduleName);
    if (_logger.isLoggable(Level.FINE)) {
      _logger.fine(
          " JdbcConnectionPoolDeployer - deployResource : " + poolInfo + " calling actualDeploy");
    }
    actualDeployResource(resource, poolInfo);
  }

  /** {@inheritDoc} */
  @Override
  public void deployResource(Object resource) throws Exception {

    JdbcConnectionPool jcp = (JdbcConnectionPool) resource;
    PoolInfo poolInfo = ConnectorsUtil.getPoolInfo(jcp);
    actualDeployResource(resource, poolInfo);
  }

  /** {@inheritDoc} */
  @Override
  public boolean canDeploy(
      boolean postApplicationDeployment, Collection<Resource> allResources, Resource resource) {
    if (handles(resource)) {
      if (!postApplicationDeployment) {
        return true;
      }
    }
    return false;
  }

  /**
   * Deploy the resource into the server's runtime naming context
   *
   * @param resource a resource object
   * @throws Exception thrown if fail
   */
  public void actualDeployResource(Object resource, PoolInfo poolInfo) {
    if (_logger.isLoggable(Level.FINE)) {
      _logger.fine(" JdbcConnectionPoolDeployer - actualDeployResource : " + poolInfo);
    }
    JdbcConnectionPool adminPool = (JdbcConnectionPool) resource;
    try {
      ConnectorConnectionPool connConnPool = createConnectorConnectionPool(adminPool, poolInfo);
      registerTransparentDynamicReconfigPool(poolInfo, adminPool);
      // now do internal book keeping
      runtime.createConnectorConnectionPool(connConnPool);
    } catch (Exception e) {
      Object params[] = new Object[] {poolInfo, e};
      _logger.log(Level.WARNING, "error.creating.jdbc.pool", params);
    }
  }

  // performance issue related fix : IT 15784
  private void registerTransparentDynamicReconfigPool(
      PoolInfo poolInfo, JdbcConnectionPool resourcePool) {
    ConnectorRegistry registry = ConnectorRegistry.getInstance();
    if (ConnectorsUtil.isDynamicReconfigurationEnabled(resourcePool)) {
      registry.addTransparentDynamicReconfigPool(poolInfo);
    } else {
      registry.removeTransparentDynamicReconfigPool(poolInfo);
    }
  }

  /** {@inheritDoc} */
  @Override
  public void undeployResource(Object resource, String applicationName, String moduleName)
      throws Exception {
    JdbcConnectionPool jdbcConnPool = (JdbcConnectionPool) resource;
    PoolInfo poolInfo = new PoolInfo(jdbcConnPool.getName(), applicationName, moduleName);
    if (_logger.isLoggable(Level.FINE)) {
      _logger.fine(
          " JdbcConnectionPoolDeployer - unDeployResource : "
              + "calling actualUndeploy of "
              + poolInfo);
    }
    actualUndeployResource(poolInfo);
  }

  /** {@inheritDoc} */
  @Override
  public synchronized void undeployResource(Object resource) throws Exception {
    JdbcConnectionPool jdbcConnPool = (JdbcConnectionPool) resource;
    PoolInfo poolInfo = ConnectorsUtil.getPoolInfo(jdbcConnPool);
    if (_logger.isLoggable(Level.FINE)) {
      _logger.fine(
          " JdbcConnectionPoolDeployer - unDeployResource : "
              + "calling actualUndeploy of "
              + poolInfo);
    }
    actualUndeployResource(poolInfo);
  }

  /** {@inheritDoc} */
  @Override
  public boolean handles(Object resource) {
    return resource instanceof JdbcConnectionPool;
  }

  /** @inheritDoc */
  @Override
  public boolean supportsDynamicReconfiguration() {
    return true;
  }

  /** @inheritDoc */
  @Override
  public Class[] getProxyClassesForDynamicReconfiguration() {
    return new Class[] {com.sun.appserv.jdbc.DataSource.class};
  }

  /**
   * Undeploy the resource from the server's runtime naming context
   *
   * @param poolInfo a resource object
   * @throws UnsupportedOperationException Currently we are not supporting this method.
   */
  private synchronized void actualUndeployResource(PoolInfo poolInfo) throws Exception {
    runtime.deleteConnectorConnectionPool(poolInfo);
    // performance issue related fix : IT 15784
    ConnectorRegistry.getInstance().removeTransparentDynamicReconfigPool(poolInfo);
    if (_logger.isLoggable(Level.FINEST)) {
      _logger.finest("Pool Undeployed");
    }
  }

  /**
   * Pull out the MCF configuration properties and return them as an array of
   * ConnectorConfigProperty
   *
   * @param adminPool - The JdbcConnectionPool to pull out properties from
   * @param conConnPool - ConnectorConnectionPool which will be used by Resource Pool
   * @param connDesc - The ConnectorDescriptor for this JDBC RA
   * @return ConnectorConfigProperty [] array of MCF Config properties specified in this JDBC RA
   */
  private ConnectorConfigProperty[] getMCFConfigProperties(
      JdbcConnectionPool adminPool,
      ConnectorConnectionPool conConnPool,
      ConnectorDescriptor connDesc) {

    ArrayList propList = new ArrayList();

    if (adminPool.getResType() != null) {
      if (ConnectorConstants.JAVA_SQL_DRIVER.equals(adminPool.getResType())) {
        propList.add(
            new ConnectorConfigProperty(
                "ClassName",
                adminPool.getDriverClassname() == null ? "" : adminPool.getDriverClassname(),
                "The driver class name",
                "java.lang.String"));
      } else {
        propList.add(
            new ConnectorConfigProperty(
                "ClassName",
                adminPool.getDatasourceClassname() == null
                    ? ""
                    : adminPool.getDatasourceClassname(),
                "The datasource class name",
                "java.lang.String"));
      }
    } else {
      // When resType is null, one of these classnames would be specified
      if (adminPool.getDriverClassname() != null) {
        propList.add(
            new ConnectorConfigProperty(
                "ClassName",
                adminPool.getDriverClassname() == null ? "" : adminPool.getDriverClassname(),
                "The driver class name",
                "java.lang.String"));
      } else if (adminPool.getDatasourceClassname() != null) {
        propList.add(
            new ConnectorConfigProperty(
                "ClassName",
                adminPool.getDatasourceClassname() == null
                    ? ""
                    : adminPool.getDatasourceClassname(),
                "The datasource class name",
                "java.lang.String"));
      }
    }
    propList.add(
        new ConnectorConfigProperty(
            "ConnectionValidationRequired",
            adminPool.getIsConnectionValidationRequired() + "",
            "Is connection validation required",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "ValidationMethod",
            adminPool.getConnectionValidationMethod() == null
                ? ""
                : adminPool.getConnectionValidationMethod(),
            "How the connection is validated",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "ValidationTableName",
            adminPool.getValidationTableName() == null ? "" : adminPool.getValidationTableName(),
            "Validation Table name",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "ValidationClassName",
            adminPool.getValidationClassname() == null ? "" : adminPool.getValidationClassname(),
            "Validation Class name",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "TransactionIsolation",
            adminPool.getTransactionIsolationLevel() == null
                ? ""
                : adminPool.getTransactionIsolationLevel(),
            "Transaction Isolatin Level",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "GuaranteeIsolationLevel",
            adminPool.getIsIsolationLevelGuaranteed() + "",
            "Transaction Isolation Guarantee",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "StatementWrapping",
            adminPool.getWrapJdbcObjects() + "",
            "Statement Wrapping",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "LogJdbcCalls",
            adminPool.getLogJdbcCalls() + "",
            "Log JDBC Calls",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "SlowQueryThresholdInSeconds",
            adminPool.getSlowQueryThresholdInSeconds() + "",
            "Slow Query Threshold In Seconds",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "StatementTimeout",
            adminPool.getStatementTimeoutInSeconds() + "",
            "Statement Timeout",
            "java.lang.String"));

    PoolInfo poolInfo = conConnPool.getPoolInfo();

    propList.add(
        new ConnectorConfigProperty(
            "PoolMonitoringSubTreeRoot",
            ConnectorsUtil.getPoolMonitoringSubTreeRoot(poolInfo, true) + "",
            "Pool Monitoring Sub Tree Root",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "PoolName", poolInfo.getName() + "", "Pool Name", "java.lang.String"));

    if (poolInfo.getApplicationName() != null) {
      propList.add(
          new ConnectorConfigProperty(
              "ApplicationName",
              poolInfo.getApplicationName() + "",
              "Application Name",
              "java.lang.String"));
    }

    if (poolInfo.getModuleName() != null) {
      propList.add(
          new ConnectorConfigProperty(
              "ModuleName", poolInfo.getModuleName() + "", "Module name", "java.lang.String"));
    }

    propList.add(
        new ConnectorConfigProperty(
            "StatementCacheSize",
            adminPool.getStatementCacheSize() + "",
            "Statement Cache Size",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "StatementCacheType",
            adminPool.getStatementCacheType() + "",
            "Statement Cache Type",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "InitSql", adminPool.getInitSql() + "", "InitSql", "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "SqlTraceListeners",
            adminPool.getSqlTraceListeners() + "",
            "Sql Trace Listeners",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "StatementLeakTimeoutInSeconds",
            adminPool.getStatementLeakTimeoutInSeconds() + "",
            "Statement Leak Timeout in seconds",
            "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "StatementLeakReclaim",
            adminPool.getStatementLeakReclaim() + "",
            "Statement Leak Reclaim",
            "java.lang.String"));

    // dump user defined poperties into the list
    Set connDefDescSet = connDesc.getOutboundResourceAdapter().getConnectionDefs();
    // since this a 1.0 RAR, we will have only 1 connDefDesc
    if (connDefDescSet.size() != 1) {
      throw new MissingResourceException("Only one connDefDesc present", null, null);
    }

    Iterator iter = connDefDescSet.iterator();

    // Now get the set of MCF config properties associated with each
    // connection-definition . Each element here is an EnviromnentProperty
    Set mcfConfigProps = null;
    while (iter.hasNext()) {
      mcfConfigProps = ((ConnectionDefDescriptor) iter.next()).getConfigProperties();
    }
    if (mcfConfigProps != null) {

      Map mcfConPropKeys = new HashMap();
      Iterator mcfConfigPropsIter = mcfConfigProps.iterator();
      while (mcfConfigPropsIter.hasNext()) {
        String key = ((ConnectorConfigProperty) mcfConfigPropsIter.next()).getName();
        mcfConPropKeys.put(key.toUpperCase(locale), key);
      }

      String driverProperties = "";
      for (Property rp : adminPool.getProperty()) {
        if (rp == null) {
          continue;
        }
        String name = rp.getName();

        // The idea here is to convert the Environment Properties coming from
        // the admin connection pool to standard pool properties thereby
        // making it easy to compare in the event of a reconfig
        if ("MATCHCONNECTIONS".equals(name.toUpperCase(locale))) {
          // JDBC - matchConnections if not set is decided by the ConnectionManager
          // so default is false
          conConnPool.setMatchConnections(toBoolean(rp.getValue(), false));
          logFine("MATCHCONNECTIONS");

        } else if ("ASSOCIATEWITHTHREAD".equals(name.toUpperCase(locale))) {
          conConnPool.setAssociateWithThread(toBoolean(rp.getValue(), false));
          logFine("ASSOCIATEWITHTHREAD");

        } else if ("LAZYCONNECTIONASSOCIATION".equals(name.toUpperCase(locale))) {
          ConnectionPoolObjectsUtils.setLazyEnlistAndLazyAssocProperties(
              rp.getValue(), adminPool.getProperty(), conConnPool);
          logFine("LAZYCONNECTIONASSOCIATION");

        } else if ("LAZYCONNECTIONENLISTMENT".equals(name.toUpperCase(Locale.getDefault()))) {
          conConnPool.setLazyConnectionEnlist(toBoolean(rp.getValue(), false));
          logFine("LAZYCONNECTIONENLISTMENT");

        } else if ("POOLDATASTRUCTURE".equals(name.toUpperCase(Locale.getDefault()))) {
          conConnPool.setPoolDataStructureType(rp.getValue());
          logFine("POOLDATASTRUCTURE");

        } else if (ConnectorConstants.DYNAMIC_RECONFIGURATION_FLAG.equals(
            name.toLowerCase(locale))) {
          String value = rp.getValue();
          try {
            conConnPool.setDynamicReconfigWaitTimeout(Long.parseLong(rp.getValue()) * 1000L);
            logFine(ConnectorConstants.DYNAMIC_RECONFIGURATION_FLAG);
          } catch (NumberFormatException nfe) {
            _logger.log(
                Level.WARNING,
                "Invalid value for "
                    + "'"
                    + ConnectorConstants.DYNAMIC_RECONFIGURATION_FLAG
                    + "' : "
                    + value);
          }
        } else if ("POOLWAITQUEUE".equals(name.toUpperCase(locale))) {
          conConnPool.setPoolWaitQueue(rp.getValue());
          logFine("POOLWAITQUEUE");

        } else if ("DATASTRUCTUREPARAMETERS".equals(name.toUpperCase(locale))) {
          conConnPool.setDataStructureParameters(rp.getValue());
          logFine("DATASTRUCTUREPARAMETERS");

        } else if ("USERNAME".equals(name.toUpperCase(Locale.getDefault()))
            || "USER".equals(name.toUpperCase(locale))) {

          propList.add(
              new ConnectorConfigProperty("User", rp.getValue(), "user name", "java.lang.String"));

        } else if ("PASSWORD".equals(name.toUpperCase(locale))) {

          propList.add(
              new ConnectorConfigProperty(
                  "Password", rp.getValue(), "Password", "java.lang.String"));

        } else if ("JDBC30DATASOURCE".equals(name.toUpperCase(locale))) {

          propList.add(
              new ConnectorConfigProperty(
                  "JDBC30DataSource", rp.getValue(), "JDBC30DataSource", "java.lang.String"));

        } else if ("PREFER-VALIDATE-OVER-RECREATE".equals(name.toUpperCase(Locale.getDefault()))) {
          String value = rp.getValue();
          conConnPool.setPreferValidateOverRecreate(toBoolean(value, false));
          logFine("PREFER-VALIDATE-OVER-RECREATE : " + value);

        } else if ("STATEMENT-CACHE-TYPE".equals(name.toUpperCase(Locale.getDefault()))) {

          if (adminPool.getStatementCacheType() != null) {
            propList.add(
                new ConnectorConfigProperty(
                    "StatementCacheType", rp.getValue(), "StatementCacheType", "java.lang.String"));
          }

        } else if ("NUMBER-OF-TOP-QUERIES-TO-REPORT"
            .equals(name.toUpperCase(Locale.getDefault()))) {

          propList.add(
              new ConnectorConfigProperty(
                  "NumberOfTopQueriesToReport",
                  rp.getValue(),
                  "NumberOfTopQueriesToReport",
                  "java.lang.String"));

        } else if ("TIME-TO-KEEP-QUERIES-IN-MINUTES"
            .equals(name.toUpperCase(Locale.getDefault()))) {

          propList.add(
              new ConnectorConfigProperty(
                  "TimeToKeepQueriesInMinutes",
                  rp.getValue(),
                  "TimeToKeepQueriesInMinutes",
                  "java.lang.String"));

        } else if (mcfConPropKeys.containsKey(name.toUpperCase(Locale.getDefault()))) {

          propList.add(
              new ConnectorConfigProperty(
                  (String) mcfConPropKeys.get(name.toUpperCase(Locale.getDefault())),
                  rp.getValue() == null ? "" : rp.getValue(),
                  "Some property",
                  "java.lang.String"));
        } else {
          driverProperties =
              driverProperties + "set" + escape(name) + "#" + escape(rp.getValue()) + "##";
        }
      }

      if (!driverProperties.equals("")) {
        propList.add(
            new ConnectorConfigProperty(
                "DriverProperties",
                driverProperties,
                "some proprietarty properties",
                "java.lang.String"));
      }
    }

    propList.add(new ConnectorConfigProperty("Delimiter", "#", "delim", "java.lang.String"));

    propList.add(
        new ConnectorConfigProperty(
            "EscapeCharacter", "\\", "escapeCharacter", "java.lang.String"));

    // create an array of EnvironmentProperties from above list
    ConnectorConfigProperty[] eProps = new ConnectorConfigProperty[propList.size()];
    ListIterator propListIter = propList.listIterator();

    for (int i = 0; propListIter.hasNext(); i++) {
      eProps[i] = (ConnectorConfigProperty) propListIter.next();
    }

    return eProps;
  }

  /**
   * To escape the "delimiter" characters that are internally used by Connector & JDBCRA.
   *
   * @param value String that need to be escaped
   * @return Escaped value
   */
  private String escape(String value) {
    CharSequence seq = "\\";
    CharSequence replacement = "\\\\";
    value = value.replace(seq, replacement);

    seq = "#";
    replacement = "\\#";
    value = value.replace(seq, replacement);
    return value;
  }

  private boolean toBoolean(Object prop, boolean defaultVal) {
    if (prop == null) {
      return defaultVal;
    }
    return Boolean.valueOf(((String) prop).toLowerCase(locale));
  }

  /**
   * Use this method if the string being passed does not <br>
   * involve multiple concatenations<br>
   * Avoid using this method in exception-catch blocks as they are not frequently executed <br>
   *
   * @param msg
   */
  private void logFine(String msg) {
    if (_logger.isLoggable(Level.FINE) && msg != null) {
      _logger.fine(msg);
    }
  }

  public ConnectorConnectionPool createConnectorConnectionPool(
      JdbcConnectionPool adminPool, PoolInfo poolInfo) throws ConnectorRuntimeException {

    String moduleName = JdbcResourcesUtil.createInstance().getRANameofJdbcConnectionPool(adminPool);
    int txSupport = getTxSupport(moduleName);

    ConnectorDescriptor connDesc = runtime.getConnectorDescriptor(moduleName);

    // Create the connector Connection Pool object from the configbean object
    ConnectorConnectionPool conConnPool = new ConnectorConnectionPool(poolInfo);

    conConnPool.setTransactionSupport(txSupport);
    setConnectorConnectionPoolAttributes(conConnPool, adminPool);

    // Initially create the ConnectorDescriptor
    ConnectorDescriptorInfo connDescInfo = createConnectorDescriptorInfo(connDesc, moduleName);

    connDescInfo.setMCFConfigProperties(getMCFConfigProperties(adminPool, conConnPool, connDesc));

    // since we are deploying a 1.0 RAR, this is null
    connDescInfo.setResourceAdapterConfigProperties((Set) null);

    conConnPool.setConnectorDescriptorInfo(connDescInfo);

    return conConnPool;
  }

  private int getTxSupport(String moduleName) {
    if (ConnectorConstants.JDBCXA_RA_NAME.equals(moduleName)) {
      return ConnectionPoolObjectsUtils.parseTransactionSupportString(
          ConnectorConstants.XA_TRANSACTION_TX_SUPPORT_STRING);
    }
    return ConnectionPoolObjectsUtils.parseTransactionSupportString(
        ConnectorConstants.LOCAL_TRANSACTION_TX_SUPPORT_STRING);
  }

  private ConnectorDescriptorInfo createConnectorDescriptorInfo(
      ConnectorDescriptor connDesc, String moduleName) {
    ConnectorDescriptorInfo connDescInfo = new ConnectorDescriptorInfo();

    connDescInfo.setManagedConnectionFactoryClass(
        connDesc.getOutboundResourceAdapter().getManagedConnectionFactoryImpl());

    connDescInfo.setRarName(moduleName);

    connDescInfo.setResourceAdapterClassName(connDesc.getResourceAdapterClass());

    connDescInfo.setConnectionDefinitionName(
        connDesc.getOutboundResourceAdapter().getConnectionFactoryIntf());

    connDescInfo.setConnectionFactoryClass(
        connDesc.getOutboundResourceAdapter().getConnectionFactoryImpl());

    connDescInfo.setConnectionFactoryInterface(
        connDesc.getOutboundResourceAdapter().getConnectionFactoryIntf());

    connDescInfo.setConnectionClass(connDesc.getOutboundResourceAdapter().getConnectionImpl());

    connDescInfo.setConnectionInterface(connDesc.getOutboundResourceAdapter().getConnectionIntf());

    return connDescInfo;
  }

  private void setConnectorConnectionPoolAttributes(
      ConnectorConnectionPool ccp, JdbcConnectionPool adminPool) {
    String poolName = ccp.getName();
    ccp.setMaxPoolSize(adminPool.getMaxPoolSize());
    ccp.setSteadyPoolSize(adminPool.getSteadyPoolSize());
    ccp.setMaxWaitTimeInMillis(adminPool.getMaxWaitTimeInMillis());

    ccp.setPoolResizeQuantity(adminPool.getPoolResizeQuantity());

    ccp.setIdleTimeoutInSeconds(adminPool.getIdleTimeoutInSeconds());

    ccp.setFailAllConnections(Boolean.valueOf(adminPool.getFailAllConnections()));

    ccp.setConnectionValidationRequired(
        Boolean.valueOf(adminPool.getIsConnectionValidationRequired()));

    ccp.setNonTransactional(Boolean.valueOf(adminPool.getNonTransactionalConnections()));
    ccp.setNonComponent(Boolean.valueOf(adminPool.getAllowNonComponentCallers()));

    ccp.setPingDuringPoolCreation(Boolean.valueOf(adminPool.getPing()));
    // These are default properties of all Jdbc pools
    // So set them here first and then figure out from the parsing routine
    // if they need to be reset
    ccp.setMatchConnections(Boolean.valueOf(adminPool.getMatchConnections()));
    ccp.setAssociateWithThread(Boolean.valueOf(adminPool.getAssociateWithThread()));
    ccp.setConnectionLeakTracingTimeout(adminPool.getConnectionLeakTimeoutInSeconds());
    ccp.setConnectionReclaim(Boolean.valueOf(adminPool.getConnectionLeakReclaim()));

    boolean lazyConnectionEnlistment = Boolean.valueOf(adminPool.getLazyConnectionEnlistment());
    boolean lazyConnectionAssociation = Boolean.valueOf(adminPool.getLazyConnectionAssociation());

    // lazy-connection-enlistment need to be ON for lazy-connection-association to work.
    if (lazyConnectionAssociation) {
      if (lazyConnectionEnlistment) {
        ccp.setLazyConnectionAssoc(true);
        ccp.setLazyConnectionEnlist(true);
      } else {
        _logger.log(
            Level.SEVERE,
            "conn_pool_obj_utils.lazy_enlist-lazy_assoc-invalid-combination",
            poolName);
        String i18nMsg = sm.getString("cpou.lazy_enlist-lazy_assoc-invalid-combination", poolName);
        throw new RuntimeException(i18nMsg);
      }
    } else {
      ccp.setLazyConnectionAssoc(lazyConnectionAssociation);
      ccp.setLazyConnectionEnlist(lazyConnectionEnlistment);
    }

    boolean pooling = Boolean.valueOf(adminPool.getPooling());

    if (!pooling) {
      // Throw exception if assoc with thread is set to true.
      if (Boolean.valueOf(adminPool.getAssociateWithThread())) {
        _logger.log(
            Level.SEVERE,
            "conn_pool_obj_utils.pooling_disabled_assocwiththread_invalid_combination",
            poolName);
        String i18nMsg =
            sm.getString("cpou.pooling_disabled_assocwiththread_invalid_combination", poolName);
        throw new RuntimeException(i18nMsg);
      }

      // Below are useful in pooled environment only.
      // Throw warning for connection validation/validate-atmost-once/
      // match-connections/max-connection-usage-count/idele-timeout
      if (Boolean.valueOf(adminPool.getIsConnectionValidationRequired())) {
        _logger.log(
            Level.WARNING,
            "conn_pool_obj_utils.pooling_disabled_conn_validation_invalid_combination",
            poolName);
      }
      if (Integer.parseInt(adminPool.getValidateAtmostOncePeriodInSeconds()) > 0) {
        _logger.log(
            Level.WARNING,
            "conn_pool_obj_utils.pooling_disabled_validate_atmost_once_invalid_combination",
            poolName);
      }
      if (Boolean.valueOf(adminPool.getMatchConnections())) {
        _logger.log(
            Level.WARNING,
            "conn_pool_obj_utils.pooling_disabled_match_connections_invalid_combination",
            poolName);
      }
      if (Integer.parseInt(adminPool.getMaxConnectionUsageCount()) > 0) {
        _logger.log(
            Level.WARNING,
            "conn_pool_obj_utils.pooling_disabled_max_conn_usage_invalid_combination",
            poolName);
      }
      if (Integer.parseInt(adminPool.getIdleTimeoutInSeconds()) > 0) {
        _logger.log(
            Level.WARNING,
            "conn_pool_obj_utils.pooling_disabled_idle_timeout_invalid_combination",
            poolName);
      }
    }
    ccp.setPooling(pooling);
    ccp.setMaxConnectionUsage(adminPool.getMaxConnectionUsageCount());

    ccp.setConCreationRetryAttempts(adminPool.getConnectionCreationRetryAttempts());
    ccp.setConCreationRetryInterval(adminPool.getConnectionCreationRetryIntervalInSeconds());

    ccp.setValidateAtmostOncePeriod(adminPool.getValidateAtmostOncePeriodInSeconds());
  }

  /** {@inheritDoc} */
  @Override
  public synchronized void redeployResource(Object resource) throws Exception {

    final JdbcConnectionPool adminPool = (JdbcConnectionPool) resource;
    PoolInfo poolInfo = ConnectorsUtil.getPoolInfo(adminPool);

    // Only if pool has already been deployed in this server-instance
    // reconfig this pool

    if (!runtime.isConnectorConnectionPoolDeployed(poolInfo)) {
      if (_logger.isLoggable(Level.FINE)) {
        _logger.fine(
            "The JDBC connection pool "
                + poolInfo
                + " is not referred or not yet created in this server "
                + "instance and hence pool redeployment is ignored");
      }
      return;
    }
    final ConnectorConnectionPool connConnPool = createConnectorConnectionPool(adminPool, poolInfo);

    if (connConnPool == null) {
      throw new ConnectorRuntimeException(
          "Unable to create ConnectorConnectionPool" + "from JDBC connection pool");
    }

    // now do internal book keeping
    HashSet excludes = new HashSet();
    // add MCF config props to the set that need to be excluded
    // in checking for the equality of the props with old pool
    excludes.add("TransactionIsolation");
    excludes.add("GuaranteeIsolationLevel");
    excludes.add("ValidationTableName");
    excludes.add("ConnectionValidationRequired");
    excludes.add("ValidationMethod");
    excludes.add("StatementWrapping");
    excludes.add("StatementTimeout");
    excludes.add("ValidationClassName");
    excludes.add("StatementCacheSize");
    excludes.add("StatementCacheType");
    excludes.add("StatementLeakTimeoutInSeconds");
    excludes.add("StatementLeakReclaim");

    try {
      if (_logger.isLoggable(Level.FINEST)) {
        _logger.finest("Calling reconfigure pool");
      }
      boolean requirePoolRecreation =
          runtime.reconfigureConnectorConnectionPool(connConnPool, excludes);
      if (requirePoolRecreation) {
        if (runtime.isServer() || runtime.isEmbedded()) {
          handlePoolRecreation(connConnPool);
        } else {
          recreatePool(connConnPool);
        }
      }
    } catch (ConnectorRuntimeException cre) {
      Object params[] = new Object[] {poolInfo, cre};
      _logger.log(Level.WARNING, "error.redeploying.jdbc.pool", params);
      throw cre;
    }
  }

  private void handlePoolRecreation(final ConnectorConnectionPool connConnPool)
      throws ConnectorRuntimeException {
    debug("[DRC] Pool recreation required");

    final long reconfigWaitTimeout = connConnPool.getDynamicReconfigWaitTimeout();
    PoolInfo poolInfo =
        new PoolInfo(
            connConnPool.getName(),
            connConnPool.getApplicationName(),
            connConnPool.getModuleName());
    final ResourcePool oldPool = runtime.getPoolManager().getPool(poolInfo);

    if (reconfigWaitTimeout > 0) {

      oldPool.blockRequests(reconfigWaitTimeout);

      if (oldPool.getPoolWaitQueue().getQueueLength() > 0
          || oldPool.getPoolStatus().getNumConnUsed() > 0) {

        Runnable thread =
            new Runnable() {
              @Override
              public void run() {
                try {

                  long numSeconds = 5000L; // poll every 5 seconds
                  long steps = reconfigWaitTimeout / numSeconds;
                  if (steps == 0) {
                    waitForCompletion(steps, oldPool, reconfigWaitTimeout);
                  } else {
                    for (long i = 0; i < steps; i++) {
                      waitForCompletion(steps, oldPool, reconfigWaitTimeout);
                      if (oldPool.getPoolWaitQueue().getQueueLength() == 0
                          && oldPool.getPoolStatus().getNumConnUsed() == 0) {
                        debug("wait-queue is empty and num-con-used is 0");
                        break;
                      }
                    }
                  }

                  handlePoolRecreationForExistingProxies(connConnPool);

                  PoolWaitQueue reconfigWaitQueue = oldPool.getReconfigWaitQueue();
                  debug("checking reconfig-wait-queue for notification");
                  if (reconfigWaitQueue.getQueueContents().size() > 0) {
                    for (Object o : reconfigWaitQueue.getQueueContents()) {
                      debug("notifying reconfig-wait-queue object [ " + o + " ]");
                      synchronized (o) {
                        o.notify();
                      }
                    }
                  }
                } catch (InterruptedException ie) {
                  if (_logger.isLoggable(Level.FINEST)) {
                    _logger.log(
                        Level.FINEST,
                        "Interrupted while waiting for all existing clients to return connections to pool",
                        ie);
                  }
                }

                if (_logger.isLoggable(Level.FINEST)) {
                  _logger.finest(
                      "woke-up after giving time for in-use connections to return, "
                          + "WaitQueue-Length : ["
                          + oldPool.getPoolWaitQueue().getQueueContents()
                          + "], "
                          + "Num-Conn-Used : ["
                          + oldPool.getPoolStatus().getNumConnUsed()
                          + "]");
                }
              }
            };

        Callable c = Executors.callable(thread);
        ArrayList list = new ArrayList();
        list.add(c);
        try {
          execService.invokeAll(list);
        } catch (Exception e) {
          Object[] params = new Object[] {connConnPool.getName(), e};
          _logger.log(Level.WARNING, "exception.redeploying.pool.transparently", params);
        }

      } else {
        handlePoolRecreationForExistingProxies(connConnPool);
      }
    } else if (oldPool.getReconfigWaitTime() > 0) {
      // reconfig is being switched off, invalidate proxies
      Collection<BindableResource> resources =
          JdbcResourcesUtil.getResourcesOfPool(
              runtime.getResources(oldPool.getPoolInfo()), oldPool.getPoolInfo().getName());
      ConnectorRegistry registry = ConnectorRegistry.getInstance();
      for (BindableResource resource : resources) {
        ResourceInfo resourceInfo = ConnectorsUtil.getResourceInfo(resource);
        registry.removeResourceFactories(resourceInfo);
      }
      // recreate the pool now.
      recreatePool(connConnPool);
    } else {
      recreatePool(connConnPool);
    }
  }

  private void waitForCompletion(long steps, ResourcePool oldPool, long totalWaitTime)
      throws InterruptedException {
    debug("waiting for in-use connections to return to pool or waiting requests to complete");
    try {
      Object poolWaitQueue = oldPool.getPoolWaitQueue();
      synchronized (poolWaitQueue) {
        long waitTime = totalWaitTime / steps;
        if (waitTime > 0) {
          poolWaitQueue.wait(waitTime);
        }
      }
    } catch (InterruptedException ie) {
      // ignore
    }
    debug("woke-up to verify in-use / waiting requests list");
  }

  private void handlePoolRecreationForExistingProxies(ConnectorConnectionPool connConnPool) {

    recreatePool(connConnPool);

    Collection<BindableResource> resourcesList;
    if (!connConnPool.isApplicationScopedResource()) {
      resourcesList =
          JdbcResourcesUtil.getResourcesOfPool(domain.getResources(), connConnPool.getName());
    } else {
      PoolInfo poolInfo = connConnPool.getPoolInfo();
      Resources resources = ResourcesUtil.createInstance().getResources(poolInfo);
      resourcesList = JdbcResourcesUtil.getResourcesOfPool(resources, connConnPool.getName());
    }
    for (BindableResource bindableResource : resourcesList) {

      ResourceInfo resourceInfo = ConnectorsUtil.getResourceInfo(bindableResource);
      ConnectorRegistry.getInstance().updateResourceInfoVersion(resourceInfo);
    }
  }

  private void recreatePool(ConnectorConnectionPool connConnPool) {
    try {
      runtime.recreateConnectorConnectionPool(connConnPool);
      debug("Pool [" + connConnPool.getName() + "] recreation done");
    } catch (ConnectorRuntimeException cre) {
      Object params[] = new Object[] {connConnPool.getName(), cre};
      _logger.log(Level.WARNING, "error.redeploying.jdbc.pool", params);
    }
  }

  /**
   * Enable the resource in the server's runtime naming context
   *
   * @param resource a resource object
   * @exception UnsupportedOperationException Currently we are not supporting this method.
   */
  @Override
  public synchronized void enableResource(Object resource) throws Exception {
    throw new UnsupportedOperationException(msg);
  }

  /**
   * Disable the resource in the server's runtime naming context
   *
   * @param resource a resource object
   * @exception UnsupportedOperationException Currently we are not supporting this method.
   */
  @Override
  public synchronized void disableResource(Object resource) throws Exception {
    throw new UnsupportedOperationException(msg);
  }

  /** {@inheritDoc} */
  @Override
  public void validatePreservedResource(
      Application oldApp, Application newApp, Resource resource, Resources allResources)
      throws ResourceConflictException {
    // do nothing.
  }

  private void debug(String message) {
    if (_logger.isLoggable(Level.FINEST)) {
      _logger.finest("[DRC] : " + message);
    }
  }
}
public class JTSConfigChangeEventListener implements JTSEventListener {
  // Sting Manager for Localization
  private static StringManager sm = StringManager.getManager(JTSConfigChangeEventListener.class);

  // Logger to log transaction messages
  static Logger _logger = LogDomains.getLogger(LogDomains.JTA_LOGGER);
  public String xPath = ServerXPathHelper.XPATH_TRANSACTION_SERVICE;

  private static ConfigChangeCategory category =
      new ConfigChangeCategory(
          "jts",
          ServerXPathHelper.REGEX_XPATH_CONFIG
              + ServerXPathHelper.XPATH_SEPARATOR
              + ServerXPathHelper.REGEX_ONE_PLUS
              + ServerTags.TRANSACTION_SERVICE
              + ".*");

  public static ConfigChangeCategory getCategory() {
    return category;
  }

  public void handleCreate(JTSEvent event) throws AdminEventListenerException {
    throw new AdminEventListenerException("handleCreate is not valid for JTSEvent");
  }

  public void handleDelete(JTSEvent event) throws AdminEventListenerException {
    throw new AdminEventListenerException("handleDelete is not valid for JTSEvent");
  }

  public void handleUpdate(JTSEvent event) throws AdminEventListenerException {
    // Bug Id: 4666390 Handle no event in event list case
    if (event == null) {
      // do nothing
      return;
    }
    ArrayList configChangeList = event.getConfigChangeList();
    if (configChangeList == null) {
      // do nothing
      return;
    }
    // Bug Id: 4666390 End

    ConfigUpdate configUpdate = null;
    boolean match = false;
    for (int i = 0; i < configChangeList.size(); i++) {
      configUpdate = (ConfigUpdate) configChangeList.get(i);
      if (configUpdate.getXPath() != null
          && configUpdate.getXPath().endsWith(ServerTags.TRANSACTION_SERVICE)) {
        if (xPath.equals(configUpdate.getXPath())) {
          match = true;
          break;
        }
      }
    }
    if (match) { // TransactionService has been changed
      Set attributeSet = configUpdate.getAttributeSet();
      String next = null;
      for (Iterator iter = attributeSet.iterator(); iter.hasNext(); ) {
        next = (String) iter.next();
        if (next.equals(ServerTags.TIMEOUT_IN_SECONDS)) {
          _logger.log(Level.FINE, " Transaction Timeout interval event occurred");
          String oldTimeout = configUpdate.getOldValue(ServerTags.TIMEOUT_IN_SECONDS);
          String newTimeout = configUpdate.getNewValue(ServerTags.TIMEOUT_IN_SECONDS);
          if (oldTimeout.equals(newTimeout)) {
          } else {
            try {
              Switch.getSwitch()
                  .getTransactionManager()
                  .setDefaultTransactionTimeout(Integer.parseInt(newTimeout, 10));
            } catch (Exception ex) {
              _logger.log(Level.WARNING, "transaction.reconfig_txn_timeout_failed", ex);
            }
          } // timeout-in-seconds
        } else if (next.equals(ServerTags.KEYPOINT_INTERVAL)) {
          _logger.log(Level.FINE, "Keypoint interval event occurred");
          String oldKeyPoint = configUpdate.getOldValue(ServerTags.KEYPOINT_INTERVAL);
          String newKeyPoint = configUpdate.getNewValue(ServerTags.KEYPOINT_INTERVAL);
          if (oldKeyPoint.equals(newKeyPoint)) {
          } else {
            Configuration.setKeypointTrigger(Integer.parseInt(newKeyPoint, 10));
          }
        } else if (next.equals(ServerTags.RETRY_TIMEOUT_IN_SECONDS)) {
          String oldRetryTiemout = configUpdate.getOldValue(ServerTags.RETRY_TIMEOUT_IN_SECONDS);
          String newRetryTiemout = configUpdate.getNewValue(ServerTags.RETRY_TIMEOUT_IN_SECONDS);
          _logger.log(
              Level.FINE, "retry_timeout_in_seconds reconfig event occurred " + newRetryTiemout);
          if (oldRetryTiemout.equals(newRetryTiemout)) {
          } else {
            Configuration.setCommitRetryVar(newRetryTiemout);
          }
        } else {
          // Not handled dynamically. Restart is required.
          AdminEventMulticaster.notifyFailure(event, AdminEventResult.RESTART_NEEDED);
        }

        /*
        //This feature is currently dropped as it's not implemented totally
        else if (next.equals("commit-retries")) {
                          String oldCommitRetries = configUpdate.getOldValue("commit-retries");
                          String newCommitRetries = configUpdate.getNewValue("commit-retries");
                          if (oldCommitRetries.equals(newCommitRetries)) {
                          }
                          else {
                              Configuration.setCommitRetryVar(newCommitRetries);
                          }
                      } // commit-retries
                      */

      }
    }
  }
}
/**
 * Implements the reload callbacks for standalone web modules.
 *
 * <p>When dynamic reloading is enabled, this object adds the list of enabled standalone web modules
 * to the reload monitor thread, so that web module reload via 'touch .reload' works.
 *
 * <p>This class lives in the com.sun.enterprise.server package and not the com.sun.enterprise.web
 * package because of the scope of the interface/methods in - ReloadMonitor, MonitorableEntry and
 * MonitorListener.
 */
public final class StandaloneWebModulesManager implements MonitorListener {

  ReloadMonitor reloadMonitor;

  // ------------------------------------------------------------ Constructor

  /**
   * Standard constructor.
   *
   * @param id The web container object identifier
   * @param modulesRoot The top level directory under which all standalone modules are deployed at.
   * @param pollInterval The interval at which dynamic reloading is performed
   */
  public StandaloneWebModulesManager(String id, String modulesRoot, long pollInterval) {
    _id = id;
    _modulesRoot = modulesRoot;
    start(pollInterval);
  }

  // ----------------------------------------------------- Instance Variables

  /**
   * The id of this object (this is the same as that of the id of the associated web container
   * object).
   */
  private String _id = null;

  /**
   * Absolute path for location where all the deployed standalone modules are stored for this Server
   * Instance.
   */
  private String _modulesRoot = null;

  /** List of web module ids registered with the reload monitor thread. */
  private ArrayList _reloadables = new ArrayList();

  // --------------------------------------------------------- Public Methods

  /**
   * Enable dynamic reloading (via the .reload file) for all the standalone web-modules that are
   * marked as enabled
   *
   * <p>This method is invoked be WebContainer.start() only when dynamic reloading has been enabled
   * in server.xml.
   */
  public void start(long pollInterval) {

    reloadMonitor = ReloadMonitor.getInstance(pollInterval * 1000);
  }

  /**
   * Remove the modules (that were previously registered by start()) from the reload monitor thread.
   *
   * <p>This method is invoked be WebContainer.stop() only when dynamic reloading has been enabled
   * in server.xml.
   */
  public void stop() {
    ReloadMonitor reloadMonitor = ReloadMonitor.getInstance(1);
    for (int i = 0; i < _reloadables.size(); i++) {
      String id = (String) _reloadables.get(i);
      reloadMonitor.removeMonitoredEntry(id);
    }
    _reloadables.clear();
    _reloadables = null;
  }

  // ------------------------------------------------ MonitorListener Methods

  /**
   * Callback from the reload monitor thread for a web module.
   *
   * <p>This is done when the user updates the $MODULE_ROOT/$MODULE/.reload file indicating the
   * server runtime for a dynamic reload.
   *
   * @param entry entry thats being monitored
   * @return true if application was reloaded successfully
   */
  public boolean reload(MonitorableEntry entry) {
    // The actual reload is done by the NSAPI reconfiguration logic which
    // the reload monitor thread invokes (at the end), so simply return
    // true here.

    InstanceEnvironment ienv = ApplicationServer.getServerContext().getInstanceEnvironment();

    // 4926513 work-around --- use displayname
    // for "foo", the id will be "foo[0]"
    // String moduleName = entry.getId();
    String moduleName = entry.getDisplayName();
    boolean status = false;

    try {
      DeploymentRequest req =
          new DeploymentRequest(ienv, DeployableObjectType.WEB, DeploymentCommand.DEPLOY);

      // monitored file points to $APP_ROOT/.reload
      req.setFileSource(entry.getMonitoredFile().getParentFile());

      // application registration name
      req.setName(moduleName);

      // we are always trying a redeployment
      req.setForced(true);

      AutoDirReDeployer deployer = new AutoDirReDeployer(req);
      status = deployer.redeploy();

    } catch (IASDeploymentException de) {
      _logger.log(Level.WARNING, "core.error_in_reload_war_module", de);
      return false;
    }
    return status;
  }

  /**
   * Callback from the auto deploy monitor when a new archive is detected.
   *
   * @param entry entry thats being monitored
   * @param archive newly detected archive under the auto deploy directory
   * @return true if archive was deployed successfully
   */
  public boolean deploy(MonitorableEntry entry, File archive) {
    // auto-deploy has not been implemented in S1AS7
    return false;
  }

  /**
   * Adds the given WebModule to the list of monitorable entries for dynamic reloading.
   *
   * @param wm The WebModule to add to the list of monitorable entries for dynamic reloading
   */
  public void addWebModule(WebModule wm) {
    if (wm != null && isEnabled(wm.getConfigContext(), wm.getName())) {
      String name = wm.getName();
      String id = name + "[" + _id + "]";
      String fileName = getReloadFilename(wm);
      MonitorableEntry entry = new MonitorableEntry(id, name, new File(fileName), this);
      _reloadables.add(id);
      reloadMonitor.addMonitorableEntry(entry);
    }
  }

  /**
   * Whether or not a component (either an application or a module) should be enabled is defined by
   * the "enable" attribute on both the application/module element and the application-ref element.
   *
   * @param config The dynamic ConfigContext
   * @param moduleName The name of the component
   * @return boolean
   */
  protected boolean isEnabled(ConfigContext config, String moduleName) {
    try {
      if (config == null) {
        config = AdminService.getAdminService().getAdminContext().getAdminConfigContext();
      }
      ConfigBean app = ApplicationHelper.findApplication(config, moduleName);
      Server server = ServerBeansFactory.getServerBean(config);
      ApplicationRef appRef = server.getApplicationRefByRef(moduleName);

      return ((app != null && app.isEnabled()) && (appRef != null && appRef.isEnabled()));
    } catch (ConfigException e) {
      _logger.log(Level.FINE, "Error in finding " + moduleName, e);

      // If there is anything wrong, do not enable the module
      return false;
    }
  }

  /**
   * Adds the given WebModule instances to the list of monitorable entries for dynamic reloading.
   *
   * @param modules The array of WebModule instances to add to the list of monitorable entries for
   *     dynamic reloading
   */
  public void addWebModules(WebModule[] modules) {
    if (modules != null && modules.length > 0) {
      for (int i = 0; i < modules.length; i++) {
        addWebModule(modules[i]);
      }
    }
  }

  /** Returns the absolute pathname to the .reload file in the specified web module's directory. */
  private String getReloadFilename(WebModule wm) {
    String path = wm.getLocation();
    File dir = new File(path);
    if (!dir.isAbsolute()) path = _modulesRoot + "/" + path;
    return path + "/" + ReloadMonitor.RELOAD_FILE;
  }

  /** logger to log core messages */
  static Logger _logger = LogDomains.getLogger(LogDomains.CORE_LOGGER);

  /** local string manager */
  private static StringManager localStrings =
      StringManager.getManager(StandAloneEJBModulesManager.class);
}