diff options
Diffstat (limited to 'spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java')
-rw-r--r-- | spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java | 956 |
1 files changed, 956 insertions, 0 deletions
diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java new file mode 100644 index 000000000..1e966911b --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java @@ -0,0 +1,956 @@ +package at.gv.egovernment.moa.spss.server.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.traversal.NodeIterator; + +import org.xml.sax.SAXException; + +import iaik.ixsil.exceptions.URIException; +import iaik.ixsil.util.URI; +import iaik.pki.pathvalidation.ChainingModes; +import iaik.utils.RFC2253NameParser; +import iaik.utils.RFC2253NameParserException; + +import at.gv.egovernment.moa.logging.LogMsg; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; + +import at.gv.egovernment.moa.spss.util.MessageProvider; + +/** + * A class that builds configuration data from a DOM based representation. + * + * @author Patrick Peck + * @version $Id$ + */ +public class ConfigurationPartsBuilder { + + // + // XPath namespace prefix shortcuts + // + + private static final String CONF = Constants.MOA_CONFIG_PREFIX + ":"; + private static final String DSIG = Constants.DSIG_PREFIX + ":"; + + // + // chaining mode constants appearing in the configuration file + // + + private static final String CM_CHAINING = "chaining"; + private static final String CM_PKIX = "pkix"; + + // + // XPath expressions to select certain parts of the configuration + // + + private static final String ROOT = "/" + CONF + "MOAConfiguration/"; + private static final String DIGEST_METHOD_XPATH = + ROOT + CONF + "DigestMethodAlgorithm/@name"; + private static final String C14N_ALGORITHM_XPATH = + ROOT + CONF + "CanonicalizationAlgorithm/@name"; + private static final String HARDWARE_CRYPTO_MODULE_XPATH = + ROOT + CONF + "HardwareCryptoModule"; + private static final String HARDWARE_KEY_XPATH = + ROOT + CONF + "HardwareKeyModule"; + private static final String SOFTWARE_KEY_XPATH = + ROOT + CONF + "SoftwareKeyModule"; + private static final String KEYGROUP_XPATH = ROOT + CONF + "KeyGroup"; + private static final String KEY_XPATH = CONF + "Key"; + private static final String KEY_MODULE_ID_XPATH = CONF + "KeyModuleID"; + private static final String KEY_CERT_XPATH = CONF + "KeyCertIssuerSerial"; + private static final String KEYGROUP_MAPPING_XPATH = + ROOT + CONF + "KeyGroupMapping"; + private static final String KEYGROUP_MAPPING_KEYGROUP_XPATH = + CONF + "KeyGroup"; + private static final String ISSUER_SERIAL_XPATH = CONF + "X509IssuerSerial"; + private static final String ISSUER_XPATH = DSIG + "X509IssuerName"; + private static final String SERIAL_XPATH = DSIG + "X509SerialNumber"; + private static final String CHAINING_MODES_XPATH = + ROOT + CONF + "ChainingModes"; + private static final String CHAINING_MODES_DEFAULT_XPATH = + CHAINING_MODES_XPATH + "/@systemDefaultMode"; + private static final String TRUST_ANCHOR_XPATH = + ROOT + CONF + "ChainingModes/" + CONF + "TrustAnchor"; + private static final String CRL_DISTRIBUTION_POINT_XPATH = + ROOT + CONF + "CRLDistributionPoint"; + private static final String CA_ISSUER_DN_XPATH = CONF + "CAIssuerDN"; + private static final String DISTRIBUTION_POINT_XPATH = + CONF + "DistributionPoint"; + private static final String CRL_ARCHIVE_XPATH = ROOT + CONF + "CRLArchive"; + private static final String GENERIC_CONFIGURATION_XPATH = + ROOT + CONF + "GenericConfiguration"; + private static final String CREATE_TRANSFORMS_INFO_PROFILE_XPATH = + ROOT + CONF + "CreateTransformsInfoProfile"; + private static final String CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH = + ROOT + CONF + "CreateSignatureEnvironmentProfile"; + private static final String VERIFY_TRANSFORMS_INFO_PROFILE_XPATH = + ROOT + CONF + "VerifyTransformsInfoProfile"; + private static final String SUPPLEMENT_PROFILE_XPATH = + ROOT + CONF + "SupplementProfile"; + private static final String TRUST_PROFILE_XPATH = + ROOT + CONF + "TrustProfile"; + + // + // default values for configuration parameters + // + + /** The accepted canonicalization algorithm URIs, as an array */ + private static final String[] ACCEPTED_C14N_ALGORITHMS_ARRAY = + { + Constants.C14N_URI, + Constants.C14N_WITH_COMMENTS_URI, + Constants.EXC_C14N_URI, + Constants.EXC_C14N_WITH_COMMENTS_URI }; + + /** The accepted canonicalization algorithm URIs, as a Set */ + private static final Set ACCEPTED_C14N_ALGORITHMS = + new HashSet(Arrays.asList(ACCEPTED_C14N_ALGORITHMS_ARRAY)); + + /** Default canonicalization algorithm, if none/illegal has been configured */ + private static final String C14N_ALGORITHM_DEFAULT = Constants.C14N_URI; + + /** The accepted digest method algorithm URIs, as an array */ + private static final String[] ACCEPTED_DIGEST_ALGORITHMS_ARRAY = + { Constants.SHA1_URI }; + + /** The accepted digest method algorithm URIs, as a Set */ + private static final Set ACCEPTED_DIGEST_ALGORITHMS = + new HashSet(Arrays.asList(ACCEPTED_DIGEST_ALGORITHMS_ARRAY)); + + /** Default digest algorithm URI, if none/illegal has been configured */ + private static final String DIGEST_ALGORITHM_DEFAULT = Constants.SHA1_URI; + + /** The root element of the MOA configuration */ + private Element configElem; + + /** Whether any warnings were encountered building the configuration. */ + private List warnings = new ArrayList(); + + /** + * Create a new <code>ConfigurationPartsBuilder</code>. + * + * @param configElem The root element of the MOA configuration. + */ + public ConfigurationPartsBuilder(Element configElem) { + this.configElem = configElem; + } + + /** + * Returns the root element of the MOA configuration. + * + * @return The root element of the MOA configuration. + */ + public Element getConfigElem() { + return configElem; + } + + /** + * Returns the warnings encountered during building the configuration. + * + * @return A <code>List</code> of <code>String</code>s, containing the + * warning messages. + */ + public List getWarnings() { + return warnings; + } + + /** + * Returns the digest method algorithm name. + * + * @return The digest method algorithm name from the configuration. + */ + public String getDigestMethodAlgorithmName() { + String digestMethod = + getAttributeValue(getConfigElem(), DIGEST_METHOD_XPATH, null); + + if (digestMethod == null + || !ACCEPTED_DIGEST_ALGORITHMS.contains(digestMethod)) { + warn( + "config.23", + new Object[] { "DigestMethodAlgorithm", DIGEST_ALGORITHM_DEFAULT }); + digestMethod = DIGEST_ALGORITHM_DEFAULT; + } + + return digestMethod; + } + + /** + * Returns the canonicalization algorithm name. + * + * @return The canonicalization algorithm name from the configuration. + */ + public String getCanonicalizationAlgorithmName() { + String c14nAlgorithm = + getAttributeValue(getConfigElem(), C14N_ALGORITHM_XPATH, null); + + if (c14nAlgorithm == null + || !ACCEPTED_C14N_ALGORITHMS.contains(c14nAlgorithm)) { + warn( + "config.23", + new Object[] { "CanonicalizationAlgorithm", C14N_ALGORITHM_DEFAULT }); + c14nAlgorithm = C14N_ALGORITHM_DEFAULT; + } + + return c14nAlgorithm; + } + + /** + * Build the mapping of generic configuration properties. + * + * @return The mapping of generic configuration properties (a name to value + * mapping) from the configuration. + */ + public Map buildGenericConfiguration() { + Map genericConfiguration = new HashMap(); + NodeIterator gcIter = + XPathUtils.selectNodeIterator( + getConfigElem(), + GENERIC_CONFIGURATION_XPATH); + Element gcElem; + + while ((gcElem = (Element) gcIter.nextNode()) != null) { + String gcName = gcElem.getAttribute("name"); + String gcValue = gcElem.getAttribute("value"); + + if (genericConfiguration.containsKey(gcName)) { + warn("config.24", new Object[] { gcName }); + } else { + genericConfiguration.put(gcName, gcValue); + } + } + + return genericConfiguration; + } + + /** + * Build the configured hardware crypto modules. + * + * @return The hardware crypto modules from the configuration. + */ + public List buildHardwareCryptoModules() { + List modules = new ArrayList(); + NodeIterator modIter = + XPathUtils.selectNodeIterator( + getConfigElem(), + HARDWARE_CRYPTO_MODULE_XPATH); + Element modElem; + + while ((modElem = (Element) modIter.nextNode()) != null) { + String name = modElem.getAttribute("name"); + String slotID = modElem.getAttribute("slotID"); + String userPIN = modElem.getAttribute("userPIN"); + HardwareCryptoModule module = + new HardwareCryptoModule(name, slotID, userPIN); + modules.add(module); + } + + return modules; + } + + /** + * Build the configured hardware keys. + * + * @param The keyModules that the configuration already knows about. To + * prevent multiple key modules with the same ID. + * @return The hardware keys contained in the configuration. + */ + public List buildHardwareKeyModules(List keyModules) { + Set existingIds = toIdSet(keyModules); + List hardwareKeys = new ArrayList(); + NodeIterator hkIter = + XPathUtils.selectNodeIterator(getConfigElem(), HARDWARE_KEY_XPATH); + Element keyElem; + + while ((keyElem = (Element) hkIter.nextNode()) != null) { + String id = keyElem.getAttribute("id"); + String name = keyElem.getAttribute("name"); + String slotID = keyElem.getAttribute("slotID"); + String userPIN = keyElem.getAttribute("userPIN"); + + if (existingIds.contains(id)) { + warn( + "config.04", + new Object[] { "Hardware- oder SoftwareKeyModule", id }); + } else { + KeyModule key = new HardwareKeyModule(id, name, slotID, userPIN); + hardwareKeys.add(key); + existingIds.add(id); + } + + } + + return hardwareKeys; + } + + /** + * Build the configured software keys. + * + * @param The keyModules that the configuration already knows about. To + * prevent multiple key modules with the same ID. + * @param configRoot The directory containing the main configuration file. + * Used to resolve keystore files configured using a relative URI. + * @return The software keys contained in the configuration. + */ + public List buildSoftwareKeyModules(List keyModules, File configRoot) { + Set existingIds = toIdSet(keyModules); + List softwareKeys = new ArrayList(); + NodeIterator skIter = + XPathUtils.selectNodeIterator(getConfigElem(), SOFTWARE_KEY_XPATH); + + Element keyElem; + + while ((keyElem = (Element) skIter.nextNode()) != null) { + String id = keyElem.getAttribute("id"); + String fileName = keyElem.getAttribute("filename"); + String passWord = keyElem.getAttribute("password"); + + if (existingIds.contains(id)) { + warn( + "config.04", + new Object[] { "Hardware- oder SoftwareKeyModule", id }); + } else { + File keyFile; + KeyModule key; + + // make keyFile absolute + keyFile = new File(fileName); + if (!keyFile.isAbsolute()) { + keyFile = new File(configRoot, fileName); + } + + // check for existence + if (!keyFile.exists() || keyFile.isDirectory()) { + warn("config.25", new Object[] { id, keyFile.getAbsolutePath()}); + } else { + // create a new key module + key = new SoftwareKeyModule(id, keyFile.getAbsolutePath(), passWord); + softwareKeys.add(key); + existingIds.add(id); + } + } + + } + + return softwareKeys; + } + + /** + * Build the key group configuration. + * + * @param keyModules The <code>KeyModule</code>s that the configuration + * knows about. Used to check for errors in the configuration. + * @return The mapping between key group IDs and key groups. + */ + public Map buildKeyGroups(List keyModules) { + Set keyModuleIds = toIdSet(keyModules); + Map keyGroups = new HashMap(); + NodeIterator kgIter; + Element keyGroupElem; + + // select all KeyGroup elements and build the KeyGroup objects from them + kgIter = XPathUtils.selectNodeIterator(getConfigElem(), KEYGROUP_XPATH); + while ((keyGroupElem = (Element) kgIter.nextNode()) != null) { + String keyGroupId = keyGroupElem.getAttribute("id"); + Set keyGroupEntries = + buildKeyGroupEntries(keyGroupId, keyModuleIds, keyGroupElem); + KeyGroup keyGroup = new KeyGroup(keyGroupId, keyGroupEntries); + + if (keyGroups.containsKey(keyGroupId)) { + warn("config.04", new Object[] { "KeyGroup", keyGroupId }); + } else { + keyGroups.put(keyGroup.getId(), keyGroup); + } + } + + return keyGroups; + } + + /** + * Return the set of IDs contained in the given <code>KeyModule</code>s. + * + * @param keyModules The <code>KeyModule</code>s from which to extract the + * IDs. + * @return The IDs from the given <code>KeyModule</code>s. + */ + private Set toIdSet(List keyModules) { + Set ids = new HashSet(); + Iterator iter; + + for (iter = keyModules.iterator(); iter.hasNext();) { + KeyModule keyModule = (KeyModule) iter.next(); + ids.add(keyModule.getId()); + } + + return ids; + } + + /** + * Build the key entries belonging to a key group. + * + * @param keyGroupId The ID of the key group we are building here. Passed + * for logging purposes. + * @param keyModuleIds The IDs of the <code>HardwareKeyModule</code>s and + * <code>SoftwareKeyModule</code>s that exist in the configuration. + * @param keyGroupElem The <code>KeyGroup</code> DOM element to parse. + * @return A <code>Set</code> of <code>KeyGroupEntry</code> objects. + */ + private Set buildKeyGroupEntries( + String keyGroupId, + Set keyModuleIds, + Element keyGroupElem) { + + Set entries = new HashSet(); + NodeIterator keyEntryIter; + Element keyEntryElem; + + // select all Key elements and put them into the Map + keyEntryIter = XPathUtils.selectNodeIterator(keyGroupElem, KEY_XPATH); + while ((keyEntryElem = (Element) keyEntryIter.nextNode()) != null) { + String keyModuleId = + getElementValue(keyEntryElem, KEY_MODULE_ID_XPATH, ""); + Element keyCertElem = + (Element) XPathUtils.selectSingleNode(keyEntryElem, KEY_CERT_XPATH); + IssuerAndSerial issuerSerial = buildIssuerAndSerial(keyCertElem); + + if (!keyModuleIds.contains(keyModuleId)) { + warn("config.26", new Object[] { keyGroupId, keyModuleId }); + } else if (issuerSerial != null) { + KeyGroupEntry entry = new KeyGroupEntry(keyModuleId, issuerSerial); + entries.add(entry); + } + } + return entries; + } + + /** + * Build the key group mapping. + * + * @param keyGroups The available key groups. + * @param anonymous The <code>IssuerAndSerial</code> to be used for key group + * mappings not protected by a certificate. + * @return The key group mapping. + */ + public Map buildKeyGroupMappings(Map keyGroups, IssuerAndSerial anonymous) { + Map mappings = new HashMap(); + NodeIterator mappingIter; + Element mappingElem; + + // select all KeyGroupMapping elements + mappingIter = + XPathUtils.selectNodeIterator(getConfigElem(), KEYGROUP_MAPPING_XPATH); + + // build the mapping for each KeyGroupMapping element + while ((mappingElem = (Element) mappingIter.nextNode()) != null) { + Element issuerSerialElem = + (Element) XPathUtils.selectSingleNode(mappingElem, ISSUER_SERIAL_XPATH); + IssuerAndSerial issuerAndSerial; + + // build the IssuerAndSerial who has access to the key groups + if (issuerSerialElem != null) { + issuerAndSerial = buildIssuerAndSerial(issuerSerialElem); + } else { + // IssuerSerial element: the keygroup is generally available + issuerAndSerial = anonymous; + } + + // add the key groups to the mappings + if (issuerAndSerial != null) { + Map groups = (Map) mappings.get(issuerAndSerial); + NodeIterator keyGroupIter; + Element keyGroupElem; + + if (groups == null) { + // no mapping exist -> build one + groups = new HashMap(); + mappings.put(issuerAndSerial, groups); + } + + // select the available key groups and add them to the mapping + keyGroupIter = + XPathUtils.selectNodeIterator( + mappingElem, + KEYGROUP_MAPPING_KEYGROUP_XPATH); + while ((keyGroupElem = (Element) keyGroupIter.nextNode()) != null) { + String keyGroupId = keyGroupElem.getAttribute("id"); + KeyGroup keyGroup = (KeyGroup) keyGroups.get(keyGroupId); + + if (keyGroup != null) { + groups.put(keyGroupId, keyGroup); + } else { + warn("config.00", new Object[] { keyGroupId }); + } + } + } + } + + return mappings; + } + + /** + * Returns the default chaining mode from the configuration. + * + * @return The default chaining mode. + */ + public String getDefaultChainingMode() { + String defaultChaining = + getAttributeValue( + getConfigElem(), + CHAINING_MODES_DEFAULT_XPATH, + CM_CHAINING); + + return translateChainingMode(defaultChaining); + + } + + /** + * Build the chaining modes for all configured trust anchors. + * + * @return The mapping from trust anchors to chaining modes. + */ + public Map buildChainingModes() { + Map chainingModes = new HashMap(); + NodeIterator trustIter = + XPathUtils.selectNodeIterator(getConfigElem(), TRUST_ANCHOR_XPATH); + Element trustAnchorElem; + + while ((trustAnchorElem = (Element) trustIter.nextNode()) != null) { + IssuerAndSerial issuerAndSerial = buildIssuerAndSerial(trustAnchorElem); + String mode = trustAnchorElem.getAttribute("mode"); + + if (issuerAndSerial != null) { + chainingModes.put(issuerAndSerial, translateChainingMode(mode)); + } + } + + return chainingModes; + } + + /** + * Build an <code>IssuerAndSerial</code> from the DOM representation. + * + * @param root The root element (being of type <code>dsig: + * X509IssuerSerialType</code>. + * @return The issuer and serial number contained in the <code>root</code> + * element or <code>null</code> if could not be built for any reason. + */ + private IssuerAndSerial buildIssuerAndSerial(Element root) { + String issuer = getElementValue(root, ISSUER_XPATH, null); + String serial = getElementValue(root, SERIAL_XPATH, null); + + if (issuer != null && serial != null) { + try { + RFC2253NameParser nameParser = new RFC2253NameParser(issuer); + Principal issuerDN = nameParser.parse(); + + return new IssuerAndSerial(issuerDN, new BigInteger(serial)); + } catch (RFC2253NameParserException e) { + warn("config.16", new Object[] { issuer, serial }, e); + return null; + } catch (NumberFormatException e) { + warn("config.16", new Object[] { issuer, serial }, e); + return null; + } + } + return null; + } + + /** + * Translate the chaining mode from the configuration file to one used in the + * IAIK MOA API. + * + * @param chainingMode The chaining mode from the configuration. + * @return The chaining mode as provided by the <code>ChainingModes</code> + * interface. + * @see iaik.pki.pathvalidation.ChainingModes + */ + private String translateChainingMode(String chainingMode) { + if (chainingMode.equals(CM_CHAINING)) { + return ChainingModes.CHAIN_MODE; + } else if (chainingMode.equals(CM_PKIX)) { + return ChainingModes.PKIX_MODE; + } else { + return ChainingModes.CHAIN_MODE; + } + } + + /** + * Build the CRL distribution points mapping. + * + * @return The mapping from certificate authorities to distribution points. + */ + public Map buildCRLDistributionPoints() { + Map crlDps = new HashMap(); + NodeIterator crlDpIter; + Element crlDpElem; + + // select all CRLDistributionPoint elements and build the + // CRLDistributionPoints + crlDpIter = + XPathUtils.selectNodeIterator( + getConfigElem(), + CRL_DISTRIBUTION_POINT_XPATH); + + // build the mapping of CA name to distribution points + while ((crlDpElem = (Element) crlDpIter.nextNode()) != null) { + String caIssuerDNText = + getElementValue(crlDpElem, CA_ISSUER_DN_XPATH, ""); + RFC2253NameParser nameParser = new RFC2253NameParser(caIssuerDNText); + NodeIterator dpIter = + XPathUtils.selectNodeIterator(crlDpElem, DISTRIBUTION_POINT_XPATH); + String caIssuerDN; + Set dps; + Element dpElem; + + try { + caIssuerDN = nameParser.parse().getName(); + + // check, if a mapping exists or make a new mapping + dps = (Set) crlDps.get(caIssuerDN); + if (dps == null) { + dps = new HashSet(); + crlDps.put(caIssuerDN, dps); + } + + // add the distribution points of this CA to the set + while ((dpElem = (Element) dpIter.nextNode()) != null) { + DistributionPoint dp = buildDistributionPoint(dpElem); + dps.add(dp); + } + } catch (RFC2253NameParserException e) { + warn("config.13", new Object[] { caIssuerDNText }, e); + } + + } + + return crlDps; + } + + /** + * Build a distribution point from the DOM representation. + * + * @param dpElem The root element of the distribution point. + * @return The distribution point. + */ + private DistributionPoint buildDistributionPoint(Element dpElem) { + String uri = dpElem.getAttribute("uri"); + String reasonCodes = dpElem.getAttribute("reasonCodes"); + + return new DistributionPoint(uri, reasonCodes != null ? reasonCodes : ""); + } + + /** + * Return the CRL archive duration. + * + * @return The value of the CRL archive duration setting from the + * configuration. + */ + public int getCRLArchiveDuration() { + Element crlArchiveElem = + (Element) XPathUtils.selectSingleNode(getConfigElem(), CRL_ARCHIVE_XPATH); + String crlArchiveDuration; + + if (crlArchiveElem == null) { + return 0; + } + + try { + crlArchiveDuration = crlArchiveElem.getAttribute("duration"); + return Integer.parseInt(crlArchiveDuration); + } catch (NumberFormatException e) { + warn("config.01", null); + return 0; + } + } + + /** + * Build the <code>CreateTransformsInfoProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildCreateTransformsInfoProfiles(File configRoot) { + return loadProfiles( + configRoot, + CREATE_TRANSFORMS_INFO_PROFILE_XPATH, + "CreateTransformsInfoProfile"); + } + + /** + * Build the <code>CreateSignatureEnvironmentProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildCreateSignatureEnvironmentProfiles(File configRoot) { + return loadProfiles( + configRoot, + CREATE_SIGNATURE_ENVIRONMENT_PROFILE_XPATH, + "CreateSignatureEnvironmentProfile"); + } + + /** + * Build the <code>VerifyTransformsInfoProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildVerifyTransformsInfoProfiles(File configRoot) { + return loadProfiles( + configRoot, + VERIFY_TRANSFORMS_INFO_PROFILE_XPATH, + "VerifyTransformsInfoProfile"); + } + + /** + * Build the <code>SupplementProfile</code>s. + * + * @param configRoot The directory of the main configuration file. Used for + * lookup of profiles with relative file names. + * @return The mapping from profile ID to profile. + */ + public Map buildSupplementProfiles(File configRoot) { + return loadProfiles( + configRoot, + SUPPLEMENT_PROFILE_XPATH, + "SupplementProfile"); + } + + /** + * Load a profile mapping. + * + * @param root The absolute directory path of the main configuration file. + * @param xpath The XPath to select the profiles from the configuration. + * @param profileRoot The name of the profile root element. + * @return Map The profile ID to profile mapping. + */ + private Map loadProfiles(File root, String xpath, String profileRoot) { + Map profiles = new HashMap(); + NodeIterator profileIter = + XPathUtils.selectNodeIterator(getConfigElem(), xpath); + Element profileElem; + + while ((profileElem = (Element) profileIter.nextNode()) != null) { + String id = profileElem.getAttribute("id"); + String fileName = profileElem.getAttribute("filename"); + + if (profiles.containsKey(id)) { + warn("config.04", new Object[] { profileRoot, id }); + } else { + Element profile; + + try { + File profileFile = new File(fileName); + + // make profileFile absolute + if (!profileFile.isAbsolute()) { + profileFile = new File(root, fileName); + } + + // load the profile + info( + "config.22", + new Object[] { profileRoot, id, profileFile.getAbsoluteFile()}); + profile = loadProfile(profileFile); + + if (profile.getTagName().equals(profileRoot)) { + profiles.put(id, profile); + } else { + warn("config.02", new Object[] { profileRoot, id, fileName }); + } + } catch (ConfigurationException e) { + warn("config.03", new Object[] { profileRoot, id }); + } + } + + } + + return profiles; + } + + /** + * Load a profile from a file. + * + * @param root The absolute directory path of the main configuration file. + * @param profileFile The file containing the profile. + * @return The profile in its DOM representation. + * @throws ConfigurationException An error occurred loading the profile. + */ + private Element loadProfile(File profileFile) throws ConfigurationException { + + Element profile; + + try { + profile = parseXml(new FileInputStream(profileFile)); + } catch (Exception e) { + throw new ConfigurationException("config.12", null, e); + } + + return profile; + } + + /** + * Bulid the trust profile mapping. + * + * @param configRoot The absolute path to the main configuration file. + * @return The profile ID to profile mapping. + */ + public Map buildTrustProfiles(File configRoot) { + Map trustProfiles = new HashMap(); + NodeIterator profileIter = + XPathUtils.selectNodeIterator(getConfigElem(), TRUST_PROFILE_XPATH); + Element profileElem; + + while ((profileElem = (Element) profileIter.nextNode()) != null) { + String id = profileElem.getAttribute("id"); + String uriStr = profileElem.getAttribute("uri"); + + try { + URI uri = new URI(uriStr); + TrustProfile profile; + File profileDir; + + if (!uri.isAbsolute()) { // make it absolute to the config file + uri = new URI(configRoot.toURL() + uriStr); + } + + profileDir = new File(uri.getPath()); + if (!profileDir.exists() || !profileDir.isDirectory()) { + warn("config.27", new Object[] { id }); + } + + if (trustProfiles.containsKey(id)) { + warn("config.04", new Object[] { "TrustProfile", id }); + } else { + profile = new TrustProfile(id, uri.toString()); + trustProfiles.put(id, profile); + } + + } catch (URIException e) { + warn("config.14", new Object[] { id, uriStr }, e); + } catch (MalformedURLException e) { + warn("config.15", null, e); + } + } + + return trustProfiles; + } + + // + // various utility methods + // + + /** + * Parse a configuration XML file. + * + * @param inputStream The stream from which to read the XML data. + * @return The DOM representation of the XML data. + * @throws ParserConfigurationException XML parser not configured properly. + * @throws SAXException An error parsing the XML file. + * @throws IOException An error reading the stream. + */ + private static Element parseXml(InputStream inputStream) + throws ParserConfigurationException, SAXException, IOException { + return DOMUtils + .parseDocument(inputStream, true, Constants.ALL_SCHEMA_LOCATIONS, null) + .getDocumentElement(); + } + + /** + * Return the value of an element located by an XPath. + * + * @param root The root element from which to evaluate the <code>xpath</code>. + * @param xpath The XPath pointing to the element. + * @param def The default value, if no element can be found with the given + * <code>xpath</code>. + * @return The element value or <code>def</code>, if the element cannot be + * found. + */ + private String getElementValue(Element root, String xpath, String def) { + + Element elem = (Element) XPathUtils.selectSingleNode(root, xpath); + return elem != null ? DOMUtils.getText(elem) : def; + } + + /** + * Return the value of an attribute located by an XPath. + * + * @param root The root element from which to evaluate the <code>xpath</code>. + * @param xpath The XPath pointing to the attribute. + * @param def The default value, if no attribute can be found with the given + * <code>xpath</code>. + * @return The element value or <code>def</code>, if the attribute cannot be + * found. + */ + private String getAttributeValue(Element root, String xpath, String def) { + Attr attr = (Attr) XPathUtils.selectSingleNode(root, xpath); + return attr != null ? attr.getValue() : def; + } + + /** + * Log an info message. + * + * @param messageId The message ID. + * @param parameters Additional parameters for the message. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private static void info(String messageId, Object[] parameters) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.info(new LogMsg(msg.getMessage(messageId, parameters))); + } + + /** + * Log a warning. + * + * @param messageId The message ID. + * @param args Additional parameters for the message. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private void warn(String messageId, Object[] args) { + MessageProvider msg = MessageProvider.getInstance(); + String txt = msg.getMessage(messageId, args); + + Logger.warn(new LogMsg(txt)); + warnings.add(txt); + } + + /** + * Log a warning. + * + * @param messageId The message ID. + * @param args Additional parameters for the message. + * @param t An exception being the cause of the warning. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private void warn(String messageId, Object[] args, Throwable t) { + MessageProvider msg = MessageProvider.getInstance(); + String txt = msg.getMessage(messageId, args); + + Logger.warn(new LogMsg(txt), t); + warnings.add(txt); + } + +} |