Java tutorial
//-------------------------------------------------------------------- // The MIT License (MIT) // // Copyright (c) 2014 by Norman Dunbar // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Project : Oracle Tnsnames.ora parser. // Developed by : Norman Dunbar, norman@dunbar-it.co.uk //-------------------------------------------------------------------- import org.antlr.v4.runtime.TokenStream; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.RuleContext; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.Interval; import java.io.File; import java.util.*; public class tnsnamesInterfaceListener extends tnsnamesBaseListener { tnsnamesParser parser; // The Parser we are listening for. String[] ruleNames; // The parser's list of rule names. List<String> aliasNames = new ArrayList<String>(); List<String> duplicateNames = new ArrayList<String>(); int lineNumber; // Which line are we parsing? int charPosition; // And where on the line? String whereAmI; // Location in file message. int totalWarnings = 0; // Total count of WARNINGs in this file. int totalErrors = 0; // Total count of ERRORs in this file. int totalInfo = 0; // Total count of INFOs in this file. int thisWarnings = 0; // Total count of WARNINGs in this entry. int thisErrors = 0; // Total count of ERRORs in this entry. int thisInfo = 0; // Total count of INFO in this entry. int totalDuplicates = 0; // Were there any duplicate entries found? // Some counters, these will be zero'd on entry to a tns_alias and // incremented for each different parameter found in an entry. // The following are all to be found in the DESCRIPTION. LineNumber firstSduLine = new LineNumber(0); // SDU. LineNumber firstLoadBalanceLine = new LineNumber(0); // LOAD_BALANCE. LineNumber firstEnableLine = new LineNumber(0); // ENABLE. LineNumber firstFailOverLine = new LineNumber(0); // FAILOVER. LineNumber firstRecvBufLine = new LineNumber(0); // RECV_BUF_SIZE LineNumber firstSendBufLine = new LineNumber(0); // SEND_BUF_SIZE LineNumber firstSourceRouteLine = new LineNumber(0); // SOURCE_ROUTE LineNumber firstServiceTypeLine = new LineNumber(0); // SERVICE_TYPE LineNumber firstSecurityLine = new LineNumber(0); // SECURITY LineNumber firstConnTimeoutLine = new LineNumber(0); // CONN_TIMEOUT LineNumber firstRetryCountLine = new LineNumber(0); // RETRY_COUNT LineNumber firstTctLine = new LineNumber(0); // TCT // The following are all DESCRIPTION_LIST parameters. LineNumber firstDL_LoadBalanceLine = new LineNumber(0); // LOAD_BALANCE. LineNumber firstDL_FailOverLine = new LineNumber(0); // FAILOVER. LineNumber firstDL_SourceRouteLine = new LineNumber(0); // SOURCE_ROUTE. // The following are all ADDRESS_LIST parameters. LineNumber firstAL_LoadBalanceLine = new LineNumber(0); // LOAD_BALANCE. LineNumber firstAL_FailOverLine = new LineNumber(0); // FAILOVER. LineNumber firstAL_SourceRouteLine = new LineNumber(0); // SOURCE_ROUTE. // The following are all ADDRESS parameters. LineNumber firstA_RecvBufLine = new LineNumber(0); // RECV_BUF_SIZE. LineNumber firstA_SendBufLine = new LineNumber(0); // SEND_BUF_SIZE. // The following are all CONNECT_DATA parameters. LineNumber firstCD_ServiceNameLine = new LineNumber(0); // SERVICE_NAME. LineNumber firstCD_SidLine = new LineNumber(0); // SID. LineNumber firstCD_InstanceNameLine = new LineNumber(0); // INSTANCE_NAME. LineNumber firstCD_FailoverModeLine = new LineNumber(0); // FAILOVER_MODE. LineNumber firstCD_GlobalNameLine = new LineNumber(0); // GLOBAL_NAME. LineNumber firstCD_HsLine = new LineNumber(0); // HS. LineNumber firstCD_RdbDatabaseLine = new LineNumber(0); // RDB_DATABASE. LineNumber firstCD_ServerLine = new LineNumber(0); // SERVER. LineNumber firstCD_UrLine = new LineNumber(0); // UR. // These are for TCP Protocol. LineNumber firstTCP_HostLine = new LineNumber(0); // HOST LineNumber firstTCP_PortLine = new LineNumber(0); // PORT LineNumber firstTCP_ProtocolLine = new LineNumber(0); // PROTOCOL // These are for IPC Protocol. LineNumber firstIPC_KeyLine = new LineNumber(0); // KEY LineNumber firstIPC_ProtocolLine = new LineNumber(0); // PROTOCOL // These are for SPX Protocol. LineNumber firstSPX_ServiceLine = new LineNumber(0); // SERVICE LineNumber firstSPX_ProtocolLine = new LineNumber(0); // PROTOCOL // These are for NMP Protocol LineNumber firstNMP_PipeLine = new LineNumber(0); // PIPE LineNumber firstNMP_ServerLine = new LineNumber(0); // SERVER LineNumber firstNMP_ProtocolLine = new LineNumber(0); // PROTOCOL // These are for BEQ Protocol LineNumber firstBEQ_ProgramLine = new LineNumber(0); // PROGRAM LineNumber firstBEQ_ProtocolLine = new LineNumber(0); // PROTOCOL LineNumber firstBEQ_Argv0Line = new LineNumber(0); // ARGV0 (ARGV<zero>) LineNumber firstBEQ_ArgsLine = new LineNumber(0); // ARGS // These are from BEQ Args. LineNumber firstBAD_AddressLine = new LineNumber(0); // ADDRESS LineNumber firstBAD_LocalLine = new LineNumber(0); // LOCAL LineNumber firstBAD_ProtocolLine = new LineNumber(0); // PROTOCOL // These are for the FAILOVER_MODE in CONNECT_DATA. LineNumber firstFOM_BackupLine = new LineNumber(0); // BACKUP LineNumber firstFOM_TypeLine = new LineNumber(0); // TYPE LineNumber firstFOM_MethodLine = new LineNumber(0); // METHOD LineNumber firstFOM_RetriesLine = new LineNumber(0); // RETRIES LineNumber firstFOM_DelayLine = new LineNumber(0); // DELAY //---------------------------------------------------------------- // CONSTRUCTOR //---------------------------------------------------------------- // We use the parser, because we need the rule names later when we // are checking for parameter redefinition of the parameters that // apply to DESCRIPTION_LIST, DESCRIPTION and ADDRESS_LIST. //---------------------------------------------------------------- public tnsnamesInterfaceListener(tnsnamesParser parser) { this.parser = parser; this.ruleNames = parser.getRuleNames(); } //---------------------------------------------------------------- // Write an INFO to stderr and increment the information counters. //---------------------------------------------------------------- public void doInfo(String message) { System.err.println(whereAmI + "INFO: " + message); totalInfo += 1; thisInfo += 1; } //---------------------------------------------------------------- // Write an WARNING to stderr and increment the warning counters. //---------------------------------------------------------------- public void doWarning(String message) { System.err.println(whereAmI + "WARNING: " + message); totalWarnings += 1; thisWarnings += 1; } //---------------------------------------------------------------- // Write an ERROR to stderr and increment the total error counters. //---------------------------------------------------------------- public void doError(String message) { System.err.println(whereAmI + "ERROR: " + message); totalErrors += 1; thisErrors += 1; } //---------------------------------------------------------------- // Error Logger for parameter redefinitions //---------------------------------------------------------------- // This function simply prints a warning message to stderr when // we find a parameter has been redefined at some point. //---------------------------------------------------------------- public void tnsRedefined(String tnsSectionName, int firstLineNumber) { doWarning(tnsSectionName + " parameter redefines " + tnsSectionName + " parameter at line " + firstLineNumber + "."); } //------------------------------------------------------------------ // Check for parameter redefinitions //------------------------------------------------------------------ // This function checks to see if the passed LineNumber has been // redefined by the current lineNumber. If so, prints a warning // message and saves the current lineNumber. //------------------------------------------------------------------ // First time we hit a specific parameter, previous will be zero // so we save the current line number as the previous one. All // other passes through will be redefinitions and result in warnings. //------------------------------------------------------------------ // And don;t talk to me about Java's inability to properly pass by // reference. Having to wrap an int in a class, with a getter and // setter just to be able to swap two ints in a function, is a joke. //------------------------------------------------------------------ public void checkForRedefinition(String message, LineNumber previous, int current) { if (previous.intValue() != 0) { // Not the first time we've seen this parameter, so // warn the user about a redefinition. tnsRedefined(message, previous.intValue()); } else { // First time we've seen this parameter, so save the // current line number. previous.setValue(current); } } //---------------------------------------------------------------- // EVERY RULE //---------------------------------------------------------------- // As we enter every rule, extract the line and column positions. // Use them to build a location string for the start of this rule. //---------------------------------------------------------------- @Override public void enterEveryRule(ParserRuleContext ctx) { Token startToken = ctx.getStart(); if (startToken != null) { // Lines number from 1. this.lineNumber = startToken.getLine(); // Characters from zero. Adjust. this.charPosition = 1 + startToken.getCharPositionInLine(); } else { // Just in case Token can ever be null. this.lineNumber = 0; this.charPosition = 0; } // Build a location string for error messages etc. this.whereAmI = "\tLine " + lineNumber + ":" + charPosition + " "; } //---------------------------------------------------------------- // LISTENER ENTRY //---------------------------------------------------------------- // We have found a listener style tns_entry. //---------------------------------------------------------------- @Override public void enterLsnr_entry(tnsnamesParser.Lsnr_entryContext ctx) { String thisAlias = ctx.alias().getText(); System.err.println("\n" + whereAmI.substring(1) + " Listener alias found: " + thisAlias); thisInfo = 0; thisWarnings = 0; thisErrors = 0; // Has this alias been seen before in this file? if (aliasNames.contains(thisAlias)) { doError("Duplicate alias - " + thisAlias); duplicateNames.add(thisAlias); totalDuplicates++; } else { // New alias, add it to the list of found aliases. aliasNames.add(ctx.alias().getText()); } } //---------------------------------------------------------------- // LISTENER EXIT //---------------------------------------------------------------- @Override public void exitLsnr_entry(tnsnamesParser.Lsnr_entryContext ctx) { System.err.println("*** INFO: " + thisInfo + ", WARNING: " + thisWarnings + ", ERRORS: " + thisErrors); } //---------------------------------------------------------------- // TNS ENTRY //---------------------------------------------------------------- // We have found a proper database style tns_entry. //---------------------------------------------------------------- @Override public void enterTns_entry(tnsnamesParser.Tns_entryContext ctx) { String thisAlias = ctx.alias_list().getText(); System.err.println("\n" + whereAmI.substring(1) + " Database alias found: " + thisAlias); // Initialise the counters for this tns alias. thisInfo = 0; thisWarnings = 0; thisErrors = 0; // Add each alias to the found aliases list, if it hasn't already been added. for (int i = 0; i < ctx.alias_list().alias().size(); i++) { thisAlias = ctx.alias_list().alias(i).getText(); // Has this alias been seen before in this file? if (aliasNames.contains(thisAlias)) { doError("Duplicate alias - " + thisAlias); duplicateNames.add(thisAlias); totalDuplicates++; } else { aliasNames.add(thisAlias); } } } //---------------------------------------------------------------- // TNS EXIT //---------------------------------------------------------------- @Override public void exitTns_entry(tnsnamesParser.Tns_entryContext ctx) { System.err.println("*** INFO: " + thisInfo + ", WARNING: " + thisWarnings + ", ERRORS: " + thisErrors); } //---------------------------------------------------------------- // DESCRIPTION_LIST ENTRY //---------------------------------------------------------------- @Override public void enterDescription_list(tnsnamesParser.Description_listContext ctx) { // Zeroise the first line counters for the parameters applicable // to a DESCRIPTION_LIST entry. firstDL_LoadBalanceLine.setValue(0); // LOAD_BALANCE firstDL_FailOverLine.setValue(0); // FAILOVER firstDL_SourceRouteLine.setValue(0); // SOURCE_ROUTE } //---------------------------------------------------------------- // DESCRIPTION ENTRY //---------------------------------------------------------------- @Override public void enterDescription(tnsnamesParser.DescriptionContext ctx) { // Zeroise the first line counters for the parameters applicable // to a DESCRIPTION entry. firstSduLine.setValue(0); // SDU firstLoadBalanceLine.setValue(0); // LOAD_BALANCE firstEnableLine.setValue(0); // ENABLE firstFailOverLine.setValue(0); // FAILOVER firstRecvBufLine.setValue(0); // RECV_BUF_SIZE firstSendBufLine.setValue(0); // SEND_BUF_SIZE firstSourceRouteLine.setValue(0); // ROUTE firstServiceTypeLine.setValue(0); // SERVICE_TYPE firstSecurityLine.setValue(0); // SECURITY firstConnTimeoutLine.setValue(0); // CONN_TIMEOUT firstRetryCountLine.setValue(0); // RETRY_COUNT firstTctLine.setValue(0); // TCT // Multiple ADDRESSes without an ADDRESS_LIST? int addressCount = ctx.address().size(); if (ctx.address_list() == null && addressCount > 1) { // We might have a problem, but Oracle allows this form anyway. doWarning("Missing ADDRESS_LIST, " + addressCount + " ADDRESS entries found."); } // Missing CONNECT_DATA? if (ctx.connect_data() == null) { doError("Missing CONNECT_DATA."); } } //---------------------------------------------------------------- // ADDRESS_LIST ENTRY //---------------------------------------------------------------- @Override public void enterAddress_list(tnsnamesParser.Address_listContext ctx) { // Zeroise the first line counters for the parameters applicable // to a ADDRESS_LIST entry. firstA_RecvBufLine.setValue(0); // RECV_BUF_SIZE firstA_SendBufLine.setValue(0); // SEND_BUF_SIZE } //---------------------------------------------------------------- // ADDRESS ENTRY //---------------------------------------------------------------- @Override public void enterAddress(tnsnamesParser.AddressContext ctx) { // Zeroise the first line counters for the parameters applicable // to a ADDRESS entry. firstAL_LoadBalanceLine.setValue(0); // Address List firstAL_FailOverLine.setValue(0); firstAL_SourceRouteLine.setValue(0); firstTCP_HostLine.setValue(0); // TCP firstTCP_PortLine.setValue(0); firstTCP_ProtocolLine.setValue(0); firstIPC_KeyLine.setValue(0); // IPC firstIPC_ProtocolLine.setValue(0); firstSPX_ServiceLine.setValue(0); // SPX firstSPX_ProtocolLine.setValue(0); firstNMP_ServerLine.setValue(0); // NMP firstNMP_PipeLine.setValue(0); firstNMP_ProtocolLine.setValue(0); firstBEQ_ProgramLine.setValue(0); // BEQ firstBEQ_ProtocolLine.setValue(0); firstBEQ_Argv0Line.setValue(0); firstBEQ_ArgsLine.setValue(0); } //---------------------------------------------------------------- // CONNECT_DATA ENTRY //---------------------------------------------------------------- @Override public void enterConnect_data(tnsnamesParser.Connect_dataContext ctx) { // Zeroise the first line counters for the parameters applicable // to a CONNECT_DATA entry. firstCD_ServiceNameLine.setValue(0); // SERVICE_NAME firstCD_SidLine.setValue(0); // SID firstCD_InstanceNameLine.setValue(0); // INSTANCE_NAME firstCD_FailoverModeLine.setValue(0); // FAILOVER_MODE firstCD_GlobalNameLine.setValue(0); // GLOBAL_NAME firstCD_HsLine.setValue(0); // HS firstCD_RdbDatabaseLine.setValue(0); // RDB_DATABASE firstCD_ServerLine.setValue(0); // SERVER firstCD_UrLine.setValue(0); // UR } //---------------------------------------------------------------- // BA_DESCRIPTION ENTRY //---------------------------------------------------------------- @Override public void enterBa_description(tnsnamesParser.Ba_descriptionContext ctx) { // Zeroise the first line counters for the parameters applicable // to a BEQ ARGS DESCRIPTION entry. firstBAD_AddressLine.setValue(0); // ADDRESS firstBAD_LocalLine.setValue(0); // LOCAL firstBAD_ProtocolLine.setValue(0); // PROTOCOL } //---------------------------------------------------------------- // SERVICE_NAME ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_service_name(tnsnamesParser.Cd_service_nameContext ctx) { checkForRedefinition("SERVICE_NAME", firstCD_ServiceNameLine, this.lineNumber); } //---------------------------------------------------------------- // SID ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_sid(tnsnamesParser.Cd_sidContext ctx) { checkForRedefinition("SID", firstCD_SidLine, this.lineNumber); } //---------------------------------------------------------------- // INSTANCE_NAME ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_instance_name(tnsnamesParser.Cd_instance_nameContext ctx) { checkForRedefinition("INSTANCE_NAME", firstCD_InstanceNameLine, this.lineNumber); } //---------------------------------------------------------------- // FAILOVER_MODE ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. There will be checks // later on for the individual parts of a FAILOVER_MODE. //---------------------------------------------------------------- @Override public void enterCd_failover_mode(tnsnamesParser.Cd_failover_modeContext ctx) { checkForRedefinition("FAILOVER_MODE", firstCD_FailoverModeLine, this.lineNumber); // Reset the line numbers for the various FAILOVER_MODE parameters. firstFOM_BackupLine.setValue(0); firstFOM_TypeLine.setValue(0); firstFOM_MethodLine.setValue(0); firstFOM_RetriesLine.setValue(0); firstFOM_DelayLine.setValue(0); } //---------------------------------------------------------------- // FOM BACKUP ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterFo_backup(tnsnamesParser.Fo_backupContext ctx) { checkForRedefinition("BACKUP", firstFOM_BackupLine, this.lineNumber); } //---------------------------------------------------------------- // FOM TYPE ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterFo_type(tnsnamesParser.Fo_typeContext ctx) { checkForRedefinition("TYPE", firstFOM_TypeLine, this.lineNumber); } //---------------------------------------------------------------- // FOM METHOD ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterFo_method(tnsnamesParser.Fo_methodContext ctx) { checkForRedefinition("METHOD", firstFOM_MethodLine, this.lineNumber); } //---------------------------------------------------------------- // FOM RETRIES ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterFo_retries(tnsnamesParser.Fo_retriesContext ctx) { checkForRedefinition("RETRIES", firstFOM_RetriesLine, this.lineNumber); } //---------------------------------------------------------------- // FOM DELAY ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterFo_delay(tnsnamesParser.Fo_delayContext ctx) { checkForRedefinition("DELAY", firstFOM_DelayLine, this.lineNumber); } //---------------------------------------------------------------- // GLOBAL_NAME ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_global_name(tnsnamesParser.Cd_global_nameContext ctx) { checkForRedefinition("GLOBAL_NAME", firstCD_GlobalNameLine, this.lineNumber); } //---------------------------------------------------------------- // HS ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_hs(tnsnamesParser.Cd_hsContext ctx) { checkForRedefinition("HS", firstCD_HsLine, this.lineNumber); } //---------------------------------------------------------------- // RDB_DATABASE ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_rdb_database(tnsnamesParser.Cd_rdb_databaseContext ctx) { checkForRedefinition("RDB_DATABASE", firstCD_RdbDatabaseLine, this.lineNumber); } //---------------------------------------------------------------- // SERVER ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_server(tnsnamesParser.Cd_serverContext ctx) { checkForRedefinition("SERVER", firstCD_ServerLine, this.lineNumber); } //---------------------------------------------------------------- // UR ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterCd_ur(tnsnamesParser.Cd_urContext ctx) { checkForRedefinition("UR", firstCD_UrLine, this.lineNumber); } //---------------------------------------------------------------- // TCP HOST ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterTcp_host(tnsnamesParser.Tcp_hostContext ctx) { checkForRedefinition("HOST", firstTCP_HostLine, this.lineNumber); } //---------------------------------------------------------------- // TCP PORT ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterTcp_port(tnsnamesParser.Tcp_portContext ctx) { checkForRedefinition("PORT", firstTCP_PortLine, this.lineNumber); } //---------------------------------------------------------------- // TCP PROTOCOL ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterTcp_tcp(tnsnamesParser.Tcp_tcpContext ctx) { checkForRedefinition("PROTOCOL", firstTCP_ProtocolLine, this.lineNumber); } //---------------------------------------------------------------- // IPC KEY ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterIpc_key(tnsnamesParser.Ipc_keyContext ctx) { checkForRedefinition("KEY", firstIPC_KeyLine, this.lineNumber); } //---------------------------------------------------------------- // IPC PROTOCOL ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterIpc_ipc(tnsnamesParser.Ipc_ipcContext ctx) { checkForRedefinition("PROTOCOL", firstIPC_ProtocolLine, this.lineNumber); } //---------------------------------------------------------------- // SPX SERVICE ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterSpx_service(tnsnamesParser.Spx_serviceContext ctx) { checkForRedefinition("KEY", firstSPX_ServiceLine, this.lineNumber); } //---------------------------------------------------------------- // SPX PROTOCOL ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterSpx_spx(tnsnamesParser.Spx_spxContext ctx) { checkForRedefinition("PROTOCOL", firstSPX_ProtocolLine, this.lineNumber); } //---------------------------------------------------------------- // NMP PIPE ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterNmp_pipe(tnsnamesParser.Nmp_pipeContext ctx) { checkForRedefinition("PIPE", firstNMP_PipeLine, this.lineNumber); } //---------------------------------------------------------------- // NMP SERVER ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterNmp_server(tnsnamesParser.Nmp_serverContext ctx) { checkForRedefinition("SERVER", firstNMP_ServerLine, this.lineNumber); } //---------------------------------------------------------------- // NMP PROTOCOL ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterNmp_nmp(tnsnamesParser.Nmp_nmpContext ctx) { checkForRedefinition("PROTOCOL", firstNMP_ProtocolLine, this.lineNumber); } //---------------------------------------------------------------- // BEQ PROGRAM ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterBeq_program(tnsnamesParser.Beq_programContext ctx) { checkForRedefinition("PROGRAM", firstBEQ_ProgramLine, this.lineNumber); } //---------------------------------------------------------------- // BEQ ARGV0 ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterBeq_argv0(tnsnamesParser.Beq_argv0Context ctx) { checkForRedefinition("ARGV0", firstBEQ_Argv0Line, this.lineNumber); } //---------------------------------------------------------------- // BEQ ARGS ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterBeq_args(tnsnamesParser.Beq_argsContext ctx) { checkForRedefinition("ARGS", firstBEQ_ArgsLine, this.lineNumber); } //---------------------------------------------------------------- // BEQ PROTOCOL ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. However, this parser // rule is called from the BEQ protocol and also from the BEQ ARGS // so we need to find out who the parent rule is before we check. //---------------------------------------------------------------- @Override public void enterBeq_beq(tnsnamesParser.Beq_beqContext ctx) { RuleContext parentCtx = ctx.getParent(); String parentRule = this.ruleNames[parentCtx.getRuleIndex()]; // Check for redefinitions. BEQ. if (parentRule == "beq_parameter") { checkForRedefinition("PROTOCOL", firstBEQ_ProtocolLine, this.lineNumber); } // Check for redefinitions. ARGS. if (parentRule == "bad_address") { checkForRedefinition("PROTOCOL", firstBAD_ProtocolLine, this.lineNumber); } } //---------------------------------------------------------------- // BAD_ADDRESS ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterBad_address(tnsnamesParser.Bad_addressContext ctx) { checkForRedefinition("ADDRESS", firstBAD_AddressLine, this.lineNumber); } //---------------------------------------------------------------- // BAD_LOCAL ENTRY //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterBad_local(tnsnamesParser.Bad_localContext ctx) { checkForRedefinition("LOCAL", firstBAD_LocalLine, this.lineNumber); } //---------------------------------------------------------------- // PORT (number) //---------------------------------------------------------------- // Check the port numbers are 1024 <= n <= 65535 //---------------------------------------------------------------- @Override public void enterPort(tnsnamesParser.PortContext ctx) { int portNumber = Integer.parseInt(ctx.INT().getText()); // Below 1024 is suspicious. Requires root privileges to open. if (portNumber < 1024) { doWarning("Port number, " + portNumber + " < 1024. May be invalid."); } // Above 65535 is out of range. if (portNumber > 65535) { doError("Port number " + portNumber + ". Out of range 1024 - 65535."); } } //---------------------------------------------------------------- // HOST //---------------------------------------------------------------- // If this is an IP address type host, we process it. Named hosts // cannot be checked at present - we might be able to ping them. // // There must be 4 "dotted quads" in an IP address (IPv4) so check // that this is so. // // Assuming there are 4, the first is 1 <= n <= 254. The remainder // are 0 <= n <= 254. //---------------------------------------------------------------- @Override public void enterHost(tnsnamesParser.HostContext ctx) { // It is possible that we don't have a host IP. if (ctx.IP() == null) { return; } String ipAddress = ctx.IP().getText(); if (ipAddress == null) { return; } // split() takes a regex, hence all the escaping! // And I have to escape the escape as well! String[] dotQuads = ipAddress.split("\\."); // We should have got 1.2.3.4 or similar. if (dotQuads.length != 4) { doError("IP Address '" + ipAddress + "' malformed. Should be aa.bb.cc.dd"); return; } int minIP = 1; // Minimum allowed for the first quad. for (int eachInt = 0; eachInt < 4; eachInt++) { int dotQuad = 0; // Temp working value. String thisQuad = dotQuads[eachInt].toLowerCase(); // We don't worry about non-integers here because the // lexer rule for an IP says QUAD.QUAD.QUAD.QUAD so it cannot fail. :-) // Famous last words perhaps ...... but QUADs are decimal, hex or octal numbers. // UPDATE: The RFC for an IPv4 address says that there can be // Octal or Hex numbers in the quads. // Decimals = 0-254; // Octal = 000-376; // Hexadecimal = 0x00 - 0xfe (upper or lower case of course) // There goes the grammar again! :-( int quadLen = thisQuad.length(); // If the first character is not a zero, it's a full decimal. if (thisQuad.charAt(0) != '0') { // If the first character is not a zero, it's a full decimal. dotQuad = Integer.parseInt(thisQuad); } else { // If the second character is an 'x' then it's a Hex integer. // So the length has to be at least 3 for "0x0", for eg. // Did I mention, I have to strip off the '0x' at the start. Sigh. if (quadLen > 2 && thisQuad.charAt(1) == 'x') { dotQuad = Integer.parseInt(thisQuad.substring(2), 16); } else { // It cannot be anything but an Octal integer from the leading zero. // UNLESS of course, someone used leading zeros on a decimal like "029". try { dotQuad = Integer.parseInt(thisQuad, 8); } catch (NumberFormatException x) { // Users eh? Who'd have them! Don't they know that // leading zeros mean OCTAL! Try to ping 012.02.012.08! dotQuad = Integer.parseInt(thisQuad); } } } if (eachInt == 1) { // Adjust for 1, 2, and 3 which can be zero. minIP = 0; } if (dotQuad < minIP || dotQuad > 254) { doError("dotQuad '" + dotQuads[eachInt] + "' in '" + ipAddress + "' out of range " + minIP + " - 254."); } } } //---------------------------------------------------------------- // SDU //---------------------------------------------------------------- // Check the SDU value is 512 <= n <= 65535. // Default is 8192. //---------------------------------------------------------------- @Override public void enterD_sdu(tnsnamesParser.D_sduContext ctx) { // If this is the first SDU, firstSduLine will be zero, otherwise // it's a redefinition. checkForRedefinition("SDU", firstSduLine, this.lineNumber); // What is the SDU parameter value? int sduValue = Integer.parseInt(ctx.INT().getText()); // Below 512 is invalid, as is > 65535. if (sduValue < 512 || sduValue > 65535) { doError("SDU value " + sduValue + ". Out of range 512 - 65535."); } // 8192 is the default setting. if (sduValue == 8192) { doInfo("SDU value " + sduValue + ". This is the default setting."); } } //---------------------------------------------------------------- // LOAD_BALANCE ENTRY on DESCRIPTION_LIST, DESCRIPTION and // ADDRESS_LIST. //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterAl_load_balance(tnsnamesParser.Al_load_balanceContext ctx) { // Who is my parent? We need this to prevent errors when, for example, // an ADDRESS_LIST FAIL_OVER parameter is flagged as redefining a parent // DESCRIPTION FAIL_OVER parameter, which is not actually the case. RuleContext parentCtx = ctx.getParent(); // We get the rule name, from the grammar, for the parent of this // rule. In lower case as we are dealing with parser rules. String parentRule = this.ruleNames[parentCtx.getRuleIndex()]; // Check for redefinitions, DESCRIPTION_LIST. if (parentRule == "dl_parameter") { checkForRedefinition("LOAD_BALANCE", firstDL_LoadBalanceLine, this.lineNumber); } // Check for redefinitions, DESCRIPTION. if (parentRule == "d_parameter") { checkForRedefinition("LOAD_BALANCE", firstLoadBalanceLine, this.lineNumber); } // Check for redefinitions, ADDRESS_LIST. if (parentRule == "al_parameter") { checkForRedefinition("LOAD_BALANCE", firstAL_LoadBalanceLine, this.lineNumber); } } //---------------------------------------------------------------- // ENABLE ENTRY (on DESCRIPTION) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_enable(tnsnamesParser.D_enableContext ctx) { checkForRedefinition("ENABLE", firstEnableLine, this.lineNumber); } //---------------------------------------------------------------- // FAILOVER ENTRY on DESCRIPTION_LIST, DESCRIPTION or ADDRESS_LIST. //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterAl_failover(tnsnamesParser.Al_failoverContext ctx) { // Who is my parent? We need this top prevent errors when, for example, // an ADDRESS_LIST FAIL_OVER parameter is flagged as redefining a parent // DESCRIPTION FAIL_OVER parameter, which is not actually the case. RuleContext parentCtx = ctx.getParent(); // We get the rule name, from the grammar, for the parent of this // rule. In lower case as we are dealing with parser rules. String parentRule = this.ruleNames[parentCtx.getRuleIndex()]; // Check for redefinitions, DESCRIPTION_LIST. if (parentRule == "dl_parameter") { checkForRedefinition("FAILOVER", firstDL_FailOverLine, this.lineNumber); } // Check for redefinitions, DESCRIPTION. if (parentRule == "d_parameter") { checkForRedefinition("FAILOVER", firstFailOverLine, this.lineNumber); } // Check for redefinitions, ADDRESS_LIST. if (parentRule == "al_parameter") { checkForRedefinition("FAILOVER", firstAL_FailOverLine, this.lineNumber); } } //---------------------------------------------------------------- // RECV_BUF ENTRY (on DESCRIPTION or ADDRESS) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_recv_buf(tnsnamesParser.D_recv_bufContext ctx) { // Who is my parent rule? RuleContext parentCtx = ctx.getParent(); String parentRule = this.ruleNames[parentCtx.getRuleIndex()]; // Check for redefinitions, DESCRIPTION. if (parentRule == "d_parameter") { checkForRedefinition("RECV_BUF_SIZE", firstRecvBufLine, this.lineNumber); } // Check for redefinitions, DESCRIPTION. if (parentRule == "a_parameter") { checkForRedefinition("RECV_BUF_SIZE", firstA_RecvBufLine, this.lineNumber); } } //---------------------------------------------------------------- // SEND_BUF ENTRY (on DESCRIPTION or ADDRESS) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_send_buf(tnsnamesParser.D_send_bufContext ctx) { // Who is my parent rule? RuleContext parentCtx = ctx.getParent(); String parentRule = this.ruleNames[parentCtx.getRuleIndex()]; // Check for redefinitions, DESCRIPTION. if (parentRule == "d_parameter") { checkForRedefinition("SEND_BUF_SIZE", firstSendBufLine, this.lineNumber); } // Check for redefinitions, DESCRIPTION. if (parentRule == "a_parameter") { checkForRedefinition("SEND_BUF_SIZE", firstA_SendBufLine, this.lineNumber); } } //---------------------------------------------------------------- // SOURCE_ROUTE ENTRY on DESCRIPTION_LIST, DESCRIPTION or // ADDRESS_LIST. //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterAl_source_route(tnsnamesParser.Al_source_routeContext ctx) { // Who is my parent? RuleContext parentCtx = ctx.getParent(); // We get the rule name, from the grammar, for the parent of this // rule. In lower case as we are dealing with parser rules. String parentRule = this.ruleNames[parentCtx.getRuleIndex()]; // Check for redefinitions, DESCRIPTION_LIST. if (parentRule == "dl_parameter") { checkForRedefinition("SOURCE_ROUTE", firstDL_SourceRouteLine, this.lineNumber); } // Check for redefinitions, DESCRIPTION. if (parentRule == "d_parameter") { checkForRedefinition("SOURCE_ROUTE", firstSourceRouteLine, this.lineNumber); } // Check for redefinitions, ADDRESS_LIST. if (parentRule == "al_parameter") { checkForRedefinition("SOURCE_ROUTE", firstAL_SourceRouteLine, this.lineNumber); } } //---------------------------------------------------------------- // SERVICE_TYPE ENTRY (on DESCRIPTION) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_service_type(tnsnamesParser.D_service_typeContext ctx) { checkForRedefinition("SOURCE_ROUTE", firstServiceTypeLine, this.lineNumber); } //---------------------------------------------------------------- // SECURITY ENTRY (on DESCRIPTION) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_security(tnsnamesParser.D_securityContext ctx) { // If this is the first SECURITY, firstSecurityLine will be zero, otherwise // it's a redefinition. checkForRedefinition("SECURITY", firstSecurityLine, this.lineNumber); } //---------------------------------------------------------------- // CONNECT_TIMEOUT ENTRY (on DESCRIPTION) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_conn_timeout(tnsnamesParser.D_conn_timeoutContext ctx) { // If this is the first CONNECT_TIMEOUT, firstConnTimeoutLine will be zero, otherwise // it's a redefinition. checkForRedefinition("CONNECT_TIMEOUT", firstConnTimeoutLine, this.lineNumber); } //---------------------------------------------------------------- // RETRY_COUNT ENTRY (on DESCRIPTION) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_retry_count(tnsnamesParser.D_retry_countContext ctx) { // If this is the first RETRY_COUNT, firstRetryCountLine will be zero, otherwise // it's a redefinition. checkForRedefinition("RETRY_COUNT", firstRetryCountLine, this.lineNumber); } //---------------------------------------------------------------- // TRANSPORT_CONNECT_TIMEOUT ENTRY (on DESCRIPTION) //---------------------------------------------------------------- // Check only for parameter redefinition. //---------------------------------------------------------------- @Override public void enterD_tct(tnsnamesParser.D_tctContext ctx) { // If this is the first TRANSPORT_CONNECT_TIMEOUT, firstTctLine will be zero, otherwise // it's a redefinition. checkForRedefinition("TRANSPORT_CONNECT_TIMEOUT", firstTctLine, this.lineNumber); } //---------------------------------------------------------------- // LSNR_DESCRIPTION ENTRY //---------------------------------------------------------------- // Listener DESCRIPTION entry found. Carry out some validation. //---------------------------------------------------------------- @Override public void enterLsnr_description(tnsnamesParser.Lsnr_descriptionContext ctx) { // Multiple ADDRESSes without an ADDRESS_LIST? int addressCount = ctx.address().size(); if (ctx.address_list() == null && addressCount > 1) { doWarning("Missing ADDRESS_LIST, " + addressCount + " ADDRESS entries found."); } } //---------------------------------------------------------------- // TNSNAMES EXIT //---------------------------------------------------------------- // On exit from the complete tnsnames file, list the included // IFILE filenames for further processing. They are not checked by // this script automatically (yet!) so need to be done manually. //---------------------------------------------------------------- @Override public void exitTnsnames(tnsnamesParser.TnsnamesContext ctx) { // Advise the user of the state of the tnsnames.ora file. System.out.println("\n" + String.format("%-80s", "=").replace(" ", "=")); System.out.println("Parsing Information:"); System.out.println("==================="); System.out.println("INFORMATION : " + totalInfo); System.out.println("PARSER WARNINGS : " + totalWarnings); System.out.println("PARSER ERRORS : " + totalErrors); System.out.println("DUPLICATE ENTRIES: " + totalDuplicates); for (int i = 0; i < totalDuplicates; i++) { System.out.println("\tDuplicate[" + i + "] = '" + duplicateNames.get(i) + "'"); } System.out.println(String.format("%-80s", "=").replace(" ", "=")); // Did we find any IFILE entries? If so, list the files for further analysis. if (ctx.ifile() != null /* && ctx.ifile().size() == 0 */) { System.out.println("\n" + String.format("%-80s", "-").replace(" ", "-")); System.out.println("IFILE List:"); System.out.println(String.format("%-80s", "-").replace(" ", "-")); System.out.println("Please run the tnsnames_checker script on the following files:"); for (int thisIfile = 0; thisIfile < ctx.ifile().size(); thisIfile++) { // Print the filename first...without leading and trailing double quotes. String ifileFilename = ctx.ifile(thisIfile).DQ_STRING().getText().replace("\"", "").trim(); System.out.print("\t" + ifileFilename); // Then attempt to determine if it exists. Not necessarily an error if not. // It fails to find the file if we leave the double quotes present. File inputFile = new File(ifileFilename); if (inputFile.isFile()) { // The file exists on this server/laptop/whatever! System.out.println(" (file exists on this computer.)"); } else { // The file doesn't exist here. We could be running a check // for another server/laptop/etc so it's not a fatal problem. System.out.println(" (file not found on this computer.)"); } } System.out.println("End of IFILE List."); } } }