Sample protocol bridge properties user exit

For information about how to use this sample user exit, see ProtocolBridgePropertiesExit2: Looking up protocol file server properties

SamplePropertiesExit2.java


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import com.ibm.wmqfte.exitroutine.api.ProtocolBridgePropertiesExit2;
import com.ibm.wmqfte.exitroutine.api.ProtocolServerPropertyConstants;

/**
 * A sample protocol bridge properties exit. This exit reads a properties file
 * that contains properties for protocol servers.
 * <p>
 * The format of each entry in the properties file is:
 * {@literal serverName=type://host:port}
 * Ensure there is a default entry such as
 * {@literal default=type://host:port}
 * otherwise the agent will fail to start with a BFGBR0168 as it must have a
 * default server. 
 * <p>
 * The location of the properties file is taken from the protocol bridge agent
 * property {@code protocolBridgePropertiesConfiguration}.
 * <p>
 * The methods {@code getCredentialLocation} returns the location of the associated
 * ProtocolBridgeCredentials.xml, this sample it is defined to be stored in a directory
 * defined by the environment variable CREDENTIALSHOME
 * <p>
 * To install the sample exit:
 * <ol>
 * <li>Compile the class and export to a jar file.
 * <li>Place the jar file in the {@code exits} subdirectory of the agent data directory
 * of the protocol bridge agent on which the exit is to be installed.
 * <li>In the {@code agent.properties} file of the protocol bridge agent
 * set the {@code protocolBridgePropertiesExitClasses} to
 * {@code SamplePropertiesExit2}.
 * <li>Create a properties file that contains the appropriate properties to specify the
 * required servers.
 * <li>In the {@code agent.properties} file of the protocol bridge agent
 * set the <code>protocolBridgePropertiesConfiguration</code> property to the
 * absolute path name of this properties file.
 * <li>To activate the changes stop and restart the protocol bridge agent.
 * </ol>
 * <p>
 * For further information on protocol bridge properties exits refer to the
 * WebSphere MQ Managed File Transfer documentation online at:
 * <p>
 * {@link https://www.ibm.com/docs/SSEP7X_7.0.4/welcome/WelcomePagev7r0.html}
 */
public class SamplePropertiesExit2 implements ProtocolBridgePropertiesExit2 {

	/**
	 * Helper class to encapsulate protocol server information.
	 */
	private static class ServerInformation {
		private final String type;
		private final String host;
		private final int port;
		
		public ServerInformation(String url) {
			int index = url.indexOf("://");
			if (index == -1) throw new IllegalArgumentException("Invalid server URL: "+url);
			type = url.substring(0, index);
			
			int portIndex = url.indexOf(":", index+3);
			if (portIndex == -1) {
				host = url.substring(index+3);
				port = -1;
			} else {
				host = url.substring(index+3,portIndex);
				port = Integer.parseInt(url.substring(portIndex+1));
			}
		}

		public String getType() {
			return type;
		}

		public String getHost() {
			return host;
		}

		public int getPort() {
			return port;
		}
	}
	
	/** A {@code Map} that holds information for each configured protocol server */
	final private Map<String, ServerInformation> servers = new HashMap<String, ServerInformation>();
	

	/* (non-Javadoc)
	 * @see com.ibm.wmqfte.exitroutine.api.ProtocolBridgePropertiesExit#getProtocolServerProperties(java.lang.String)
	 */
	public Properties getProtocolServerProperties(String protocolServerName) {
		// Attempt to get the protocol server information for the given protocol server name	
		// If no name has been supplied then this implies the default.
		final ServerInformation info;
		if (protocolServerName == null || protocolServerName.length() == 0) {
			protocolServerName = "default";
		}
		info = servers.get(protocolServerName);
		
		// Build the return set of properties from the collected protocol server information, when available.
		// The properties set here is the minimal set of properties to be a valid set.
		final Properties result;
		if (info != null) {
			result = new Properties();
			result.setProperty(ProtocolServerPropertyConstants.SERVER_NAME, protocolServerName);
			result.setProperty(ProtocolServerPropertyConstants.SERVER_TYPE, info.getType());
			result.setProperty(ProtocolServerPropertyConstants.SERVER_HOST_NAME, info.getHost());
			if (info.getPort() != -1) result.setProperty(ProtocolServerPropertyConstants.SERVER_PORT_VALUE, ""+info.getPort());
			result.setProperty(ProtocolServerPropertyConstants.SERVER_PLATFORM, "UNIX");
			if (info.getType().toUpperCase().startsWith("FTP")) {		// FTP & FTPS
				result.setProperty(ProtocolServerPropertyConstants.SERVER_TIMEZONE, "Europe/London");
				result.setProperty(ProtocolServerPropertyConstants.SERVER_LOCALE, "en-GB");
			}
			result.setProperty(ProtocolServerPropertyConstants.SERVER_FILE_ENCODING, "UTF-8");
		} else {
			System.err.println("Error no default protocol file server entry has been supplied");
			result = null;
		}
		
		return result;
	}

	/* (non-Javadoc)
	 * @see com.ibm.wmqfte.exitroutine.api.ProtocolBridgePropertiesExit#initialize(java.util.Map)
	 */
	public boolean initialize(Map<String, String> bridgeProperties) {
		// Flag to indicate whether the exit has been successfully initialized or not
		boolean initialisationResult = true;
		
		// Get the path of the properties file
		final String propertiesFilePath = bridgeProperties.get("protocolBridgePropertiesConfiguration");
		if (propertiesFilePath == null || propertiesFilePath.length() == 0) {
			// The protocol server properties file path has not been specified. Output an error and return false
			System.err.println("Error initializing SamplePropertiesExit."); 
			System.err.println("The location of the protocol server properties file has not been specified in the 
      protocolBridgePropertiesConfiguration property");
			initialisationResult = false;
		}
		
		if (initialisationResult) {
			// The Properties object that holds protocol server information
			final Properties mappingProperties = new Properties();
			
			// Open and load the properties from the properties file
			final File propertiesFile = new File (propertiesFilePath);
			FileInputStream inputStream = null;
			try {
				// Create a file input stream to the file
				inputStream = new FileInputStream(propertiesFile);
				
				// Load the properties from the file
				mappingProperties.load(inputStream);
			} catch (final FileNotFoundException ex) {
				System.err.println("Error initializing SamplePropertiesExit."); 
				System.err.println("Unable to find the protocol server properties file: " + propertiesFilePath);
				initialisationResult = false;
			} catch (final IOException ex) {
				System.err.println("Error initializing SamplePropertiesExit."); 
				System.err.println("Error loading the properties from the protocol server properties file: " + propertiesFilePath);
				initialisationResult = false;
			} finally {
				// Close the inputStream
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (final IOException ex) {
						System.err.println("Error initializing SamplePropertiesExit."); 
						System.err.println("Error closing the protocol server properties file: " + propertiesFilePath);
						initialisationResult = false;
					}
				}
			}
			
			if (initialisationResult) {
				// Populate the map of protocol servers from the properties
				for (Entry<Object, Object> entry : mappingProperties.entrySet()) {
					final String serverName = (String)entry.getKey();
					final ServerInformation info = new ServerInformation((String)entry.getValue());
					servers.put(serverName, info);
				}		
			}
		}
		
		return initialisationResult;
	}

	/* (non-Javadoc)
	 * @see com.ibm.wmqfte.exitroutine.api.ProtocolBridgePropertiesExit#shutdown(java.util.Map)
	 */
	public void shutdown(Map<String, String> bridgeProperties) {
		// Nothing to do in this method because there are no resources that need to be released
	}

	/* (non-Javadoc)
	 * @see com.ibm.wmqfte.exitroutine.api.ProtocolBridgePropertiesExit2#getCredentialLocation()
	 */
	public String getCredentialLocation() {
		String envLocationPath;
		if (System.getProperty("os.name").toLowerCase().contains("win")) {
			// Windows style
			envLocationPath = "%CREDENTIALSHOME%\\ProtocolBridgeCredentials.xml";
		}
		else {
			// Unix style
			envLocationPath = "$CREDENTIALSHOME/ProtocolBridgeCredentials.xml";
		}
		return envLocationPath;
	}

}