diff --git a/.travis/create_release.sh b/.travis/create_release.sh index b681e40..739558a 100644 --- a/.travis/create_release.sh +++ b/.travis/create_release.sh @@ -5,6 +5,10 @@ VERSION=`date +%Y%m%d%H%M` mkdir dist mv target/appassembler utPLSQL-cli +# Remove Oracle libraries du to licensing problems +rm utPLSQL-cli/lib/ojdbc8* +rm utPLSQL-cli/lib/orai18n* + zip -r -q dist/utPLSQL-cli-${TRAVIS_BRANCH}-${VERSION}.zip utPLSQL-cli zip -r -q utPLSQL-cli.zip utPLSQL-cli diff --git a/README.md b/README.md index a98c171..973b531 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ You can download development versions on [Bintray](https://bintray.com/viniciusa ## Requirements * [Java SE Runtime Environment 8](http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html) * When using reporters for Sonar or Coveralls client needs to be invoked from project's root directory. +* Due to Oracle license we can't ship the necessary oracle libraries directly with utPLSQL-cli. Please download the libraries directly from oracle website and put the jars into the "lib" folder of your utPLSQL-cli installation + * Oracle JDBC driver: http://www.oracle.com/technetwork/database/features/jdbc/jdbc-ucp-122-3110062.html + * If you are on a 11g database you might need the orai18n library, too: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html ## Compatibility The latest CLI is always compatible with all database frameworks of the same major version. diff --git a/src/main/java/org/utplsql/cli/Cli.java b/src/main/java/org/utplsql/cli/Cli.java index 4ea8652..bdfbac3 100644 --- a/src/main/java/org/utplsql/cli/Cli.java +++ b/src/main/java/org/utplsql/cli/Cli.java @@ -3,6 +3,9 @@ import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; +import org.utplsql.api.exception.DatabaseNotCompatibleException; +import org.utplsql.api.exception.UtPLSQLNotInstalledException; +import org.utplsql.cli.exception.DatabaseConnectionFailed; public class Cli { @@ -34,6 +37,8 @@ public static void main(String[] args) { } else { jc.usage(); } + } catch ( DatabaseNotCompatibleException | UtPLSQLNotInstalledException | DatabaseConnectionFailed e ) { + System.out.println(e.getMessage()); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/org/utplsql/cli/ConnectionInfo.java b/src/main/java/org/utplsql/cli/ConnectionInfo.java index 287f989..4f76f81 100644 --- a/src/main/java/org/utplsql/cli/ConnectionInfo.java +++ b/src/main/java/org/utplsql/cli/ConnectionInfo.java @@ -6,10 +6,14 @@ import java.io.File; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; public class ConnectionInfo { + private String databaseVersion; + static { String oracleHome = System.getenv("ORACLE_HOME"); if (oracleHome != null) { @@ -42,4 +46,40 @@ public ConnectionInfo convert(String s) { } } + public String getOracleDatabaseVersion() throws SQLException + { + try ( Connection conn = getConnection() ) { + return getOracleDatabaseVersion(conn); + } + } + + public String getOracleDatabaseVersion( Connection conn ) throws SQLException + { + if ( databaseVersion == null ) { + databaseVersion = getOracleDatabaseVersionFromConnection( conn ); + } + + return databaseVersion; + } + + /** TODO: Outsource this to Java-API + * + * @param conn + * @return + * @throws SQLException + */ + public static String getOracleDatabaseVersionFromConnection( Connection conn ) throws SQLException { + assert conn != null; + String result = null; + try (PreparedStatement stmt = conn.prepareStatement("select version from product_component_version where product like 'Oracle Database%'")) + { + ResultSet rs = stmt.executeQuery(); + + if ( rs.next() ) + result = rs.getString(1); + } + + return result; + } + } diff --git a/src/main/java/org/utplsql/cli/OracleLibraryChecker.java b/src/main/java/org/utplsql/cli/OracleLibraryChecker.java new file mode 100644 index 0000000..24b02f8 --- /dev/null +++ b/src/main/java/org/utplsql/cli/OracleLibraryChecker.java @@ -0,0 +1,39 @@ +package org.utplsql.cli; + +/** Simple class to check whether needed Oracle libraries are on classpath or not + * + * @author pesse + */ +class OracleLibraryChecker { + + private static boolean classExists( String classFullName ){ + try + { + Class.forName(classFullName); + + return true; + } + catch ( ClassNotFoundException e ) + { + return false; + } + } + + /** Checks if OJDBC library is on the classpath by searching for oracle.jdbc.OracleDriver class + * + * @return true or false + */ + public static boolean checkOjdbcExists() { + return classExists("oracle.jdbc.OracleDriver"); + } + + /** Checks if Orai18n library is on the classpath by searching for oracle.i18n.text.OraCharset + * + * @return true or false + */ + public static boolean checkOrai18nExists() { + return classExists("oracle.i18n.text.OraCharset"); + } + + +} diff --git a/src/main/java/org/utplsql/cli/RunCommand.java b/src/main/java/org/utplsql/cli/RunCommand.java index a1b7035..690a453 100644 --- a/src/main/java/org/utplsql/cli/RunCommand.java +++ b/src/main/java/org/utplsql/cli/RunCommand.java @@ -3,10 +3,13 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import org.utplsql.api.*; +import org.utplsql.api.compatibility.CompatibilityProxy; +import org.utplsql.api.compatibility.OptionalFeatures; import org.utplsql.api.exception.DatabaseNotCompatibleException; import org.utplsql.api.exception.SomeTestsFailedException; import org.utplsql.api.reporter.Reporter; import org.utplsql.api.reporter.ReporterFactory; +import org.utplsql.cli.exception.DatabaseConnectionFailed; import java.io.File; import java.io.FileNotFoundException; @@ -80,6 +83,8 @@ public class RunCommand { "most actual. Use this if you use CLI with a development version of utPLSQL-framework") private boolean skipCompatibilityCheck = false; + private CompatibilityProxy compatibilityProxy; + public ConnectionInfo getConnectionInfo() { return connectionInfoList.get(0); } @@ -89,6 +94,9 @@ public List getTestPaths() { } public int run() throws Exception { + + RunCommandChecker.checkOracleJDBCExists(); + final ConnectionInfo ci = getConnectionInfo(); final List reporterList; @@ -107,14 +115,27 @@ public int run() throws Exception { // Do the reporters initialization, so we can use the id to run and gather results. try (Connection conn = ci.getConnection()) { + // Check if orai18n exists if database version is 11g + RunCommandChecker.checkOracleI18nExists(ci.getOracleDatabaseVersion(conn)); + // First of all do a compatibility check and fail-fast - checkFrameworkCompatibility(conn); + compatibilityProxy = checkFrameworkCompatibility(conn); reporterList = initReporters(conn, reporterOptionsList); } catch (SQLException e) { - System.out.println(e.getMessage()); - return Cli.DEFAULT_ERROR_CODE; + if ( e.getErrorCode() == 1017 || e.getErrorCode() == 12514 ) { + throw new DatabaseConnectionFailed(e); + } + else { + throw e; + } + } + + // Output a message if --failureExitCode is set but database framework is not capable of + String msg = RunCommandChecker.getCheckFailOnErrorMessage(failureExitCode, compatibilityProxy.getDatabaseVersion()); + if ( msg != null ) { + System.out.println(msg); } ExecutorService executorService = Executors.newFixedThreadPool(1 + reporterList.size()); @@ -256,21 +277,19 @@ public List getReporterOptionsList() { * @param conn Active Connection * @throws SQLException */ - private void checkFrameworkCompatibility(Connection conn) throws SQLException { + private CompatibilityProxy checkFrameworkCompatibility(Connection conn) throws SQLException { - if ( !skipCompatibilityCheck ) { - try { - DBHelper.failOnVersionCompatibilityCheckFailed(conn); - } catch (DatabaseNotCompatibleException e) { - System.out.println(e.getMessage()); + CompatibilityProxy proxy = new CompatibilityProxy(conn, skipCompatibilityCheck); - throw e; - } + if ( !skipCompatibilityCheck ) { + proxy.failOnNotCompatible(); } else { System.out.println("Skipping Compatibility check with framework version, expecting the latest version " + "to be installed in database"); } + + return proxy; } public FileMapperOptions getMapperOptions(List mappingParams, List filePaths) { @@ -320,4 +339,14 @@ public FileMapperOptions getMapperOptions(List mappingParams, List