/* * [CrossCheckProject.java] * * Summary: cross check different files files related to the project. * * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2007-05-12 initial version. */ package com.mindprod.zzz; import com.mindprod.common18.Build; import com.mindprod.common18.EIO; import com.mindprod.common18.ST; import com.mindprod.fastcat.FastCat; import com.mindprod.hunkio.HunkIO; import com.mindprod.prices.AppCat; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Enumeration; import java.util.HashSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import static com.mindprod.zzz.CompilerCat.JAVA; import static com.mindprod.zzz.PADType.PAD40; import static java.lang.System.*; /** * cross check different files files related to the project. *

* Version History: * 1.0 2007-05-12 - initial version. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2007-05-12 initial version. * @since 2007-05-12 */ class CrossCheckProject extends ProjectInfo { // declarations /** * max allowable error in Pad file size in K before reporting the discrepancy. * Asked to make manual correction on AppVisor if outside bounds. */ private static final double ALLOWABLE_FILESIZE_SLOP_PERCENT = 4.0d; /** * Regex to look for Windows EOL sequence */ private static final String A_EOL = "\\r\\n"; /** * regex fragment to match a = */ private static final String A_EQUAL = "="; /** * regex fragment to match a " */ private static final String A_QUOTE = "\""; /** * regex fragment to look for some spaces */ private static final String A_SPACES = "\\s++"; /** * regex fragment to look for FIND_CMP_APPLET = Pattern.compile( A_START_HTML_COMMENT + A_SPACES + "macro" + A_SPACES + "CMPApplet" + A_SPACES + "(" + A_VERSION // jdk version + ")" + A_SPACES + "(" + "\\w+" // package without com.mindprod + ")" + A_SPACES + "(" + "\\w+" // program + ")" + A_SPACES + "(" + "\\d+" // width + ")" + A_SPACES + "(" + "\\d+" // height + ")" ); FIND_JDK_REQUIRED_COMMENT = Pattern.compile( "Requires:" + A_SPACES + "JDK" + A_SPACES + "(" + A_VERSION + ")\\+" ); // macro NeedsJava javaVersion(e.g. 1.1) (signed/unsigned) (jni/nojni) // (Applet/hybrid/webstart) (ClassName) (Desc) [why signed]"; FIND_NEEDSJAVA_PARMS = Pattern.compile( A_START_HTML_COMMENT + A_SPACES + "macro" + A_SPACES + "NeedsJava" + A_SPACES + "(" + A_VERSION // 1.1 + ")" + A_SPACES + "(" + "\\w+" // signed/unsigned + ")" + A_SPACES + "(" + "\\w+" // jni/nojni + ")" + A_SPACES + "(" + "\\w+" // Applet/hybrid/webstart any case + ")" + A_SPACES + "(" + "\\w+" // className + ")" + A_SPACES ); FIND_RELEASE_DATE = Pattern.compile( "RELEASE_DATE" + A_SPACES + A_EQUAL + A_SPACES + A_QUOTE + A_YYYYMMDD + A_QUOTE ); FIND_VERSION_HISTORY = Pattern.compile( A_EOL + A_EOL + "\\s?" + "(" + A_VERSION + ") (" + A_YYYYMMDD + ")" + " " ); FIND_VERSION_STRING_IN_JAVA = Pattern.compile( "VERSION_STRING" + A_SPACES + A_EQUAL + A_SPACES + A_QUOTE + "(" + A_VERSION + ")" + A_QUOTE ); FIND_APPLET_WIDTH = Pattern.compile( "APPLET_WIDTH = (\\d+);" ); FIND_APPLET_HEIGHT = Pattern.compile( "APPLET_HEIGHT = (\\d+);" ); } // methods /** * Copy constructor * * @param pi Copy constructor to extend class */ @SuppressWarnings( { "SameParameterValue" } ) CrossCheckProject( ProjectInfo pi ) { super( pi ); } /** * makes sure @version is correct * * @param jdkVersionString what to expect for JDK value * @param mainClass main class name without .class * @param versionString what to expert for version in #version * @param program java source code */ private static void checkAtVersion( String jdkVersionString, String mainClass, String versionString, String program ) { Matcher m = FIND_AT_VERSION.matcher( program ); int found = 0; while ( m.find() ) { found++; String match = m.group( 1 ); if ( !match.equals( versionString ) ) { final FastCat sb = new FastCat( 8 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " mismatched @version in Intellij Java source: " ); sb.append( match ); sb.append( " should match stomp " ); sb.append( versionString ); err.println( sb.toString() ); } } switch ( found ) { case 0: { final FastCat sb = new FastCat( 6 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " missing @version in Intellij Java source " ); sb.append( versionString ); err.println( sb.toString() ); } break; case 1: // all ok break; default: { final FastCat sb = new FastCat( 6 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " too many @versions in Intellij Java source " ); sb.append( found ); err.println( sb.toString() ); } break; } }// /method /** * make sure JDK_REQUIRED in CMPApplet macros in corresponding Applet html is correct * * @param projectLower name of project in lower case, without lead com.mindprod * @param mainClass main class name without .class * @param jdkVersionString what to expect for JDK value * @param appletHtml applet html * @param appletHtmlFile file where html text came from */ private static void checkCMPApplet( final String projectLower, final String mainClass, final String jdkVersionString, final String appletHtml, final File appletHtmlFile ) { final Matcher a = FIND_CMP_APPLET.matcher( appletHtml ); int found = 0; while ( a.find() ) { found++; if ( !( a.groupCount() == 5 && a.group( 1 ).equals( jdkVersionString ) && a.group( 2 ).equals( projectLower ) && a.group( 3 ).equals( mainClass ) && a.group( 4 ).equals( appletWidth ) && a.group( 5 ).equals( appletHeight ) ) ) { final FastCat sb = new FastCat( 22 ); sb.append( "In file " ); sb.append( EIO.getCanOrAbsPath( appletHtmlFile ) ); sb.append( " malformed Applet is: " ); sb.append( a.group( 1 ) ); sb.append( " " ); sb.append( a.group( 2 ) ); sb.append( " " ); sb.append( a.group( 3 ) ); sb.append( " " ); sb.append( a.group( 4 ) ); sb.append( " " ); sb.append( a.group( 5 ) ); sb.append( "\nShould be: CMPApplet " ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( projectLower ); sb.append( " " ); sb.append( mainClass ); sb.append( " " ); sb.append( appletWidth ); sb.append( " " ); sb.append( appletHeight ); err.println( sb.toString() ); } switch ( found ) { case 0: { final FastCat sb = new FastCat( 13 ); sb.append( "In file " ); sb.append( EIO.getCanOrAbsPath( appletHtmlFile ) ); sb.append( " CMPApplet missing. Should be: CMPApplet" ); sb.append( " " ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( projectLower ); sb.append( " " ); sb.append( mainClass ); sb.append( " " ); sb.append( appletWidth ); sb.append( " " ); sb.append( appletHeight ); err.println( sb.toString() ); err.println( appletHtml.substring( 0, 100 ) ); } break; case 1: // all ok break; default: { final FastCat sb = new FastCat( 12 ); sb.append( "In file " ); sb.append( EIO.getCanOrAbsPath( appletHtmlFile ) ); sb.append( "Too many CMPApplet macros. Should just be one CMPApplet " ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( projectLower ); sb.append( " " ); sb.append( mainClass ); sb.append( " " ); sb.append( appletWidth ); sb.append( " " ); sb.append( appletHeight ); err.println( sb.toString() ); } break; } // end switch } // end while }// /method /** * make sure @copyright is correct * * @param mainClass main class name without .class * @param jdkVersionString what to expect for JDK value * @param program java source code * @param forgiveExcess true if we should forgive excess copyright lines. * * @return firstCopyrightYear as int */ private static int checkCopyright( final String mainClass, final String jdkVersionString, final String program, final boolean forgiveExcess ) { final int firstCopyrightYear; final Matcher mf = FIND_FIRST_COPYRIGHT_YEAR.matcher( program ); if ( mf.find() ) { firstCopyrightYear = Integer.parseInt( mf.group( 1 ) ); } else { firstCopyrightYear = Build.THIS_COPYRIGHT_YEAR; final FastCat sb = new FastCat( 5 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " missing FIRST_COPYRIGHT_YEAR " + "in Intellij source " ); err.println( sb.toString() ); } final Matcher m = FIND_COPYRIGHT.matcher( program ); int found = 0; while ( m.find() ) { if ( firstCopyrightYear != Integer.parseInt( m.group( 1 ) ) ) { final FastCat sb = new FastCat( 5 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " inconsistent Copyright: (c) in Intellij source " ); err.println( sb.toString() ); } found++; } switch ( found ) { case 0: { final FastCat sb = new FastCat( 5 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " missing Copyright: (c) in Intellij source " ); err.println( sb.toString() ); } break; case 2: // all ok, should find one in packaged comment and one in embedded copyright. break; case 1: default: { if ( !forgiveExcess ) { final FastCat sb = new FastCat( 10 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " should have two lines containing Copyright: (c) in Intellij Java source. Found " ); sb.append( found ); err.println( sb.toString() ); } } break; } // end switch return firstCopyrightYear; }// /method /** * make sure JDK_REQUIRED in comment is correct * * @param mainClass main class name without .class * @param jdkVersionString what to expect for JDK value * @param program java source code */ private static void checkJDKRequiredInComment( String mainClass, String jdkVersionString, String program ) { Matcher m = FIND_JDK_REQUIRED_COMMENT.matcher( program ); int found = 0; while ( m.find() ) { found++; String match = m.group( 1 ); if ( !match.equals( jdkVersionString ) ) { { final FastCat sb = new FastCat( 8 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " mismatched 'Requires: JDK' comment in Intellij Java source: " ); sb.append( match ); sb.append( " should match stomp: " ); sb.append( jdkVersionString ); err.println( sb.toString() ); } } } switch ( found ) { case 0: { final FastCat sb = new FastCat( 6 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " missing 'Requires: JDK' comment in Intellij Java source " ); sb.append( jdkVersionString ); err.println( sb.toString() ); } break; case 1: // all ok break; default: { final FastCat sb = new FastCat( 6 ); sb.append( "J" ); sb.append( jdkVersionString ); sb.append( " " ); sb.append( mainClass ); sb.append( " too many 'Requires: JDK' comments in Intellij Java source " ); sb.append( found ); err.println( sb.toString() ); } break; } }// /method /** * make sure JDK_REQUIRED in NeedsJava macros in corresponding Applet html is correct * * @param appletHtml applet html * @param appletHtmlFile file where html text came from * @param expectedMainClass main class name without .class * @param expectedJDKVersionString what to expect for JDK value * @param expectedAppcat applet category to expect in NeedsJava macro * @param expectedSigning signed/unsigned * @param expectedJNI jni/nojni */ private static void checkJDKRequiredInNeedsJava( final String appletHtml, final File appletHtmlFile, final String expectedMainClass, final String expectedJDKVersionString, final String expectedAppcat, final String expectedSigning, final String expectedJNI ) { Matcher m = FIND_NEEDSJAVA_PARMS.matcher( appletHtml ); int found = 0; while ( m.find() ) { found++; String match = m.group( 1 ); if ( match.equals( expectedJDKVersionString ) ) { // macro NeedsJava javaVersion(e.g. 1.1) (signed/unsigned) (jni/nojni) // (Applet/hybrid/webstart) (ClassName) (Desc) [why signed; if ( !( expectedSigning.equals( m.group( 2 ) ) && expectedJNI.equals( m.group( 3 ) ) && expectedAppcat.equals( m.group( 4 ).toLowerCase() ) && expectedMainClass.equals( m.group( 5 ) ) ) ) { final FastCat sb = new FastCat( 17 ); sb.append( "In file " ); sb.append( EIO.getCanOrAbsPath( appletHtmlFile ) ); sb.append( " " ); sb.append( expectedMainClass ); sb.append( " inconsistent NeedsJava macro in html\n Is: " ); sb.append( m.group( 0 ) ); sb.append( "\nExpected: