Package com.esri.gpt.framework.context

Source Code of com.esri.gpt.framework.context.ApplicationConfigurationLoader

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.lucene.search.BooleanQuery;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.esri.gpt.catalog.arcims.ImsService;
import com.esri.gpt.catalog.context.CatalogConfiguration;
import com.esri.gpt.catalog.lucene.LuceneIndexObserver;
import com.esri.gpt.catalog.lucene.LuceneIndexObserverInfo;
import com.esri.gpt.catalog.lucene.ParserAdaptorInfo;
import com.esri.gpt.catalog.lucene.ParserAdaptorInfos;
import com.esri.gpt.catalog.search.MapViewerConfigs;
import com.esri.gpt.catalog.search.SearchConfig;
import com.esri.gpt.control.download.DownloadConfiguration;
import com.esri.gpt.control.download.ItemInfo;
import com.esri.gpt.control.georss.DcatField;
import com.esri.gpt.control.georss.DcatFields;
import com.esri.gpt.control.georss.DcatSchemas;
import com.esri.gpt.control.webharvest.engine.DataProcessorFactory;
import com.esri.gpt.control.webharvest.engine.HarvesterConfiguration;
import com.esri.gpt.control.webharvest.engine.LocalDataProcessorFactory;
import com.esri.gpt.control.webharvest.protocol.ProtocolFactories;
import com.esri.gpt.control.webharvest.protocol.ProtocolFactory;
import com.esri.gpt.control.webharvest.protocol.ProtocolInitializer;
import com.esri.gpt.control.webharvest.validator.IValidatorFactory;
import com.esri.gpt.control.webharvest.validator.ValidatorFactory;
import com.esri.gpt.framework.collection.StringAttribute;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.http.HttpClientRequest;
import com.esri.gpt.framework.mail.MailConfiguration;
import com.esri.gpt.framework.scheduler.ThreadSchedulerConfiguration;
import com.esri.gpt.framework.security.codec.PC1_Encryptor;
import com.esri.gpt.framework.security.credentials.ProxyAuthenticator;
import com.esri.gpt.framework.security.credentials.UsernamePasswordCredentials;
import com.esri.gpt.framework.security.identity.IdentityConfiguration;
import com.esri.gpt.framework.security.identity.IdentitySupport;
import com.esri.gpt.framework.security.identity.SingleSignOnMechanism;
import com.esri.gpt.framework.security.identity.ldap.LdapConfiguration;
import com.esri.gpt.framework.security.identity.ldap.LdapConnectionProperties;
import com.esri.gpt.framework.security.identity.ldap.LdapGroupProperties;
import com.esri.gpt.framework.security.identity.ldap.LdapUserProperties;
import com.esri.gpt.framework.security.identity.open.OpenProvider;
import com.esri.gpt.framework.security.metadata.MetadataAccessPolicy;
import com.esri.gpt.framework.security.principal.Group;
import com.esri.gpt.framework.security.principal.Role;
import com.esri.gpt.framework.security.principal.Roles;
import com.esri.gpt.framework.security.principal.UserAttribute;
import com.esri.gpt.framework.security.principal.UserAttributeMap;
import com.esri.gpt.framework.sql.DatabaseReference;
import com.esri.gpt.framework.util.LogUtil;
import com.esri.gpt.framework.util.TimePeriod;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.framework.xml.DomUtil;
import com.esri.gpt.framework.xml.NodeListAdapter;

/**
* Application configuration loader.
* <p>
* Loads the primary configuration for an application based upon the XML content
* defined by the primary configuration source.
*
* @see ApplicationConfiguration
*/
public class ApplicationConfigurationLoader {

 
/** Main XML configuration file location. */
private static final String MAIN_FILE = "gpt/config/gpt.xml";

private static final String MAIN_FILE_DEV = "gpt/config/gpt_dev.xml";

/** Default constructor. */
public ApplicationConfigurationLoader() {
}

// properties ==================================================================
/**
* Gets the logger.
*
* @return the logger
*/
private Logger getLogger() {
  return LogUtil.getLogger();
}

// methods =====================================================================
/**
* Starts the configuration loading process.
*
* @param appConfig
*          the primary application configuration
* @throws Exception
*/
public void load(ApplicationConfiguration appConfig) throws Exception {

  // load the dom
  String sConfigFile = null;
  Document dom = null;
  try {
    sConfigFile = MAIN_FILE_DEV;
    dom = DomUtil.makeDomFromResourcePath(sConfigFile, false);
    getLogger().log(Level.FINE, "Loaded configuration file: {0}", sConfigFile);
  } catch (Throwable e) {
    // Dev config not found
  }
  if (dom == null) {
    sConfigFile = MAIN_FILE;
    getLogger().log(Level.FINE, "Loading configuration file: {0}", sConfigFile);
    dom = DomUtil.makeDomFromResourcePath(sConfigFile, false);
  }
  XPath xpath = XPathFactory.newInstance().newXPath();


  try {
    Node root = (Node) xpath.evaluate("/gptConfig", dom, XPathConstants.NODE);
    appConfig.setVersion(xpath.evaluate("@version", root));

    // load configurations
    loadDatabase(appConfig, dom, root);
    loadIdentity(appConfig, dom, root);
    loadMail(appConfig, dom, root);
    loadInteractiveMap(appConfig, dom, root);
    loadCatalog(appConfig, dom, root);
    loadScheduler(appConfig, dom, root);
    loadDownloadData(appConfig, dom, root);
    loadHarvesterConfiguration(appConfig, dom, root);
    loadProtocolFactories(appConfig, dom, root);

    // forward proxy authentication
    Node ndProxyAuth = (Node) xpath.evaluate("forwardProxyAuth", root, XPathConstants.NODE);
    if (ndProxyAuth != null) {
      String sUser = xpath.evaluate("@username", ndProxyAuth);
      String sPwd = xpath.evaluate("@password", ndProxyAuth);
      boolean bEncrypted = Val.chkBool(xpath.evaluate("@encrypted", ndProxyAuth), false);
      boolean bSetSystemProperties = Val.chkBool(xpath.evaluate("@setSystemProperties", ndProxyAuth), true);
      if (bEncrypted) {
        try {
          String sDecrypted = PC1_Encryptor.decrypt(sPwd);
          sPwd = sDecrypted;
        } catch (Exception e) {
          this.getLogger().log(Level.SEVERE, "The forwardProxyAuth password failed to decrypt.", e);
        }
      }
      if ((sUser != null) && (sUser.length() > 0) && (sPwd != null) && (sPwd.length() > 0)) {
        ProxyAuthenticator.setDefault(sUser, sPwd);

        // set system properties
        if (bSetSystemProperties) {
          try {
            if (System.getProperty("http.proxyUser") == null) {
              System.setProperty("http.proxyUser", sUser);
              System.setProperty("http.proxyPassword", sPwd);
            }
            if (System.getProperty("https.proxyUser") == null) {
              System.setProperty("https.proxyUser", sUser);
              System.setProperty("https.proxyPassword", sPwd);
            }
          } catch (Exception e) {
            this.getLogger().log(Level.SEVERE, "Error setting system properties for forward proxy authentication.", e);
          }
        }
      }
    }

  } catch (XPathExpressionException e) {
    e.printStackTrace(System.err);
  }

  StringAttributeMap params = appConfig.getCatalogConfiguration().getParameters();
  String param = Val.chkStr(params.getValue("catalog.echoConfigOnStartup"));
  boolean bEchoConfig = !param.equalsIgnoreCase("false");
  if (bEchoConfig) {
    getLogger().info(appConfig.toString());
  }
}

/**
* Loads the catalog configuration.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws Exception
*/
private void loadCatalog(ApplicationConfiguration appConfig, Document dom,
    Node root) throws Exception {
  XPath xpath = XPathFactory.newInstance().newXPath();

  // catalog configuration
  Node ndCat = (Node) xpath.evaluate("catalog", root, XPathConstants.NODE);
  if (ndCat != null) {
    CatalogConfiguration cfg = appConfig.getCatalogConfiguration();
    cfg.getParameters().clear();
    ImsService publish = cfg.getArcImsCatalog().getPublishService();
    ImsService browse = cfg.getArcImsCatalog().getBrowseService();
    cfg.setTablePrefix(Val.chkStr(xpath.evaluate("@gptTablePrefix", ndCat),"GPT_"));
    cfg.setMvsTablePrefix(Val.chkStr(xpath.evaluate("@mvsTablePrefix", ndCat),"MVS_"));

    publish.setServerUrl(xpath.evaluate("@metadataServerUrl", ndCat));
    publish.setServiceName(Val.chkStr(xpath.evaluate("@metadataServerPublishService",ndCat), "GPT_Publish_Metadata"));
    publish.setTimeoutMillisecs(Val.chkInt(xpath.evaluate("@metadataServerTimeoutMillisecs", ndCat), 0));

    browse.setServerUrl(publish.getServerUrl());
    browse.setServiceName(Val.chkStr(xpath.evaluate("@metadataServerBrowseService", ndCat),"GPT_Browse_Metadata"));
    browse.setTimeoutMillisecs(publish.getTimeoutMillisecs());

    // additional parameters
    populateParameters(cfg.getParameters(), ndCat);
   
    //load dcat fields
    if(cfg.getParameters().containsKey("dcat.mappings")){
      loadDcatMappings(cfg.getDcatSchemas(),cfg.getParameters().get("dcat.mappings").getValue());
    }
   
    // parse http timeouts
    String connectionTimeout = cfg.getParameters().getValue("httpClientRequest.connectionTimeout");
    String responseTimeout   = cfg.getParameters().getValue("httpClientRequest.responseTimeout");
   
    // set http timeouts
    cfg.setConnectionTimeMs((int)parsePeriod(connectionTimeout, HttpClientRequest.DEFAULT_CONNECTION_TIMEOUT).getValue());
    cfg.setResponseTimeOutMs((int)parsePeriod(responseTimeout , HttpClientRequest.DEFAULT_RESPONSE_TIMEOUT).getValue());
  }

  // search configuration
  Node ndSearch = (Node) xpath.evaluate("catalog/search", root,
      XPathConstants.NODE);
  SearchConfig sCfg = appConfig.getCatalogConfiguration().getSearchConfig();
  sCfg.setSearchConfigNode(ndSearch);
  if (ndSearch != null) {
    sCfg.setResultsReviewsShown(
        Val.chkStr(xpath.evaluate("@searchResultsReviewsShown", ndSearch)));
    sCfg.setResultsPerPage(xpath.evaluate("@searchResultsPerPage", ndSearch));
    sCfg.setMaxSavedSearches(xpath.evaluate("@maxSavedSearches", ndSearch));
    sCfg.setCswProfile(
        Val.chkStr(xpath.evaluate("@cswServletUrlProfile", ndSearch),"urn:ogc:CSW:2.0.2:HTTP:OGCCORE:ESRI:GPT"));
    sCfg.setSearchUri(xpath.evaluate("@cswServletUrl", ndSearch));
    sCfg.setTimeOut(xpath.evaluate("@searchTimeoutMillisecs", ndSearch));
    sCfg.setDistributedSearchMaxSelectedSites(
        Val.chkStr(xpath.evaluate("@distributedSearchMaxSelectedSites",
            ndSearch)));
    sCfg.setDistributedSearchTimeoutMillisecs(
        Val.chkStr(xpath.evaluate("@distributedSearchTimeoutMillisecs",
            ndSearch)));
       
    sCfg.setAllowExternalSearch(Val.chkBool(xpath.evaluate(
        "@allowExternalSiteSearch", ndSearch), false));
    sCfg.setAllowTemporalSearch(Val.chkBool(xpath.evaluate("@allowTemporalSearch",ndSearch),false));
    sCfg.setJsfSuffix(Val.chkStr(xpath.evaluate(
        "@jsfSuffix", ndSearch)));
    sCfg.setGptToCswXsltPath(xpath.evaluate("@gpt2cswXslt", ndSearch));
    sCfg.setMapViewerUrl(Val.chkStr(xpath.evaluate("@mapViewerUrl", ndSearch),""));
    sCfg.validate();
  }


  NodeList nodes = (NodeList) xpath.evaluate(
      "catalog/search/repositories/repository",
      root, XPathConstants.NODESET);
  NodeList nodeList = nodes;
  LinkedHashMap<String, Map<String, String>> sFactory =
      new LinkedHashMap<String, Map<String, String>>();
  Map<String, String> attributes =
      new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
  /*attributes.put("key", "local");
  attributes.put("class", "com.esri.gpt.catalog.search.SearchEngineLocal");
  attributes.put("resourceKey", "catalog.search.searchSite.defaultsite");
  attributes.put("labelResourceKey", "catalog.search.searchSite.defaultsite");
  attributes.put("abstractResourceKey", "catalog.search.searchSite.defaultsite.abstract");
  sFactory.put("local", attributes);*/
  for (int i = 0; nodeList != null && i < nodeList.getLength(); i++) {
    ndSearch = nodeList.item(i);
    attributes =
        new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
    NamedNodeMap nnm = ndSearch.getAttributes();
    for (int j = 0; nnm != null && j < nnm.getLength(); j++) {
      Node nd = nnm.item(j);
      String key = Val.chkStr(nd.getNodeName());
      String value = Val.chkStr(nd.getNodeValue());
      attributes.put(key, value);
      if (key.equalsIgnoreCase("RESOURCEKEY")) {
        attributes.put("RESOURCEKEY", value);
      }
      if (key.equalsIgnoreCase("labelResourceKey")) {
        attributes.put("labelResourceKey", value);
      }
      if (key.equalsIgnoreCase("abstractResourceKey")) {
        attributes.put("abstractResourceKey", value);
      }
    }
    NodeList params = (NodeList) xpath.evaluate("parameter",
        ndSearch, XPathConstants.NODESET);
    for (int k = 0; params != null && k < params.getLength(); k++) {
      String key = xpath.evaluate("@key", params.item(k));
      String value = xpath.evaluate("@value", params.item(k));
      attributes.put(Val.chkStr(key), Val.chkStr(value));
    }

    String key = Val.chkStr(xpath.evaluate("@key", ndSearch));
    sFactory.put(key, attributes);

  }
  sCfg.setSearchFactoryRepos(sFactory);

  // Mapviewer
  ArrayList<MapViewerConfigs> mapViewerConfigs =
      new ArrayList<MapViewerConfigs>();
  nodes = (NodeList) xpath.evaluate("catalog/mapViewer/instance", root,
      XPathConstants.NODESET);
  for (int j = 0; nodes != null && j < nodes.getLength(); j++) {
    MapViewerConfigs mvConfigs = new MapViewerConfigs();
    Node nd = nodes.item(j);
    mvConfigs.setClassName(Val.chkStr(xpath.evaluate("@className", nd),"com.esri.gpt.catalog.search.MapViewerFlex"));
    mvConfigs.setUrl(xpath.evaluate("@url", nd));
    NodeList pNodeList = (NodeList) xpath.evaluate("parameter", nd, XPathConstants.NODESET);
    for (int k = 0; pNodeList != null && k < pNodeList.getLength(); k++) {
      String key = xpath.evaluate("@key", pNodeList.item(k));
      String value = xpath.evaluate("@value", pNodeList.item(k));
      if (key != null || value != null) {
        mvConfigs.addParameter(key, value);
      }
    }
    mapViewerConfigs.add(mvConfigs);

  }
  sCfg.setMapViewerInstances(mapViewerConfigs);

  // Lucene configuration
  Node ndLucene = (Node) xpath.evaluate("catalog/lucene", root, XPathConstants.NODE);
  if (ndLucene != null) {
    CatalogConfiguration cfg = appConfig.getCatalogConfiguration();
    cfg.getLuceneConfig().setIndexLocation(
        xpath.evaluate("@indexLocation", ndLucene));
    cfg.getLuceneConfig().setWriteLockTimeout(
        Val.chkInt(xpath.evaluate("@writeLockTimeout", ndLucene), -1));
    cfg.getLuceneConfig().setUseNativeFSLockFactory(
        Val.chkStr(xpath.evaluate("@useNativeFSLockFactory", ndLucene)).equalsIgnoreCase("true"));
    cfg.getLuceneConfig().setAnalyzerClassName(
        xpath.evaluate("@analyzerClassName", ndLucene));
    cfg.getLuceneConfig().setUseConstantScoreQuery(
        Val.chkBool(xpath.evaluate("@useConstantScoreQuery", ndLucene), false));
    cfg.getLuceneConfig().setMaxClauseCount(
        Val.chkInt(xpath.evaluate("@maxClauseCount", ndLucene), BooleanQuery.getMaxClauseCount()));

    ParserAdaptorInfos infos = new ParserAdaptorInfos();
    NodeList ndLstProxies = (NodeList) xpath.evaluate("adaptor", ndLucene,
        XPathConstants.NODESET);
    for (int i = 0; i < ndLstProxies.getLength(); i++) {
      Node ndProxy = ndLstProxies.item(i);
      String proxyName = xpath.evaluate("@name", ndProxy);
      String proxyClassName = xpath.evaluate("@className", ndProxy);

      ParserAdaptorInfo info = new ParserAdaptorInfo();
      info.setName(proxyName);
      info.setClassName(proxyClassName);

      NodeList ndListProps = (NodeList) xpath.evaluate("attribute", ndProxy,
          XPathConstants.NODESET);
      for (int p = 0; p < ndListProps.getLength(); p++) {
        Node ndProp = ndListProps.item(p);
        String key = xpath.evaluate("@key", ndProp);
        String value = xpath.evaluate("@value", ndProp);
        info.getAttributes().set(key, value);
      }

      infos.add(info);
    }

    cfg.getLuceneConfig().setParserProxies(infos.createParserProxies());
   
    NodeList ndObservers = (NodeList) xpath.evaluate("observer", ndLucene, XPathConstants.NODESET);
    for (Node ndObserver: new NodeListAdapter(ndObservers)) {
      LuceneIndexObserverInfo info = new LuceneIndexObserverInfo();
      info.setClassName(Val.chkStr(xpath.evaluate("@className", ndObserver)));
      NodeList ndListProps = (NodeList) xpath.evaluate("attribute", ndObserver, XPathConstants.NODESET);
      for (Node ndAttribute: new NodeListAdapter(ndListProps)) {
        String key = xpath.evaluate("@key", ndAttribute);
        String value = xpath.evaluate("@value", ndAttribute);
        info.getAttributes().set(key, value);
      }
      LuceneIndexObserver observer = info.createObserver();
      if (observer!=null) {
        cfg.getLuceneConfig().getObservers().add(observer);
      }
    }
   
  }

  loadMetadataAccessPolicyConfiguration(appConfig, root);

  StringAttributeMap params = appConfig.getCatalogConfiguration().getParameters();
  String param = Val.chkStr(params.getValue("catalog.loadSchemasOnStartup"));
  boolean bLoadSchemas = param.equalsIgnoreCase("true");
  if (bLoadSchemas) {
    appConfig.getCatalogConfiguration().getConfiguredSchemas();
  }
}

/**
* Load configured dcat mappings
* @param dcatSchemas the configured dcat schemas
* @param dcatMappings the path to dcat mapping file
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
private void loadDcatMappings(DcatSchemas dcatSchemas, String dcatMappings) throws Exception {
  getLogger().log(Level.FINE, "Loading dcat mapping file: {0}", dcatMappings);
  Document dom = DomUtil.makeDomFromResourcePath(dcatMappings, false);
  XPath xpath = XPathFactory.newInstance().newXPath();
  Node dcat = (Node) xpath.evaluate("/dcat", dom, XPathConstants.NODE);
  NodeList fields = (NodeList) xpath.evaluate("fields", dcat, XPathConstants.NODESET);
  if(fields != null){   
    for (int j = 0; j < fields.getLength(); j++) {   
      Node fld = fields.item(j);
      DcatFields dcatFields = new DcatFields();
      String schema = xpath.evaluate("@schema", fld);
      NodeList flds = (NodeList) xpath.evaluate("field", fld, XPathConstants.NODESET);
      for (int i = 0; i < flds.getLength(); i++) {
        Node field = flds.item(i);
        DcatField df = new DcatField();
        String name = xpath.evaluate("@name", field);
        df.setName(name);
        df.setType(xpath.evaluate("@type", field));
        df.setIndex(xpath.evaluate("@index", field));
        df.setDateFormat(xpath.evaluate("@dateFormat", field));
        String max = Val.chkStr(xpath.evaluate("@maxChars", field));
        String required = Val.chkStr(xpath.evaluate("@required", field));
        if(required.length() > 0){
          df.setRequired(Boolean.parseBoolean(required));
        }
        if(max.length() > 0){
          df.setMaxChars(Integer.parseInt(max));
        }
        df.setDelimiter(xpath.evaluate("@delimiter", field));
        dcatFields.add(df);
      }
      dcatSchemas.put(schema, dcatFields);
    }
  }
}

/**
* Loads the acsess policies.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws Exception
* @throws Exception
*/
private void loadMetadataAccessPolicyConfiguration(
    ApplicationConfiguration appConfig, Node root) throws Exception {
  XPath xpath = XPathFactory.newInstance().newXPath();
  MetadataAccessPolicy aclCfg = appConfig.getMetadataAccessPolicy();
  Node ndPolicy = (Node) xpath.evaluate("catalog/metadataAccessPolicy", root,
      XPathConstants.NODE);
  if (ndPolicy != null) {
    String type = xpath.evaluate("@type", ndPolicy);
    aclCfg.setAccessPolicyType(type);
    String accessToGroupDN = xpath.evaluate("@protectedGroupDN", ndPolicy);
    if (accessToGroupDN != null && accessToGroupDN.trim().length() > 0) {
      aclCfg.setAccessToGroupDN(accessToGroupDN);
    }
  }
}

/**
* Loads the database references.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void loadDatabase(ApplicationConfiguration appConfig, Document dom,
    Node root) throws XPathExpressionException {
  XPath xpath = XPathFactory.newInstance().newXPath();
  Node ndDb = (Node) xpath.evaluate("databaseReference", root,
      XPathConstants.NODE);
  if (ndDb != null) {
    DatabaseReference dbRef = new DatabaseReference();
    dbRef.setReferenceName(xpath.evaluate("@name", ndDb));
    dbRef.setJndiName(xpath.evaluate("@jndiName", ndDb));
    dbRef.setDirectDriverClassName(xpath.evaluate("@driver", ndDb));
    dbRef.setDirectUrl(xpath.evaluate("@url", ndDb));
    dbRef.setDirectUsername(xpath.evaluate("@username", ndDb));
    dbRef.setDirectPassword(xpath.evaluate("@password", ndDb));
    dbRef.getTags().add("default");
    appConfig.getDatabaseReferences().add(dbRef, true);
  }
}

/**
* Loads the identify configuration.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void loadIdentity(ApplicationConfiguration appConfig, Document dom,
    Node root) throws XPathExpressionException {

  // prepare
  XPath xpath = XPathFactory.newInstance().newXPath();
  IdentityConfiguration idConfig = appConfig.getIdentityConfiguration();
  LdapConfiguration ldapConfig = idConfig.getLdapConfiguration();
  Node ndIdentity = (Node) xpath.evaluate("identity", root, XPathConstants.NODE);
  if (ndIdentity == null) {
    return;
  }

  // primary parameters
  String sName = Val.chkStr(xpath.evaluate("@name", ndIdentity));
  String sRealm = Val.chkStr(xpath.evaluate("@realm", ndIdentity));
  String sEncKey = Val.chkStr(xpath.evaluate("@encKey", ndIdentity));
  String sAdapterClass = Val.chkStr(xpath.evaluate("@adapterClassName", ndIdentity));
  if (sName.length() == 0) {
    sName = "Identity Configuration";
  }
  if (sRealm.length() == 0) {
    sRealm = "Geoportal";
  }
  if (sAdapterClass.length() == 0) {
    sAdapterClass = "com.esri.gpt.framework.security.identity.ldap.LdapIdentityAdapter";
  }
  idConfig.setName(sName);
  idConfig.setRealm(sRealm);
  idConfig.setEncKey(sEncKey);

  // determine the adapter
  Node ndSimple = (Node) xpath.evaluate("simpleAdapter", ndIdentity, XPathConstants.NODE);
  Node ndLdap = (Node) xpath.evaluate("ldapAdapter", ndIdentity, XPathConstants.NODE);
  if (ndSimple != null) {
    ndLdap = null;
    sAdapterClass = "com.esri.gpt.framework.security.identity.local.SimpleIdentityAdapter";
  }
  idConfig.setAdapterClassName(sAdapterClass);

  // simple adapter configuration
  if (ndSimple != null) {

    // account
    Node ndAccount = (Node) xpath.evaluate("account", ndSimple, XPathConstants.NODE);
    if (ndAccount != null) {
      String sUser = xpath.evaluate("@username", ndAccount);
      String sPwd = xpath.evaluate("@password", ndAccount);
      String sDN = "cn=" + sUser + ",ou=simpleadapter";
      boolean bEncrypted = Val.chkBool(xpath.evaluate("@encrypted", ndAccount),
          false);
      if (bEncrypted) {
        try {
          String sDecrypted = PC1_Encryptor.decrypt(sPwd);
          sPwd = sDecrypted;
        } catch (Exception e) {
          this.getLogger().log(Level.SEVERE,
              "The simple account password failed to decrypt.", e);
        }
      }
      UsernamePasswordCredentials creds = new UsernamePasswordCredentials( sUser, sPwd);
      creds.setDistinguishedName(sDN);
      idConfig.setCatalogAdminDN(creds.getDistinguishedName());
      idConfig.getSimpleConfiguration().setServiceAccountCredentials(creds);
    }

    // roles
    Node ndRoles = (Node) xpath.evaluate("roles", ndSimple, XPathConstants.NODE);
    if (ndRoles != null) {
      Roles roles = idConfig.getConfiguredRoles();
      NodeList nlRoles = (NodeList) xpath.evaluate("role", ndRoles, XPathConstants.NODESET);
      for (int i = 0; i < nlRoles.getLength(); i++) {
        Node ndRole = nlRoles.item(i);
        Role role = new Role();
        role.setKey(xpath.evaluate("@key", ndRole));
        roles.add(role);
      }
      for (Role role : roles.values()) {
        role.buildFullRoleSet(roles);
      }
    }

  }

  // LDAP adapter configuration
  if (ndLdap != null) {

    // connection properties & service account
    Node ndCon = (Node) xpath.evaluate("ldapConnectionProperties", ndLdap,
        XPathConstants.NODE);
    if (ndCon != null) {
      LdapConnectionProperties props = ldapConfig.getConnectionProperties();
      props.setProviderUrl(xpath.evaluate("@providerURL", ndCon));
      props.setInitialContextFactoryName(xpath.evaluate(
          "@initialContextFactoryName", ndCon));
      props.setSecurityAuthenticationLevel(xpath.evaluate(
          "@securityAuthentication", ndCon));
      props.setSecurityProtocol(xpath.evaluate("@securityProtocol", ndCon));

      Node ndService = (Node) xpath.evaluate("ldapServiceAccount", ndCon, XPathConstants.NODE);
      if (ndService != null) {
        String sUser = xpath.evaluate("@securityPrincipal", ndService);
        String sPwd = xpath.evaluate("@securityCredentials", ndService);
        boolean bEncrypted = Val.chkBool(xpath.evaluate("@encrypted", ndService), false);
        if (bEncrypted) {
          try {
            String sDecrypted = PC1_Encryptor.decrypt(sPwd);
            sPwd = sDecrypted;
          } catch (Exception e) {
            this.getLogger().log(Level.SEVERE, "The securityCredentials failed to decrypt.", e);
          }
        }
        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(sUser, sPwd);
        props.setServiceAccountCredentials(creds);
        idConfig.setCatalogAdminDN(xpath.evaluate("@catalogAdminDN", ndService));
      }
    }

    // single sign-on mechanism
    Node ndSSO = (Node) xpath.evaluate("singleSignOn", ndLdap,
        XPathConstants.NODE);
    if (ndSSO != null) {
      SingleSignOnMechanism sso = idConfig.getSingleSignOnMechanism();
      sso.setActive(Val.chkBool(xpath.evaluate("@active", ndSSO), false));
      sso.setCredentialLocation(xpath.evaluate("@credentialLocation", ndSSO));
      sso.setAnonymousValue(xpath.evaluate("@anonymousValue", ndSSO));
    }

    // self care support
    Node ndSupport = (Node) xpath.evaluate("selfCareSupport", ndLdap,
        XPathConstants.NODE);
    if (ndSupport != null) {
      IdentitySupport support = idConfig.getSupportedFunctions();
      support.setSupportsLogin(Val.chkBool(xpath.evaluate("@supportsLogin",
          ndSupport), true));
      support.setSupportsLogout(Val.chkBool(xpath.evaluate("@supportsLogout",
          ndSupport), true));
      support.setSupportsUserRegistration(Val.chkBool(xpath.evaluate(
          "@supportsUserRegistration", ndSupport), false));
      support.setSupportsUserProfileManagement(Val.chkBool(xpath.evaluate(
          "@supportsUserProfileManagement", ndSupport), false));
      support.setSupportsPasswordChange(Val.chkBool(xpath.evaluate(
          "@supportsPasswordChange", ndSupport), false));
      support.setSupportsPasswordRecovery(Val.chkBool(xpath.evaluate(
          "@supportsPasswordRecovery", ndSupport), false));
    }

    // roles
    Node ndRoles = (Node) xpath.evaluate("roles", ndLdap, XPathConstants.NODE);
    if (ndRoles != null) {
      Roles roles = idConfig.getConfiguredRoles();
      String sRegUserKey = Val.chkStr(xpath.evaluate("@registeredUserRoleKey",
          ndRoles));
      if (sRegUserKey.length() == 0) {
        sRegUserKey = "gptRegisteredUser";
      }
      roles.setAuthenticatedUserRequiresRole(Val.chkBool(xpath.evaluate(
          "@authenticatedUserRequiresRole", ndRoles), true));
      roles.setRegisteredUserRoleKey(sRegUserKey);
                
      NodeList nlRoles = (NodeList) xpath.evaluate("role", ndRoles,
          XPathConstants.NODESET);
      for (int i = 0; i < nlRoles.getLength(); i++) {
        Node ndRole = nlRoles.item(i);
        Role role = new Role();
        role.setKey(xpath.evaluate("@key", ndRole));
        role.setInherits(xpath.evaluate("@inherits", ndRole));
        role.setResKey(xpath.evaluate("@resKey", ndRole));
        role.setManage(Val.chkBool(xpath.evaluate("@manage", ndRole),true));
        role.setForbidden(Val.chkBool(xpath.evaluate("@forbidden", ndRole),false));
        role.setDistinguishedName(xpath.evaluate("@groupDN", ndRole));
        roles.add(role);
      }
      for (Role role : roles.values()) {
        role.buildFullRoleSet(roles);
      }
    }

    // user properties
    Node ndUser = (Node) xpath.evaluate("users", ndLdap, XPathConstants.NODE);
    if (ndUser != null) {
      LdapUserProperties props = ldapConfig.getUserProperties();
      props.setUserDisplayNameAttribute(xpath.evaluate("@displayNameAttribute",
          ndUser));
      props.setPasswordEncryptionAlgorithm(xpath.evaluate(
          "@passwordEncryptionAlgorithm", ndUser));
      props.setUserDNPattern(xpath.evaluate("@newUserDNPattern", ndUser));
      props.setUsernameSearchPattern(xpath.evaluate("@usernameSearchPattern",
          ndUser));
     
      props.setUserRequestsSearchPattern(xpath.evaluate("@newUserRequestSearchPattern",
              ndUser));
     
      props.setUserSearchDIT(xpath.evaluate("@searchDIT", ndUser));
      NodeList nlObj = (NodeList) xpath.evaluate(
          "requiredObjectClasses/objectClass/@name", ndUser,
          XPathConstants.NODESET);
      for (int i = 0; i < nlObj.getLength(); i++) {
        props.addUserObjectClass(nlObj.item(i).getNodeValue());
      }
    }

    // user profile parameters
    UserAttributeMap uaMap = idConfig.getUserAttributeMap();
    NodeList nlUserAttr = (NodeList) xpath.evaluate(
        "users/userAttributeMap/attribute", ndLdap, XPathConstants.NODESET);
    for (int i = 0; i < nlUserAttr.getLength(); i++) {
      UserAttribute attr = new UserAttribute();
      attr.setKey(xpath.evaluate("@key", nlUserAttr.item(i)));
      attr.setLdapName(xpath.evaluate("@ldapName", nlUserAttr.item(i)));

      // TODO: need to do a better check to filter out badly defined
      // parameters
      boolean bIsLdap = (idConfig.getAdapterClassName().indexOf("Ldap") != -1);
      if (bIsLdap && (attr.getLdapName().length() > 0)) {
        uaMap.add(attr);
      }
    }
    ldapConfig.getUserProperties().getUserProfileMapping().configureFromUserAttributes(uaMap);

    // group properties
    Node ndGroup = (Node) xpath.evaluate("groups", ndLdap, XPathConstants.NODE);
    if (ndGroup != null) {
      LdapGroupProperties props = ldapConfig.getGroupProperties();
      props.setGroupDisplayNameAttribute(xpath.evaluate(
          "@displayNameAttribute", ndGroup));
      props.setGroupDynamicMemberAttribute(xpath.evaluate(
          "@dynamicMemberOfGroupsAttribute", ndGroup));
      props.setGroupDynamicMembersAttribute(xpath.evaluate(
          "@dynamicMembersAttribute", ndGroup));
      props.setGroupMemberAttribute(xpath.evaluate("@memberAttribute", ndGroup));
      props.setGroupMemberSearchPattern(xpath.evaluate("@memberSearchPattern",
          ndGroup));
      props.setGroupNameSearchPattern(xpath.evaluate("@nameSearchPattern",
          ndGroup));
      props.setGroupSearchDIT(xpath.evaluate("@searchDIT", ndGroup));
    }

    // metadata management groups
    NodeList nlMmg = (NodeList) xpath.evaluate("groups/metadataManagementGroup",ndLdap,XPathConstants.NODESET);
    for (int i = 0; i < nlMmg.getLength(); i++) {
      Node ndMmg = nlMmg.item(i);
      Group group = new Group();
      group.setDistinguishedName(xpath.evaluate("@groupDN", ndMmg));
      group.setKey(group.getDistinguishedName());
      group.setName(xpath.evaluate("@name", ndMmg));
      idConfig.getMetadataManagementGroups().add(group);
    }

  }
 
  // open providers
  NodeList nlOpenProviders = (NodeList)xpath.evaluate("openProviders/openProvider",ndIdentity,XPathConstants.NODESET);
  for (int i=0; i<nlOpenProviders.getLength(); i++) {
    try {
      OpenProvider op = new OpenProvider();
      op.processConfgurationNode(idConfig.getOpenProviders(),nlOpenProviders.item(i));
    } catch (Exception e) {
      this.getLogger().log(Level.SEVERE,"Error while configuring openProvider.",e);
    }
  }
}

/**
* Loads the interactive map configuration.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void loadInteractiveMap(ApplicationConfiguration appConfig,
    Document dom, Node root) throws XPathExpressionException {
  XPath xpath = XPathFactory.newInstance().newXPath();
  appConfig.getInteractiveMap().setJsapiUrl(
      xpath.evaluate("interactiveMap/@jsapiUrl", root));
  appConfig.getInteractiveMap().setMapServiceUrl(
      xpath.evaluate("interactiveMap/@mapServiceUrl", root));
  appConfig.getInteractiveMap().setMapServiceType(
      xpath.evaluate("interactiveMap/@mapServiceType", root));
  appConfig.getInteractiveMap().setGeometryServiceUrl(
      xpath.evaluate("interactiveMap/@geometryServiceUrl", root));
  appConfig.getInteractiveMap().setLocatorUrl(
      xpath.evaluate("interactiveMap/@locatorUrl", root));
  appConfig.getInteractiveMap().setLocatorSingleFieldParameter(
      xpath.evaluate("interactiveMap/@locatorSingleFieldParameter", root));
  appConfig.getInteractiveMap().setMapVisibleLayers(
      xpath.evaluate("interactiveMap/@mapVisibleLayers", root));
  appConfig.getInteractiveMap().setMapInitialExtent(
      xpath.evaluate("interactiveMap/@mapInitialExtent", root));
}

/**
* Loads the mail configuration.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void loadMail(ApplicationConfiguration appConfig, Document dom,
    Node root) throws XPathExpressionException {
  XPath xpath = XPathFactory.newInstance().newXPath();
  MailConfiguration mcfg = appConfig.getMailConfiguration();
  mcfg.put(
      xpath.evaluate("mail/@smtpHost", root),
      xpath.evaluate("mail/@smtpPort", root),
      xpath.evaluate("mail/@siteEmailAddress", root),
      xpath.evaluate("mail/@siteEmailAddress", root));
  mcfg.setEmailAddressRegexp(xpath.evaluate("mail/@emailAddressRegexp", root));

  Node ndAuth = (Node) xpath.evaluate("mail/smtpAuth", root, XPathConstants.NODE);
  if (ndAuth != null) {
    String sUser = Val.chkStr(xpath.evaluate("@username", ndAuth));
    String sPwd = xpath.evaluate("@password", ndAuth);
    boolean bEncrypted = Val.chkBool(xpath.evaluate("@encrypted", ndAuth), false);
    if (bEncrypted) {
      try {
        String sDecrypted = PC1_Encryptor.decrypt(sPwd);
        sPwd = sDecrypted;
      } catch (Exception e) {
        this.getLogger().log(Level.SEVERE, "The smptAuth password failed to decrypt.", e);
      }
    }
    if ((sUser != null) && (sUser.length() > 0) && (sPwd != null) && (sPwd.length() > 0)) {
      mcfg.setPasswordAuthentication(new javax.mail.PasswordAuthentication(sUser, sPwd));
    }
  }
}

/**
* Loads the scheduler configuration.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void loadScheduler(ApplicationConfiguration appConfig, Document dom,
    Node root) throws XPathExpressionException {

  XPath xpath = XPathFactory.newInstance().newXPath();
  ThreadSchedulerConfiguration tsConfig = appConfig.getThreadSchedulerConfiguration();
  Node ndScheduler = (Node) xpath.evaluate("scheduler", root,
      XPathConstants.NODE);
  if (ndScheduler == null) {
    return;
  }

  // primary parameters
  tsConfig.setActive(Val.chkBool(xpath.evaluate("@active", ndScheduler), false));
  tsConfig.setCorePoolSize(Val.chkInt(xpath.evaluate("@corePoolSize",
      ndScheduler), 0));

  // threads
  NodeList nlThreads = (NodeList) xpath.evaluate("thread", ndScheduler,
      XPathConstants.NODESET);
  for (int i = 0; i < nlThreads.getLength(); i++) {
    Node ndThread = nlThreads.item(i);
    String sClass = Val.chkStr(xpath.evaluate("@class", ndThread));
    String sDelay = Val.chkStr(xpath.evaluate("@delay", ndThread));
    String sPeriod = Val.chkStr(xpath.evaluate("@period", ndThread));
    String sAt = Val.chkStr(xpath.evaluate("@at", ndThread));

    // read parameters
    StringAttributeMap parameters = new StringAttributeMap();
    populateParameters(parameters, ndThread);

    // add definition
    tsConfig.addDefinition(sClass, sDelay, sPeriod, sAt, parameters);
  }
}

/**
* Loads the download data configuration.
*
* @param appConfig
*          the primary application configuration
* @param dom
*          the configuration document
* @param root
*          the root node for the document
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void loadDownloadData(ApplicationConfiguration appConfig, Document dom,
    Node root) throws XPathExpressionException {

  // download configuration
  XPath xpath = XPathFactory.newInstance().newXPath();
  Node ndDownload = (Node) xpath.evaluate("downloadData", root,
      XPathConstants.NODE);
  if (ndDownload != null) {
    DownloadConfiguration cfg = appConfig.getDownloadDataConfiguration();
    cfg.setTaskUrl(xpath.evaluate("@taskUrl", ndDownload));
    cfg.setMapServiceUrl(xpath.evaluate("@mapServiceUrl", ndDownload));
    cfg.setMapServiceType(xpath.evaluate("@mapServiceType", ndDownload));
    cfg.setMapInitialExtent(xpath.evaluate("@mapInitialExtent", ndDownload));

    // load projections
    NodeList ndProjections = (NodeList) xpath.evaluate(
        "projections/projection", ndDownload, XPathConstants.NODESET);
    for (int i = 0; i < ndProjections.getLength(); i++) {
      Node node = ndProjections.item(i);
      String key = xpath.evaluate("@key", node);
      String alias = xpath.evaluate("@alias", node);
      String resKey = xpath.evaluate("@resKey", node);
      ItemInfo ii = new ItemInfo(key, alias, resKey);
      cfg.getProjectionInfo().add(ii);
    }

    // load output format
    NodeList ndFormats = (NodeList) xpath.evaluate("formats/format",
        ndDownload, XPathConstants.NODESET);
    for (int i = 0; i < ndFormats.getLength(); i++) {
      Node node = ndFormats.item(i);
      String key = xpath.evaluate("@key", node);
      String alias = xpath.evaluate("@alias", node);
      String resKey = xpath.evaluate("@resKey", node);
      ItemInfo ii = new ItemInfo(key, alias, resKey);
      cfg.getOutputFormatInfo().add(ii);
    }

    // load feature formats
    NodeList ndFeatureFormats = (NodeList) xpath.evaluate("features/feature",
        ndDownload, XPathConstants.NODESET);
    for (int i = 0; i < ndFeatureFormats.getLength(); i++) {
      Node node = ndFeatureFormats.item(i);
      String key = xpath.evaluate("@key", node);
      String alias = xpath.evaluate("@alias", node);
      String resKey = xpath.evaluate("@resKey", node);
      ItemInfo ii = new ItemInfo(key, alias, resKey);
      cfg.getFeatureFormatInfo().add(ii);
    }

    // load raster formats
    NodeList ndRasterFormats = (NodeList) xpath.evaluate("rasters/raster",
        ndDownload, XPathConstants.NODESET);
    for (int i = 0; i < ndRasterFormats.getLength(); i++) {
      Node node = ndRasterFormats.item(i);
      String key = xpath.evaluate("@key", node);
      String alias = xpath.evaluate("@alias", node);
      String resKey = xpath.evaluate("@resKey", node);
      ItemInfo ii = new ItemInfo(key, alias, resKey);
      cfg.getRasterFormatInfo().add(ii);
    }
  }
}

/**
* Loads harvester configuration.
* @param appConfig application configuration
*/
private void loadHarvesterConfiguration(ApplicationConfiguration appConfig, Document dom, Node root) throws XPathExpressionException {
  StringAttributeMap parameters = appConfig.getCatalogConfiguration().getParameters();
  HarvesterConfiguration cfg = appConfig.getHarvesterConfiguration();

  String active = Val.chkStr(parameters.getValue("webharvester.active"));
  String suspended = Val.chkStr(parameters.getValue("webharvester.suspended"));
  String queueEnabled = Val.chkStr(parameters.getValue("webharvester.queueEnabled"));
  String poolsize = Val.chkStr(parameters.getValue("webharvester.poolSize"));
  String autoselectfrequency = Val.chkStr(parameters.getValue("webharvester.autoSelectFrequency"));
  String watchdogfrequency = Val.chkStr(parameters.getValue("webharvester.watchDogFrequency"));
  String basecontextpath = Val.chkStr(parameters.getValue("webharvester.baseContextPath"));
  String maxRepRecords = Val.chkStr(parameters.getValue("webharvester.maxRepRecords"));
  String maxRepErrors = Val.chkStr(parameters.getValue("webharvester.maxRepErrors"));
  String resourceAutoApprove = Val.chkStr(parameters.getValue("webharvester.resource.autoApprove"));

  Logger logger = getLogger();

  if (Val.chkBool(active, true)) {
    cfg.setActive(true);
    cfg.setQueueEnabled(true);
  } else {
    cfg.setActive(false);
    cfg.setQueueEnabled(false);
  }

  if (Val.chkBool(suspended, false)) {
    cfg.setSuspended(true);
  } else {
    cfg.setSuspended(false);
  }

  if (queueEnabled.length()>0) {
    cfg.setQueueEnabled(Val.chkBool(queueEnabled, cfg.getQueueEnabled()) || cfg.getActive());
  }

  if (poolsize.length() > 0) {
    try {
      int num = Integer.parseInt(poolsize);
      if (num <= 0) {
        logger.info("[SYNCHRONIZER] Parameter \"webharvester.poolSize\" less or equal to zero. No harvestig will be performed.");
      }
      cfg.setPoolSize(num);
    } catch (NumberFormatException ex) {
      logger.log(Level.INFO, "[SYNCHRONIZER] Invalid \"webharvester.poolSize\" parameter. Default {0} will be used instead.", HarvesterConfiguration.DEFAULT_POOL_SIZE);
      cfg.setPoolSize(HarvesterConfiguration.DEFAULT_POOL_SIZE);
    }
  } else {
    logger.log(Level.INFO, "[SYNCHRONIZER] Missing \"webharvester.poolSize\" parameter. Default {0} will be used instead.", HarvesterConfiguration.DEFAULT_POOL_SIZE);
    cfg.setPoolSize(HarvesterConfiguration.DEFAULT_POOL_SIZE);
  }

  if (autoselectfrequency.length() > 0) {
    try {
      TimePeriod tp = TimePeriod.parseValue(autoselectfrequency);
      cfg.setAutoSelectFrequency(tp);
    } catch (NumberFormatException ex) {
      logger.log(Level.INFO, "[SYNCHRONIZER] Invalid \"webharvester.autoSelectFrequency\" parameter. Default {0} will be used instead.", HarvesterConfiguration.AUTOSELECT_FREQUENCY);
      cfg.setAutoSelectFrequency(new TimePeriod(HarvesterConfiguration.AUTOSELECT_FREQUENCY));
    }
  } else {
    logger.log(Level.INFO, "[SYNCHRONIZER] Missing \"webharvester.autoSelectFrequency\" parameter. Default {0} will be used instead.", HarvesterConfiguration.AUTOSELECT_FREQUENCY);
    cfg.setAutoSelectFrequency(new TimePeriod(HarvesterConfiguration.AUTOSELECT_FREQUENCY));
  }

  if (watchdogfrequency.length() > 0) {
    try {
      TimePeriod tp = TimePeriod.parseValue(watchdogfrequency);
      cfg.setWatchDogFrequency(tp);
    } catch (NumberFormatException ex) {
      logger.log(Level.INFO, "[SYNCHRONIZER] Invalid \"webharvester.watchDogFrequency\" parameter. Default {0} will be used instead.", HarvesterConfiguration.WATCHDOG_FREQUENCY);
      cfg.setWatchDogFrequency(new TimePeriod(HarvesterConfiguration.WATCHDOG_FREQUENCY));
    }
  } else {
    logger.log(Level.INFO, "[SYNCHRONIZER] Missing \"webharvester.watchDogFrequency\" parameter. Default {0} will be used instead.", HarvesterConfiguration.WATCHDOG_FREQUENCY);
    cfg.setWatchDogFrequency(new TimePeriod(HarvesterConfiguration.WATCHDOG_FREQUENCY));
  }

  if (basecontextpath.length() > 0) {
    cfg.setBaseContextPath(basecontextpath);
  } else {
    String reverseProxyPath = Val.chkStr(parameters.getValue("reverseProxy.baseContextPath"));
    if (reverseProxyPath.length() > 0) {
      logger.info("[SYNCHRONIZER] Missing \"webharvester.baseContextPath\" parameter. Value of \"reverseProxy.baseContextPath\" will be used instead.");
    } else {
      logger.info("[SYNCHRONIZER] Missing \"webharvester.baseContextPath\" parameter. Harvest notification messages will be sent without information about harvest report.");
    }
  }

  if (maxRepRecords.length() > 0) {
    try {
      long num = Long.parseLong(maxRepRecords);
      if (num < 0) {
        logger.info("[SYNCHRONIZER] Parameter \"webharvester.maxRepRecords\" less than zero. No limits will be set.");
      }
      cfg.setMaxRepRecords(num);
    } catch (NumberFormatException ex) {
      logger.log(Level.INFO, "[SYNCHRONIZER] Invalid \"webharvester.maxRepRecords\" parameter. Default {0} will be used instead.", HarvesterConfiguration.MAX_REP_RECORDS);
      cfg.setMaxRepRecords(HarvesterConfiguration.MAX_REP_RECORDS);
    }
  } else {
    logger.log(Level.INFO, "[SYNCHRONIZER] Missing \"webharvester.maxRepRecords\" parameter. Default {0} will be used instead.", HarvesterConfiguration.MAX_REP_RECORDS);
    cfg.setMaxRepRecords(HarvesterConfiguration.MAX_REP_RECORDS);
  }


  if (maxRepErrors.length() > 0) {
    try {
      long num = Long.parseLong(maxRepErrors);
      if (num < 0) {
        logger.info("[SYNCHRONIZER] Parameter \"webharvester.maxRepErrors\" less than zero. No limits will be set.");
      }
      cfg.setMaxRepErrors(num);
    } catch (NumberFormatException ex) {
      logger.log(Level.INFO, "[SYNCHRONIZER] Invalid \"webharvester.maxRepErrors\" parameter. Default {0} will be used instead.", HarvesterConfiguration.MAX_REP_ERRORS);
      cfg.setMaxRepErrors(HarvesterConfiguration.MAX_REP_ERRORS);
    }
  } else {
    logger.log(Level.INFO, "[SYNCHRONIZER] Missing \"webharvester.maxRepErrors\" parameter. Default {0} will be used instead.", HarvesterConfiguration.MAX_REP_ERRORS);
    cfg.setMaxRepErrors(HarvesterConfiguration.MAX_REP_ERRORS);
  }

  if (resourceAutoApprove.length() > 0) {
    boolean bool = Val.chkBool(resourceAutoApprove,HarvesterConfiguration.RESOURCE_AUTOAPPROVE);
    cfg.setResourceAutoApprove(bool);
  } else {
    logger.log(Level.INFO, "[SYNCHRONIZER] Missing \"webharvester.resource.autoApprove\" parameter. Default {0} will be used instead.", HarvesterConfiguration.RESOURCE_AUTOAPPROVE);
    cfg.setResourceAutoApprove(HarvesterConfiguration.RESOURCE_AUTOAPPROVE);
  }
 
  // load data processor factories
  XPath xpath = XPathFactory.newInstance().newXPath();
 
  // add local data processor factory by default
  cfg.getDataProcessorFactories().add(new LocalDataProcessorFactory());

  // get root of webharvester configuration
  Node ndWebHarvester = (Node) xpath.evaluate("webharvester", root, XPathConstants.NODE);
  if (ndWebHarvester!=null) {
    // create and initialize data processor for each netry in configuration
    NodeList ndDataProcessorFactories = (NodeList) xpath.evaluate("dataProcessorFactory", ndWebHarvester, XPathConstants.NODESET);
    for (Node ndDataProcessorFactory : new NodeListAdapter(ndDataProcessorFactories)) {
      String className = Val.chkStr((String) xpath.evaluate("@className", ndDataProcessorFactory, XPathConstants.STRING));
      String name = Val.chkStr((String) xpath.evaluate("@name", ndDataProcessorFactory, XPathConstants.STRING));
      boolean enabled = Val.chkBool(Val.chkStr((String) xpath.evaluate("@enabled", ndDataProcessorFactory, XPathConstants.STRING)), true);
      if (enabled) {
        try {
          Class factoryClass = Class.forName(className);
          DataProcessorFactory processorFactory = (DataProcessorFactory) factoryClass.newInstance();
          processorFactory.setName(name);
          processorFactory.init(ndDataProcessorFactory);
          cfg.getDataProcessorFactories().add(processorFactory);
        } catch (Exception ex) {
          getLogger().log(Level.SEVERE, "Error creating processor factory: "+className, ex);
        }
      } else {
        if (LocalDataProcessorFactory.class.getCanonicalName().equals(className)) {
          removeDataProcessorFactory(cfg.getDataProcessorFactories(), className);
        }
      }
    }
  }
}

private void removeDataProcessorFactory(List<DataProcessorFactory> factories, String factoryClassName) {
  for (DataProcessorFactory factory : factories) {
    if (factory.getClass().getCanonicalName().equals(factoryClassName)) {
      factories.remove(factory);
      break;
    }
  }
}

/**
* Loads protocol factories.
* @param appConfig protocol factories
*/
private void loadProtocolFactories(ApplicationConfiguration appConfig, Document dom, Node root) throws XPathExpressionException {
  ProtocolFactories factories = appConfig.getProtocolFactories();
  XPath xpath = XPathFactory.newInstance().newXPath();

  Node ndProtocols = (Node) xpath.evaluate("protocols", root, XPathConstants.NODE);
  if (ndProtocols!=null) {
    // check 'default' attribute of the 'protcols' node; if present and true than initialize default factories
    boolean defaultValue = Val.chkBool((String) xpath.evaluate("@default", ndProtocols, XPathConstants.STRING),false);
    if (defaultValue) {
        factories.initDefault();
    }
   
    // initilaize explicit protocol factories
    NodeList lstProtocol = (NodeList) xpath.evaluate("protocol", ndProtocols, XPathConstants.NODESET);
    for (Node ndProto : new NodeListAdapter(lstProtocol)) {
      String factoryClass = (String) xpath.evaluate("@factoryClass", ndProto, XPathConstants.STRING);
      try {
        Class fc = Class.forName(factoryClass);
        ProtocolFactory factory = (ProtocolFactory) fc.newInstance();
        ProtocolInitializer.init(factory, ndProto);
        String resourceKey = Val.chkStr((String) xpath.evaluate("@resourceKey", ndProto, XPathConstants.STRING));
        factories.put(factory.getName(), factory, resourceKey);
      } catch (Exception ex) {
        getLogger().log(Level.WARNING, "Error loading protocol: "+factoryClass, ex);
      }
     
      String validatorFactoryClass = Val.chkStr((String) xpath.evaluate("validator/@factoryClass", ndProto, XPathConstants.STRING));
      if (!validatorFactoryClass.isEmpty()) {
        try {
          Class fc = Class.forName(validatorFactoryClass);
          IValidatorFactory factory = (IValidatorFactory) fc.newInstance();
          ValidatorFactory.register(factory);
        } catch (Exception ex) {
          getLogger().log(Level.WARNING, "Error loading protocol validator factory: "+validatorFactoryClass, ex);
        }
      }
    }
  } else {
    factories.initDefault();
  }
}

/**
* Reads the parameters under a parent node.
*
* @param parameters
*          the parameters to populate
* @param parent
*          the parent node containing the parameters to read
* @throws XPathExpressionException
*           indicates a programming error, bad XPath
*/
private void populateParameters(StringAttributeMap parameters, Node parent)
    throws XPathExpressionException {
  XPath xpath = XPathFactory.newInstance().newXPath();
  NodeList nlParameters = (NodeList) xpath.evaluate("parameter", parent,
      XPathConstants.NODESET);
  for (int i = 0; i < nlParameters.getLength(); i++) {
    Node ndParameter = nlParameters.item(i);
    String sKey = Val.chkStr(xpath.evaluate("@key", ndParameter));
    String sValue = Val.chkStr(xpath.evaluate("@value", ndParameter));
    if (sKey.length() > 0) {
      parameters.add(new StringAttribute(sKey, sValue));
    }
  }
}
 
/**
* Safely parses time period giving default value if time period can not be parsed.
* @param periodDef period definition to parse
* @param defaultValue default value if period definition cannot be parsed
* @return time period
*/
private TimePeriod parsePeriod(String periodDef, long defaultValue) {
  try {
    periodDef = Val.chkStr(periodDef);
    if (periodDef.isEmpty()) {
      return new TimePeriod(defaultValue);
    }
    return TimePeriod.parseValue(periodDef);
  } catch (IllegalArgumentException ex) {
    return new TimePeriod(defaultValue);
  }
}
}
TOP

Related Classes of com.esri.gpt.framework.context.ApplicationConfigurationLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.