All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.galasa.zos3270.internal.Zos3270ManagerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright contributors to the Galasa project
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package dev.galasa.zos3270.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.validation.constraints.NotNull;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.annotations.Component;

import dev.galasa.ManagerException;
import dev.galasa.framework.spi.AbstractGherkinManager;
import dev.galasa.framework.spi.AnnotatedField;
import dev.galasa.framework.spi.ConfigurationPropertyStoreException;
import dev.galasa.framework.spi.GenerateAnnotatedField;
import dev.galasa.framework.spi.IConfigurationPropertyStoreService;
import dev.galasa.framework.spi.IDynamicStatusStoreService;
import dev.galasa.framework.spi.IFramework;
import dev.galasa.framework.spi.IGherkinManager;
import dev.galasa.framework.spi.IManager;
import dev.galasa.framework.spi.ResourceUnavailableException;
import dev.galasa.framework.spi.Result;
import dev.galasa.framework.spi.language.GalasaMethod;
import dev.galasa.framework.spi.language.GalasaTest;
import dev.galasa.ipnetwork.IIpHost;
import dev.galasa.textscan.spi.ITextScannerManagerSpi;
import dev.galasa.zos.IZosImage;
import dev.galasa.zos.IZosManager;
import dev.galasa.zos.spi.IZosManagerSpi;
import dev.galasa.zos3270.ITerminal;
import dev.galasa.zos3270.TerminalInterruptedException;
import dev.galasa.zos3270.Zos3270ManagerException;
import dev.galasa.zos3270.Zos3270Terminal;
import dev.galasa.zos3270.common.screens.TerminalSize;
import dev.galasa.zos3270.internal.gherkin.Gherkin3270Coordinator;
import dev.galasa.zos3270.internal.properties.ExtraBundles;
import dev.galasa.zos3270.internal.properties.Zos3270PropertiesSingleton;
import dev.galasa.zos3270.spi.IZos3270ManagerSpi;
import dev.galasa.zos3270.spi.NetworkException;
import dev.galasa.zos3270.spi.Zos3270TerminalImpl;

@Component(service = { IManager.class, IGherkinManager.class })
public class Zos3270ManagerImpl extends AbstractGherkinManager implements IZos3270ManagerSpi {
    protected static final String                       NAMESPACE     = "zos3270";

    private static final Log                            logger        = LogFactory.getLog(Zos3270ManagerImpl.class);

    private IDynamicStatusStoreService                  dss;

    private IZosManagerSpi                              zosManager;
    private ITextScannerManagerSpi						textScannerManager;

    private ArrayList              terminals     = new ArrayList<>();

    private int                                         terminalCount = 0;
    
    private Gherkin3270Coordinator                      gherkinCoordinator;

    /*
     * (non-Javadoc)
     * 
     * @see
     * dev.galasa.framework.spi.AbstractManager#initialise(dev.galasa.framework.spi.
     * IFramework, java.util.List, java.util.List, java.lang.Class)
     */
    @Override
    public void initialise(@NotNull IFramework framework, @NotNull List allManagers,
            @NotNull List activeManagers, @NotNull GalasaTest galasaTest) throws ManagerException {
        super.initialise(framework, allManagers, activeManagers, galasaTest);

        if(galasaTest.isJava()) {
            // *** Check to see if any of our annotations are present in the test class
            // *** If there is, we need to activate
            List ourFields = findAnnotatedFields(Zos3270ManagerField.class);
            if (!ourFields.isEmpty()) {
                youAreRequired(allManagers, activeManagers,galasaTest);
            }
        } else if (galasaTest.isGherkin()) {
            this.gherkinCoordinator = new Gherkin3270Coordinator(this, galasaTest.getGherkinTest());
            if (this.gherkinCoordinator.registerStatements()) {
                youAreRequired(allManagers, activeManagers,galasaTest);
            }
        }

        try {
            this.dss = framework.getDynamicStatusStoreService(NAMESPACE);
            Zos3270PropertiesSingleton.setCps(framework.getConfigurationPropertyService(NAMESPACE));
        } catch (Exception e) {
            throw new Zos3270ManagerException("Unable to request framework services", e);
        }

    }

    @Override
    public Result endOfTestMethod(@NotNull GalasaMethod galasaMethod, @NotNull Result currentResult, Throwable currentException)
            throws ManagerException {

        super.endOfTestMethod(galasaMethod, currentResult, currentException);

        if (galasaMethod.isGherkin()) {
            // The end of a test method in gherkin equates to the end of the scenario.
            // So we need to free up terminals so their state doesn't leech into the next scenario.
            // A scenario equates to a java method.
            disconnectAllTerminals();
        }

        return currentResult;
    }

    private void disconnectAllTerminals() throws Zos3270ManagerException {
        for( Zos3270TerminalImpl terminal: terminals) {
            if (terminal.isConnected()) {
                disconnectTerminal(terminal);
            }
        }
    }

    @Override
    public List extraBundles(@NotNull IFramework framework) throws ManagerException {
        try {
        	Zos3270PropertiesSingleton.setCps(framework.getConfigurationPropertyService(NAMESPACE));
        } catch (ConfigurationPropertyStoreException e) {
            throw new Zos3270ManagerException("Unable to request framework services", e);
        }

        return ExtraBundles.get();
    }

    @Override
    public void youAreRequired(@NotNull List allManagers, @NotNull List activeManagers, @NotNull GalasaTest galasaTest)
            throws ManagerException {
        if (activeManagers.contains(this)) {
            return;
        }

        activeManagers.add(this);
        zosManager = addDependentManager(allManagers, activeManagers, galasaTest, IZosManagerSpi.class);
        if (zosManager == null) {
            throw new Zos3270ManagerException("The zOS Manager is not available");
        }
        
        textScannerManager = addDependentManager(allManagers, activeManagers, galasaTest, ITextScannerManagerSpi.class);
        if (textScannerManager == null) {
        	throw new Zos3270ManagerException("The Text Scanner Manager is not available");
        }
    }

    @Override
    public boolean areYouProvisionalDependentOn(@NotNull IManager otherManager) {
        return (otherManager instanceof IZosManager) || (otherManager instanceof ITextScannerManagerSpi);
    }

    @Override
    public void provisionGenerate() throws ManagerException, ResourceUnavailableException {
        if (this.gherkinCoordinator != null) {
            this.gherkinCoordinator.provisionGenerate();
            return;
        }
        
        // *** Auto generate the fields
        generateAnnotatedFields(Zos3270ManagerField.class);
    }

    @GenerateAnnotatedField(annotation = Zos3270Terminal.class)
    public ITerminal generateTerminal(Field field, List annotations) throws Zos3270ManagerException {
        Zos3270Terminal terminalAnnotation = field.getAnnotation(Zos3270Terminal.class);

        // *** Default the tag to primary
        String tag = defaultString(terminalAnnotation.imageTag(), "PRIMARY").toUpperCase();
        // *** Default the tag to primary
        boolean autoConnect = terminalAnnotation.autoConnect();

        TerminalSize primaryTerminalSize   = new TerminalSize(terminalAnnotation.primaryColumns(), terminalAnnotation.primaryRows());
        TerminalSize alternateTerminalSize = new TerminalSize(terminalAnnotation.alternateColumns(), terminalAnnotation.alternateRows());
        
        return generateTerminal(tag, autoConnect, primaryTerminalSize, alternateTerminalSize);
    }
    
    public Zos3270TerminalImpl generateTerminal(String imageTag, boolean autoConnect, TerminalSize primarySize, TerminalSize alternateSize) throws Zos3270ManagerException {
        // *** Ask the zosManager for the image for the Tag
        try {
            IZosImage image = this.zosManager.provisionImageForTag(imageTag);
            IIpHost host = image.getIpHost();

            terminalCount++;
            String terminaId = "term" + (terminalCount);

            Zos3270TerminalImpl terminal = new Zos3270TerminalImpl(terminaId, host.getHostname(), host.getTelnetPort(),
                    host.isTelnetPortTls(), getFramework(), autoConnect, image, primarySize, alternateSize, textScannerManager);
            
            this.terminals.add(terminal);
            logger.info("Generated a terminal for zOS Image tagged " + imageTag);

            return terminal;
        } catch (Exception e) {
            throw new Zos3270ManagerException("Unable to generate Terminal for zOS Image tagged " + imageTag, e);
        }
    }
    
    @Override
    public void provisionStart() throws ManagerException, ResourceUnavailableException {
        if (terminals.isEmpty()) {
            return;
        }

        logger.info("Connecting zOS3270 Terminals");
        for (Zos3270TerminalImpl terminal : terminals) {
            try {
                if (terminal.doAutoConnect()) {
                    terminal.connect();
                    logger.trace("Connected zOS 3270 Terminal " + terminal.getId());
                } else {
                    logger.trace("AutoConnect flag is false for: " + terminal.getId());
                }
                
            } catch (NetworkException e) {
                logger.info("Failed to connect zOS 3270 Terminal to " + terminal.getHostPort(), e);
            }
        }
    }

    @Override
    public void provisionStop() {
        logger.trace("Disconnecting terminals");
        for (Zos3270TerminalImpl terminal : terminals) {
            disconnectTerminal(terminal);
        }
    }

    private void disconnectTerminal(Zos3270TerminalImpl terminal) {
        String terminalId = terminal.getId();
        logger.info("Disconnecting terminal "+terminalId);
        try {
            terminal.writeRasOutput();
            terminal.flushTerminalCache();
            terminal.disconnect();
        } catch (TerminalInterruptedException e) {
            logger.warn("Thread interrupted whilst disconnecting terminals", e);
            Thread.currentThread().interrupt();
        }
    }

    protected IConfigurationPropertyStoreService getCps() throws Zos3270ManagerException {
        return Zos3270PropertiesSingleton.cps();
    }

    protected IDynamicStatusStoreService getDss() {
        return this.dss;
    }

    public IZosManagerSpi getZosManager() {
        return this.zosManager;
    }

    /**
     * Get a CPS property from the zos3270 namespace.
     * 
     * The Gherkin sister-classes need to be able to retrieve properties from the CPS.
     *
     * @param fullPropertyName the name of the property you want. Including the namespace, which must
     * match {@link Zos3270ManagerImpl#NAMESPACE}
     */
    public String getCpsProperty(String fullPropertyName) throws Zos3270ManagerException {

        String propertyValue;

        if (!fullPropertyName.startsWith(Zos3270ManagerImpl.NAMESPACE+".")) {
            // This manager can only get properties from the zos3270 namespace.
            throw new Zos3270ManagerException(
                "Program logic error. CPS property name must start with '"+Zos3270ManagerImpl.NAMESPACE+".' for the Zos3270 manager to access it."+
                " Property"+fullPropertyName+" cannot be retrieved.");
        }

        try {

            // We get something like "zos3270.gherkin.terminal.rows" as input.
            // The cps we are using is already pinned to the zos3270 namespace, so we don't need to 
            // pass that. It is implicitly given.


            String[] propNameParts = fullPropertyName.split("\\.");
            // Skip the namespace zos3270 part.
            String prefix = propNameParts[1]; 
            String suffix = propNameParts[propNameParts.length-1]; 
            // allocate space for the infixes.
            String [] infixes = new String[propNameParts.length-3];
            System.arraycopy( propNameParts, 2, infixes, 0, propNameParts.length-3 );

            propertyValue = getCps().getProperty(prefix, suffix, infixes);
            logger.info("Property requested:"+fullPropertyName+" value:"+propertyValue);

        } catch (ConfigurationPropertyStoreException ex) {
            throw new Zos3270ManagerException("Failed to retrieve the CPS property "+fullPropertyName , ex );
        }

        return propertyValue;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy