FileDocCategorySizeDatePackage
PEDomainsManager.javaAPI DocGlassfish v2 API30445Mon Jul 30 15:00:38 BST 2007com.sun.enterprise.admin.servermgmt.pe

PEDomainsManager.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.admin.servermgmt.pe;

import com.sun.enterprise.admin.servermgmt.InstanceException;
import com.sun.enterprise.admin.servermgmt.InstancesManager;
import com.sun.enterprise.admin.servermgmt.launch.LaunchConstants;
import com.sun.enterprise.util.SystemPropertyConstants;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import com.sun.enterprise.util.io.FileUtils;
import com.sun.enterprise.util.i18n.StringManager;

import com.sun.enterprise.admin.servermgmt.DomainException;
import com.sun.enterprise.admin.servermgmt.DomainConfig;
import com.sun.enterprise.admin.servermgmt.RepositoryConfig;
import com.sun.enterprise.admin.servermgmt.RepositoryException;
import com.sun.enterprise.admin.servermgmt.DomainsManager;
import com.sun.enterprise.admin.servermgmt.RepositoryNameValidator;
import com.sun.enterprise.admin.servermgmt.DomainXmlEventListener;
import com.sun.enterprise.admin.servermgmt.RepositoryManager;
import com.sun.enterprise.admin.servermgmt.util.DomainXmlSAXParser;

import com.sun.enterprise.admin.common.Status;
import com.sun.enterprise.admin.util.TokenValue;

import com.sun.enterprise.admin.util.TokenValueSet;
import com.sun.enterprise.config.serverbeans.ServerValidationHandler;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
import java.util.BitSet;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import javax.xml.transform.OutputKeys;
import org.xml.sax.EntityResolver;

public class PEDomainsManager extends RepositoryManager 
    implements DomainsManager
{
    /**
     * i18n strings manager object
     */
    private static final StringManager strMgr = 
        StringManager.getManager(PEDomainsManager.class);
    private static final String NAME_DELIMITER = ",";
    
    /* These properties are public interfaces, handle with care */
    public static final String PROFILEPROPERTY_DOMAINXML_STYLESHEETS = "domain.xml.style-sheets";
    public static final String PROFILEPROPERTY_DOMAINXML_TOKENVALUES = "domain.xml.token-values";
    /* These properties are public interfaces, handle with care */
    
    public PEDomainsManager()
    {
        super();
    }
    
    //PE does not require that an admin user / password is available at start-domain time.
    //SE/SEE does require it.
    public BitSet getDomainFlags()
    {
        BitSet bs = new BitSet();        
        bs.set(DomainConfig.K_FLAG_START_DOMAIN_NEEDS_ADMIN_USER, false);
        return bs;
    }
    
    public void validateDomain(DomainConfig domainConfig, boolean domainExists)
        throws DomainException
    {
        try {
            checkRepository(domainConfig, domainExists, domainExists);
        } catch (RepositoryException ex) {
            throw new DomainException(ex);
        }
    }

    public void validateAdminUserAndPassword(DomainConfig domainConfig) 
        throws DomainException
    {
        try {
            validateAdminUserAndPassword(domainConfig, getDomainUser(domainConfig),
                getDomainPasswordClear(domainConfig));
        } catch (RepositoryException ex) {
            throw new DomainException(ex);
        }
    }
    
    public void validateMasterPassword(DomainConfig domainConfig) 
        throws DomainException
    {
        try {
            validateMasterPassword(domainConfig, getMasterPasswordClear(domainConfig));
        } catch (RepositoryException ex) {
            throw new DomainException(ex);
        }
    }
    
    public void createDomain(DomainConfig domainConfig) 
        throws DomainException
    {
        PEFileLayout layout = getFileLayout(domainConfig);
        
        try {
            new RepositoryNameValidator(strMgr.getString("domainsRoot")).
                    checkValidXmlToken(
                        layout.getRepositoryRootDir().getAbsolutePath());
            layout.createRepositoryRoot();        
            new PEDomainConfigValidator().validate(domainConfig);
            checkRepository(domainConfig, false);
        } catch (Exception ex) {
            throw new DomainException(ex);
        }
        
        try {            
            String masterPassword = getMasterPasswordClear(domainConfig);
            layout.createRepositoryDirectories();
            createDomainXml(domainConfig);
            createDomainXmlEvents(domainConfig);
            createScripts(domainConfig);
            createServerPolicyFile(domainConfig);
            createAdminKeyFile(domainConfig, getDomainUser(domainConfig), 
                getDomainPasswordClear(domainConfig));
            createKeyFile(domainConfig, getDomainUser(domainConfig),
                getDomainPasswordClear(domainConfig));
            createAppClientContainerXml(domainConfig);
            createIndexFile(domainConfig);
            createDefaultWebXml(domainConfig);
            createLoginConf(domainConfig);
            createWssServerConfig(domainConfig);
            createWssServerConfigOld(domainConfig);
            createSSLCertificateDatabase(domainConfig, masterPassword);                                     
            changeMasterPasswordInMasterPasswordFile(domainConfig, masterPassword, 
                saveMasterPassword(domainConfig));
            createPasswordAliasKeystore(domainConfig, masterPassword);        
            createTimerWal(domainConfig);
            createTimerDbn(domainConfig);
            createMQInstance(domainConfig);
            createJBIInstance(getDefaultInstance(), domainConfig);
            if (layout.getDerbyEjbTimerSqlFile().exists()) //will be cleaned up once derby integrates, 05/19/2005
                handleDerby(domainConfig);
            setPermissions(domainConfig);
        } catch (DomainException de) {
            //rollback
            FileUtils.liquidate(getDomainDir(domainConfig));
            throw de;
        } catch (Exception ex) {
            //rollback
            FileUtils.liquidate(getDomainDir(domainConfig));
            throw new DomainException(ex);
        }
    }
    /**
     */
    protected void createJBIInstance(String instanceName, 
                   DomainConfig domainConfig) throws DomainException
    {        
        try {
            getFileLayout(domainConfig).createJBIDomainDirectories();
            super.createJBIInstance(instanceName, domainConfig);

        } catch (Exception ex) {
            throw new DomainException(ex);
        }
    }
    /**
     * Sets the permissions for the domain directory, its config directory,
     * startserv/stopserv scripts etc.
     */
    protected void setPermissions(DomainConfig domainConfig) throws DomainException
    {        
        final PEFileLayout layout = getFileLayout(domainConfig);
        try {
            //4958533
            chmod("-R u+x ", layout.getBinDir());
            chmod("-R g-rwx,o-rwx ", layout.getConfigRoot());
            //4958533
        } catch (Exception e) {
            throw new DomainException(
                strMgr.getString("setPermissionError"), e);
        }   
    }

    public void deleteDomain(DomainConfig domainConfig) 
        throws DomainException
    {               
        try {
            deleteRepository(domainConfig);
        } catch (Exception e) {
            throw new DomainException(e);
        }
    }

    public void startDomain(DomainConfig domainConfig) 
        throws DomainException
    {                        
        try {
            checkRepository(domainConfig);            
            String[] options = getInteractiveOptions(
                (String)domainConfig.get(DomainConfig.K_USER), 
                (String)domainConfig.get(DomainConfig.K_PASSWORD),
                (String)domainConfig.get(DomainConfig.K_MASTER_PASSWORD),
                (HashMap)domainConfig.get(DomainConfig.K_EXTRA_PASSWORDS));            
            getInstancesManager(domainConfig).startInstance(options, (String[])null, getEnvProps(domainConfig));            
        } catch (Exception e) {
            throw new DomainException(e);
        }
    }

    public void stopDomain(DomainConfig domainConfig) 
        throws DomainException
    {                        
        try {
            checkRepository(domainConfig);            
            getInstancesManager(domainConfig).stopInstance();
        } catch (Exception e) {
            throw new DomainException(e);
        }
    }

    public String[] listDomainsAndStatus(DomainConfig domainConfig)
        throws DomainException
    {
        try {
            return listDomainsAndStatusAsString(domainConfig);
        } catch (Exception e) {
            throw new DomainException(e);
        }        
    }

    /**
     * Lists all the domains.
     */
    public String[] listDomains(DomainConfig domainConfig)
        throws DomainException
    {        
        try {
            return listRepository(domainConfig); 
        } catch (Exception e) {
            throw new DomainException(e);
        }        
    }


    protected void createDomainXmlEvents(DomainConfig domainConfig) 
        throws DomainException {
            try {
                final PEFileLayout layout = getFileLayout(domainConfig);
                final File domainXml = layout.getDomainConfigFile();
                DomainXmlSAXParser parser = new DomainXmlSAXParser();
                try {
                    parser.parse(domainXml,layout.getDtdFile());
                }
                catch(Exception e) {
                    throw new DomainException(
                        strMgr.getString("domainXmlNotParsed"), e);
                }
                String className = parser.getDomainXmlEventListenerClass();
                if(className!=null) {
                    DomainXmlEventListener listener = (DomainXmlEventListener) Class.forName(className).newInstance();
                    listener.handleCreateEvent(domainConfig);
                }
            }
            catch(Exception e) {
                throw new DomainException(
                    strMgr.getString("domainXmlEventsNotCreated"), e);
            }
    }

    /**
     * The EEDomains manager needs to have an augmented set of tokens
     */
    protected TokenValueSet getDomainXmlTokens(DomainConfig domainConfig) {
        return PEDomainXmlTokens.getTokenValueSet(domainConfig);
    }
    
    protected void createDomainXml(DomainConfig domainConfig) 
        throws DomainException
    {
        try
        {
            final PEFileLayout layout = getFileLayout(domainConfig);
            final File dx = layout.getDomainConfigFile();
            final File dxt, tr;
            TokenValueSet tokens = getDomainXmlTokens(domainConfig);
            String tn = (String)domainConfig.get(DomainConfig.K_TEMPLATE_NAME);
            if((tn == null)||(tn.equals(""))) {
                //use profiles in this case
                dxt = layout.getDomainXmlTemplate();
                final String p = domainConfig.getProfile();
                final File pf = layout.getProfileFolder(p);
                if (!pf.exists()) {
                    final String key = "profileNotFound";
                    final String path = pf.getAbsolutePath();
                    final String name = domainConfig.getRepositoryName();
                    final String msg = strMgr.getString(key, p, path, name);
                    throw new IllegalArgumentException(msg);
                }
                if (new File(pf, layout.DOMAIN_XML_FILE).exists()) {
                // takes care of the default profiles that we bundle.
                    tr = new File(pf, layout.DOMAIN_XML_FILE);
                }
                else { //now transform for generic xsl
                    tr = invokeGenericXmlTemplateProcessing(dxt, domainConfig, 
                        PROFILEPROPERTY_DOMAINXML_STYLESHEETS, layout.getConfigRoot());
                    addTokenValuesIfAny(tokens, layout, p, this.PROFILEPROPERTY_DOMAINXML_TOKENVALUES);
                }
                generateFromTemplate(tokens, tr, dx);
            }
            else {
                dxt = layout.getDomainXmlTemplate(tn);
                generateFromTemplate(tokens, dxt, dx);
            }
        }
        catch(Exception e)
        {
            throw new DomainException(
                strMgr.getString("domainXmlNotCreated"), e);
        }
    }

    protected void createScripts(DomainConfig domainConfig)
        throws DomainException
    {
        final TokenValueSet tokens = PEScriptsTokens.getTokenValueSet(domainConfig);
        createStartServ(domainConfig, tokens);
        createStopServ(domainConfig, tokens);
    }

    void createStartServ(DomainConfig domainConfig, 
        TokenValueSet  tokens) throws DomainException
    {
        try
        {
            final PEFileLayout  layout = getFileLayout(domainConfig);
            final File startServTemplate = layout.getStartServTemplate();
            final File startServ = layout.getStartServ();
            generateFromTemplate(tokens, startServTemplate, startServ);
        }
        catch (Exception e)
        {
            throw new DomainException(
                strMgr.getString("startServNotCreated"), e);
        }
    }

    void createStopServ(DomainConfig domainConfig, 
        TokenValueSet  tokens) throws DomainException
    {
        try
        {
            final PEFileLayout  layout = getFileLayout(domainConfig);
            final File stopServTemplate = layout.getStopServTemplate();
            final File stopServ = layout.getStopServ();
            generateFromTemplate(tokens, stopServTemplate, stopServ);
            //final File killServ = layout.getKillServTemplate();
            //generateFromTemplate(new TokenValueSet(), 
		//layout.getKillServTemplate(), layout.getKillServ());
        }
        catch (Exception e)
        {
            throw new DomainException(
                strMgr.getString("stopServNotCreated"), e);
        }
    } 

    protected void createAppClientContainerXml(
        DomainConfig domainConfig) throws DomainException
    {
        try
        {
            final PEFileLayout layout = getFileLayout(domainConfig);
            final File accXmlTemplate = 
                layout.getAppClientContainerXmlTemplate();
            final File accXml = layout.getAppClientContainerXml();
            TokenValueSet tokens = PEAccXmlTokens.getTokenValueSet(domainConfig);
            generateFromTemplate(tokens, accXmlTemplate, accXml);
        }
        catch(Exception e)
        {
            throw new DomainException(strMgr.getString("accXmlNotCreated"), e);
        }
    }

    protected void createIndexFile(
        DomainConfig domainConfig) throws DomainException
    {
        final PEFileLayout layout = getFileLayout(domainConfig);
        final File src = layout.getIndexFileTemplate();
        final File dest = layout.getIndexFile();
        try
        {
            final TokenValueSet tokens = IndexHtmlTokens.getTokenValueSet(domainConfig);
            generateFromTemplate(tokens, src, dest);
            handleLocalizedIndexHtmls(layout, tokens);
        }
        catch (IOException ioe)
        {
            throw new DomainException(
                strMgr.getString("indexFileNotCreated"), ioe);
        }
    }
    private void handleLocalizedIndexHtmls(PEFileLayout layout, TokenValueSet tokens) {
        Locale locale = Locale.getDefault();
        if (Locale.ENGLISH.getLanguage().equals(locale.getLanguage()))
            return; //don't do anything in the case of English "language", not just locale
        //rename the existing index.file first
        File src  = layout.getNonEnglishIndexFileTemplate(locale);
        File dest = layout.getIndexFile();
        if (src.exists()) {
            dest.renameTo(layout.getEnglishIndexFile());
            dest = layout.getIndexFile();
            try {
                generateFromTemplate(tokens, src, dest);
            } catch(IOException e) {
                String one = strMgr.getString("problemCopyingIndexHtml", src.getAbsolutePath(), dest.getAbsolutePath());
                System.out.println(one);
            }
        } else {
            String two = strMgr.getString("localeFileNotFound", locale, src.getAbsolutePath());
            System.out.println(two);
        }
    }
    
    protected void createDefaultWebXml(
        DomainConfig domainConfig) throws DomainException
    {
        final PEFileLayout layout = getFileLayout(domainConfig);
        final File src = layout.getDefaultWebXmlTemplate();
        final File dest = layout.getDefaultWebXml();
        try
        {
            FileUtils.copy(src, dest);
        }
        catch (IOException ioe)
        {
            throw new DomainException(
                strMgr.getString("defaultWebXmlNotCreated"), ioe);
        }
    }
    
    protected void createLoginConf(
        RepositoryConfig config) throws DomainException
    {
        final PEFileLayout layout = getFileLayout(config);
        final File src = layout.getLoginConfTemplate();
        final File dest = layout.getLoginConf();
        try
        {
            FileUtils.copy(src, dest);
        }
        catch (IOException ioe)
        {
            throw new DomainException(
                strMgr.getString("loginConfNotCreated"), ioe);
        }
    }    

    protected void createWssServerConfigOld(RepositoryConfig config)
        throws DomainException
    {
        final PEFileLayout layout = getFileLayout(config);
        final File src = layout.getWssServerConfigOldTemplate();
        final File dest = layout.getWssServerConfigOld();
        try
        {
            FileUtils.copy(src, dest);
        }
        catch (IOException ioe)
        {
            throw new DomainException(
                strMgr.getString("wssserverconfignotcreated"), ioe);
        }

    }

    protected void createWssServerConfig(RepositoryConfig config)
        throws DomainException
    {
        final PEFileLayout layout = getFileLayout(config);
        final File src = layout.getWssServerConfigTemplate();
        final File dest = layout.getWssServerConfig();
        try
        {
            FileUtils.copy(src, dest);
        }
        catch (IOException ioe)
        {
            throw new DomainException(
                strMgr.getString("wssserverconfignotcreated"), ioe);
        }

    }

    protected File getDomainDir(DomainConfig domainConfig)
    {
        return getRepositoryDir(domainConfig);
    }

    protected File getDomainRoot(DomainConfig domainConfig)
    {
        return getRepositoryRootDir(domainConfig);
    }

    String getDefaultInstance()
    {
        return PEFileLayout.DEFAULT_INSTANCE_NAME;
    }
     
    /** Returns the domain user from the domainConfig.
     *  @param Map that represents the domain configuration
     *  @return String representing the domain user if the given map contains
     *  it, null otherwise
    */

    protected static String getDomainUser(DomainConfig domainConfig) 
    {
        return ( (String) domainConfig.get(DomainConfig.K_USER) );
    }
    
    /** Returns the domain user's password in cleartext from the domainConfig.
     *  @param Map that represents the domain configuration
     *  @return String representing the domain user password if the 
     *  given map contains it, null otherwise
    */

    protected static String getDomainPasswordClear(DomainConfig domainConfig) 
    {
        return ( (String) domainConfig.get(DomainConfig.K_PASSWORD) );
    } 
    
    protected static String getMasterPasswordClear(DomainConfig domainConfig)
    {
        return ((String)domainConfig.get(DomainConfig.K_MASTER_PASSWORD));
    }
    
    protected static String getNewMasterPasswordClear(DomainConfig domainConfig)
    {
        return ((String)domainConfig.get(DomainConfig.K_NEW_MASTER_PASSWORD));
    }
    
    protected static boolean saveMasterPassword(DomainConfig domainConfig) {
        Boolean b = (Boolean)domainConfig.get(DomainConfig.K_SAVE_MASTER_PASSWORD);
        return b.booleanValue();
    }
    
    /**
     * Changes the master password for the domain
     */    
    public void changeMasterPassword(DomainConfig config) throws DomainException
    {                                      
        try {
            //Ensure that the entity is stopped
            final int status = getInstancesManager(config).getInstanceStatus();
            if (status != Status.kInstanceNotRunningCode) {
                throw new DomainException(
                    strMgr.getString("cannotChangePassword_invalidState",
                        config.getDisplayName(), Status.getStatusString(status)));
            }
        
            String oldPass = getMasterPasswordClear(config);
            String newPass = getNewMasterPasswordClear(config);                        
            
            //Change the password of the keystore alias file
            changePasswordAliasKeystorePassword(config, oldPass, newPass);
            
            //Change the password of the keystore and truststore
            changeSSLCertificateDatabasePassword(config, oldPass, newPass);

            //Change the password in the masterpassword file or delete the file if it is 
            //not to be saved.
            changeMasterPasswordInMasterPasswordFile(config, newPass, saveMasterPassword(config));
        } catch (Exception ex) {
            throw new DomainException(
                strMgr.getString("masterPasswordNotChanged"), ex);
        }
    }
    
    public String[] getExtraPasswordOptions(DomainConfig config)
        throws DomainException
    {
        return null;
    }
    
    public void stopDomainForcibly(DomainConfig domainConfig, int timeout) 
        throws DomainException 
    {
        try {
            checkRepository(domainConfig);
            InstancesManager domainMgr = getInstancesManager(domainConfig);

            boolean stopped = false;
            
            if(timeout > 0)
                stopped = domainMgr.stopInstanceWithinTime(timeout);
            
            if (!stopped) domainMgr.killRelatedProcesses(); 
        } catch (Exception e) {
            throw new DomainException(e);
        }        
    }

    protected Properties getEnvProps(DomainConfig dc)
    {
        Properties p = new Properties();

        p.setProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY,
                    dc.getRepositoryRoot() + File.separator + dc.getRepositoryName());
        
        // this will be set again by ASLauncher.  It doesn't hurt to do it here too
        p.setProperty("domain.name", dc.getRepositoryName());
      
        p.setProperty(LaunchConstants.PROCESS_NAME_PROP, "as9-server");
        
        return p;
    }

    private boolean isDomainNotRunning(DomainConfig domainConfig) 
        throws InstanceException
    {
        InstancesManager instMgr = getInstancesManager(domainConfig);
        
        return (Status.kInstanceNotRunningCode ==
                instMgr.getInstanceStatus());
    }
    
    private File invokeGenericXmlTemplateProcessing(final File base, final DomainConfig
        dc, final String propName, final File destDir) 
        throws ProfileTransformationException {
        final PEFileLayout layout                 = getFileLayout(dc);
        final String profileName                  = dc.getProfile();
        final File profileFolder                  = layout.getProfileFolder(profileName);
        String msg = strMgr.getString("genericProfileHandlingStarts", profileFolder.getName());
        System.out.println(msg);
        msg = strMgr.getString("genericXmlProcessing", base, profileFolder.getName(), propName);
        System.out.println(msg);
        final File propsFile = layout.getProfilePropertiesFile(profileName);
        final List<File> styleSheets = getStyleSheetList(profileFolder, propsFile, propName);
        final Properties p = new Properties();
        p.setProperty(OutputKeys.DOCTYPE_PUBLIC, ServerValidationHandler.SERVER_DTD_PUBLIC_ID);
        p.setProperty(OutputKeys.DOCTYPE_SYSTEM, ServerValidationHandler.SERVER_DTD_SYSTEM_ID);
        final EntityResolver er = new ServerValidationHandler();
        final ProfileTransformer px = new ProfileTransformer(base, styleSheets, destDir, er, p);
        final File transformed = px.transform();
        return ( transformed );
    }
    
    private static List<File> getStyleSheetList(final File pf,
        final File propsFile, final String p) throws RuntimeException {
        /* Implementation note: I have chosen to throw a runtime exception here
         * because if this fails, there is no way to recover. It almost
         * certainly means that there is something wrong with the installation.
         */
        if (! propsFile.exists() || ! propsFile.canRead()) {
            final String msg = strMgr.getString("profilePropertiesMissing", propsFile.getAbsolutePath());
            throw new IllegalArgumentException(msg);
        }
        try {
            final String ssNames    = readProfilePropertyValue(propsFile, p);
            final StringTokenizer tk = new StringTokenizer(ssNames, NAME_DELIMITER);
            final List<File> list    = new ArrayList<File>(tk.countTokens());
            while (tk.hasMoreTokens()) {
                final File ss = new File(pf, tk.nextToken().trim());
                if (! ss.exists()) {
                    final String msg = strMgr.getString("styleSheetNotFound", ss.getAbsolutePath());
                    throw new RuntimeException(msg);
                }
                list.add(ss);
            }
            return ( list );
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    private static String readProfilePropertyValue(final File propsFile, final
        String propName) throws IOException {
        /* Could be optimized, but it should not be done prematurely. This
         * method could be called multiple times while doing profile processing,
         * but it is OK to load the properties every time, because I don't have
         * data to suggest that that should not be done. I don't think we will
         * run into performance issues with respect to this.
         */
        final Properties ps = new Properties();
        String propValue = null;
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(propsFile));
        try {
            ps.load(bis);
            propValue = ps.getProperty(propName);
            if (propValue == null) {
                propValue = "";
            }
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (final IOException ee) {
                    // Have to squelch
                }
            }
        }
        return ( propValue ); 
    }
    
    private static void addTokenValuesIfAny(final TokenValueSet tokens, 
        final PEFileLayout layout, final String profileName, final String propName) 
        throws IOException {
        final File propsFile      = layout.getProfilePropertiesFile(profileName);
        final String tvsAsString  = readProfilePropertyValue(propsFile, propName);
        final Set<TokenValue> tvs = s2TV(tvsAsString);
        tokens.addAll(tvs);
    }
    
    private static Set<TokenValue> s2TV(final String nvpairs) {
        final Set<TokenValue> set = new HashSet<TokenValue>();
        final StringTokenizer st = new StringTokenizer(nvpairs, NAME_DELIMITER);
        String msg;
        while (st.hasMoreTokens()) {
            String tvs = st.nextToken();
            if (tvs == null || tvs.indexOf("=") == -1 || tvs.length() < 3) {
                msg = strMgr.getString("invalidToken", tvs);
            }
            tvs = tvs.trim();
            final int e2 = tvs.indexOf("=");
            final String t = tvs.substring(0, e2);
            final String v = tvs.substring(e2+1);
            msg = strMgr.getString("processingToken", new String[] {t, v});
            System.out.println(msg);
            final TokenValue tv = new TokenValue(t, v); //default delimiter
            set.add(tv);
        }
        return ( set );
    }

}