diff --git a/android/CouchbaseLite/build.gradle b/android/CouchbaseLite/build.gradle index abea78278..5e87e9152 100644 --- a/android/CouchbaseLite/build.gradle +++ b/android/CouchbaseLite/build.gradle @@ -92,6 +92,12 @@ android { } } } + + compileOptions { + targetCompatibility 1.8 + sourceCompatibility 1.8 + } + buildTypes { release { minifyEnabled false @@ -442,5 +448,5 @@ task smoketest(dependsOn: ['checkstyle', 'lint', 'findbugsHtml', 'pmd', 'testDeb task checkLocal(dependsOn: ['checkstyle', 'lint', 'findbugsHtml', 'pmd', 'testDebugUnitTest', 'connectedDebugAndroidTest']) -task buildJenkins(dependsOn: ['checkstyle', 'lint', 'findbugsXml', 'pmd', 'check', 'connectedAndroidTest']) +task buildCI(dependsOn: ['checkstyle', 'lint', 'findbugsXml', 'pmd', 'check', 'connectedAndroidTest']) diff --git a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/BaseTest.java b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/BaseTest.java index 1db4eb164..5473796d7 100644 --- a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/BaseTest.java +++ b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/BaseTest.java @@ -18,21 +18,9 @@ package com.couchbase.lite; import android.content.Context; +import android.content.res.AssetManager; import android.support.test.InstrumentationRegistry; -import com.couchbase.lite.internal.support.Log; -import com.couchbase.lite.internal.utils.ExecutorUtils; -import com.couchbase.lite.internal.utils.JsonUtils; -import com.couchbase.lite.utils.Config; -import com.couchbase.lite.utils.FileUtils; -import com.couchbase.lite.internal.core.C4Constants; - -import org.json.JSONObject; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.rules.ExpectedException; - import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -45,26 +33,36 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import static com.couchbase.lite.utils.Config.EE_TEST_PROPERTIES_FILE; -import static com.couchbase.lite.utils.Config.TEST_PROPERTIES_FILE; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.ExpectedException; + +import com.couchbase.lite.internal.core.C4Constants; +import com.couchbase.lite.internal.utils.ExecutorUtils; +import com.couchbase.lite.internal.utils.JsonUtils; +import com.couchbase.lite.utils.Config; +import com.couchbase.lite.utils.FileUtils; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; + public class BaseTest implements C4Constants, CBLError.Domain, CBLError.Code { public static final String TAG = "Test"; protected final static String kDatabaseName = "testdb"; protected Config config; - protected Context context; private File dir = null; protected Database db = null; ExecutorService executor = null; @Rule - public ExpectedException thrown = ExpectedException.none(); + public final ExpectedException thrown = ExpectedException.none(); protected File getDir() { return dir; @@ -77,8 +75,9 @@ protected void setDir(File dir) { // https://stackoverflow.com/questions/2799097/how-can-i-detect-when-an-android-application-is-running-in-the-emulator?noredirect=1&lq=1 private static String getSystemProperty(String name) throws Exception { - Class systemPropertyClazz = Class.forName("android.os.SystemProperties"); - return (String) systemPropertyClazz.getMethod("get", new Class[]{String.class}).invoke(systemPropertyClazz, new Object[]{name}); + Class systemPropertyClazz = Class.forName("android.os.SystemProperties"); + return (String) systemPropertyClazz + .getMethod("get", new Class[] {String.class}).invoke(systemPropertyClazz, new Object[] {name}); } protected static boolean isEmulator() { @@ -87,7 +86,8 @@ protected static boolean isEmulator() { boolean emu = getSystemProperty("ro.kernel.qemu").length() > 0; boolean sdk = getSystemProperty("ro.product.model").equals("sdk"); return goldfish || emu || sdk; - } catch (Exception e) { + } + catch (Exception e) { return false; } } @@ -101,14 +101,17 @@ protected static boolean isARM() { public void setUp() throws Exception { executor = Executors.newSingleThreadExecutor(); - context = InstrumentationRegistry.getTargetContext(); + final Context ctxt = InstrumentationRegistry.getTargetContext(); + + CouchbaseLite.init(ctxt); try { config = new Config(openTestPropertiesFile()); - } catch (IOException e) { + } + catch (IOException e) { fail("Failed to load test.properties"); } - setDir(new File(context.getFilesDir(), "CouchbaseLiteTest")); + setDir(new File(ctxt.getFilesDir(), "CouchbaseLiteTest")); // database exist, delete it deleteDatabase(kDatabaseName); @@ -120,10 +123,12 @@ public void setUp() throws Exception { } private InputStream openTestPropertiesFile() throws IOException { + final AssetManager assets = CouchbaseLite.getContext().getAssets(); try { - return context.getAssets().open(EE_TEST_PROPERTIES_FILE); - } catch (IOException e) { - return context.getAssets().open(TEST_PROPERTIES_FILE); + return assets.open(Config.EE_TEST_PROPERTIES_FILE); + } + catch (IOException e) { + return assets.open(Config.TEST_PROPERTIES_FILE); } } @@ -142,8 +147,7 @@ public void tearDown() throws Exception { } protected void deleteDatabase(String dbName) throws CouchbaseLiteException { - if (config != null && !config.deleteDatabaseInTearDown()) - return; + if (config != null && !config.deleteDatabaseInTearDown()) { return; } // database exist, delete it if (Database.exists(dbName, getDir())) { @@ -153,13 +157,16 @@ protected void deleteDatabase(String dbName) throws CouchbaseLiteException { try { Database.delete(dbName, getDir()); break; - } catch (CouchbaseLiteException ex) { + } + catch (CouchbaseLiteException ex) { if (ex.getCode() == CBLErrorBusy) { try { Thread.sleep(500); - } catch (Exception e) { } - } else { + catch (Exception e) { + } + } + else { throw ex; } } @@ -168,7 +175,7 @@ protected void deleteDatabase(String dbName) throws CouchbaseLiteException { } protected Database open(String name) throws CouchbaseLiteException { - DatabaseConfiguration config = new DatabaseConfiguration(this.context); + DatabaseConfiguration config = new DatabaseConfiguration(); config.setDirectory(dir.getAbsolutePath()); return new Database(name, config); } @@ -209,7 +216,7 @@ protected void loadJSONResource(String name) throws Exception { String line; int n = 0; while ((line = reader.readLine()) != null) { - if (line.trim().isEmpty()) continue; + if (line.trim().isEmpty()) { continue; } n += 1; JSONObject json = new JSONObject(line); Map props = JsonUtils.fromJson(json); @@ -286,7 +293,8 @@ public void run() { String docID; try { docID = createDocNumbered(i, to); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { throw new RuntimeException(e); } numbers.add(db.getDocument(docID).toMap()); @@ -337,14 +345,15 @@ protected static void expectError(String domain, int code, Execution execution) try { execution.run(); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(domain, e.getDomain()); assertEquals(code, e.getCode()); } } protected static void log(LogLevel level, String message) { - switch(level) { + switch (level) { case DEBUG: android.util.Log.d("CouchbaseLite/" + TAG, message); break; diff --git a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/DatabaseTest.java b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/DatabaseTest.java index 940c86279..2f4fc8da5 100644 --- a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/DatabaseTest.java +++ b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/DatabaseTest.java @@ -19,12 +19,6 @@ import android.os.Build; -import com.couchbase.lite.internal.support.Log; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -33,6 +27,10 @@ import java.util.Locale; import java.util.Map; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -40,6 +38,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; + public class DatabaseTest extends BaseTest { final static String kDatabaseTestBlob = "i'm blob"; @@ -53,13 +52,12 @@ private Database openDatabase(String dbName) throws CouchbaseLiteException { } private Database openDatabase(String dbName, boolean countCheck) throws CouchbaseLiteException { - DatabaseConfiguration config = new DatabaseConfiguration(this.context); + DatabaseConfiguration config = new DatabaseConfiguration(); config.setDirectory(getDir().getAbsolutePath()); Database db = new Database(dbName, config); assertEquals(dbName, db.getName()); assertTrue(new File(db.getPath()).getAbsolutePath().endsWith(".cblite2")); - if (countCheck) - assertEquals(0, db.getCount()); + if (countCheck) { assertEquals(0, db.getCount()); } return db; } @@ -67,12 +65,10 @@ private Database openDatabase(String dbName, boolean countCheck) throws Couchbas void deleteDatabase(Database db) throws CouchbaseLiteException { File path = db.getPath() != null ? new File(db.getPath()) : null; // if path is null, db is already closed - if (path != null) - assertTrue(path.exists()); + if (path != null) { assertTrue(path.exists()); } db.delete(); // if path is null, db is already closed before db.delete() - if (path != null) - assertFalse(path.exists()); + if (path != null) { assertFalse(path.exists()); } } // helper methods to verify getDoc @@ -146,53 +142,56 @@ public void tearDown() throws Exception { @Test public void testCreateConfiguration() { // Default: - DatabaseConfiguration config1 = new DatabaseConfiguration(this.context); + DatabaseConfiguration config1 = new DatabaseConfiguration(); config1.setDirectory("/tmp"); assertNotNull(config1.getDirectory()); assertTrue(config1.getDirectory().length() > 0); // Custom - DatabaseConfiguration config2 = new DatabaseConfiguration(this.context); + DatabaseConfiguration config2 = new DatabaseConfiguration(); config2.setDirectory("/tmp/mydb"); assertEquals("/tmp/mydb", config2.getDirectory()); } @Test public void testGetSetConfiguration() throws CouchbaseLiteException { - DatabaseConfiguration config = new DatabaseConfiguration(this.context); + DatabaseConfiguration config = new DatabaseConfiguration(); config.setDirectory(this.db.getConfig().getDirectory()); Database db = new Database("db", config); try { assertNotNull(db.getConfig()); assertFalse(db.getConfig() == config); assertEquals(db.getConfig().getDirectory(), config.getDirectory()); - } finally { + } + finally { db.delete(); } } @Test public void testConfigurationIsCopiedWhenGetSet() throws CouchbaseLiteException { - DatabaseConfiguration config = new DatabaseConfiguration(this.context); + DatabaseConfiguration config = new DatabaseConfiguration(); config.setDirectory(this.db.getConfig().getDirectory()); Database db = new Database("db", config); try { assertNotNull(db.getConfig()); assertTrue(db.getConfig() != config); - } finally { + } + finally { db.delete(); } } @Test public void testDatabaseConfigurationWithAndroidContect() throws CouchbaseLiteException { - DatabaseConfiguration config = new DatabaseConfiguration(this.context); - assertEquals(config.getDirectory(), context.getFilesDir().getAbsolutePath()); + DatabaseConfiguration config = new DatabaseConfiguration(); + assertEquals(config.getDirectory(), CouchbaseLite.getContext().getFilesDir().getAbsolutePath()); Database db = new Database("db", config); try { - String expectedPath = context.getFilesDir().getAbsolutePath(); + String expectedPath = CouchbaseLite.getContext().getFilesDir().getAbsolutePath(); assertTrue(new File(db.getPath()).getAbsolutePath().contains(expectedPath)); - } finally { + } + finally { db.delete(); } } @@ -208,7 +207,8 @@ public void testCreate() throws CouchbaseLiteException { try { assertNotNull(db); assertEquals(0, db.getCount()); - } finally { + } + finally { // delete database deleteDatabase(db); } @@ -217,9 +217,10 @@ public void testCreate() throws CouchbaseLiteException { @Test public void testCreateWithDefaultConfiguration() throws CouchbaseLiteException { - Database db = new Database("db", new DatabaseConfiguration(this.context)); + Database db = new Database("db", new DatabaseConfiguration()); try { - } finally { + } + finally { // delete database deleteDatabase(db); } @@ -231,7 +232,8 @@ public void testCreateWithSpecialCharacterDBNames() throws CouchbaseLiteExceptio try { assertNotNull(db); assertEquals(0, db.getCount()); - } finally { + } + finally { // delete database deleteDatabase(db); } @@ -242,9 +244,11 @@ public void testCreateWithEmptyDBNames() { try { Database db = openDatabase(""); fail(); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // NOTE: CBL Android's Database constructor does not work without specified directory. - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { e.printStackTrace(); } } @@ -254,17 +258,18 @@ public void testCreateWithCustomDirectory() throws CouchbaseLiteException { String dbName = "db"; - File dir = new File(context.getFilesDir(), "CouchbaseLite"); + File dir = new File(CouchbaseLite.getContext().getFilesDir(), "CouchbaseLite"); try { Database.delete(dbName, dir); - } catch (CouchbaseLiteException ex) { + } + catch (CouchbaseLiteException ex) { } assertFalse(Database.exists(dbName, dir)); // create db with custom directory - DatabaseConfiguration config = new DatabaseConfiguration(this.context) - .setDirectory(dir.getAbsolutePath()); + DatabaseConfiguration config = new DatabaseConfiguration() + .setDirectory(dir.getAbsolutePath()); Database db = new Database(dbName, config); try { assertNotNull(db); @@ -273,7 +278,8 @@ public void testCreateWithCustomDirectory() throws CouchbaseLiteException { assertTrue(new File(db.getPath()).getAbsolutePath().indexOf(dir.getPath()) != -1); assertTrue(Database.exists(dbName, dir)); assertEquals(0, db.getCount()); - } finally { + } + finally { // delete database deleteDatabase(db); } @@ -342,7 +348,8 @@ public void testGetDocFromClosedDB() throws CouchbaseLiteException { try { Document doc = db.getDocument("doc1"); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -357,7 +364,8 @@ public void testGetDocFromDeletedDB() throws CouchbaseLiteException { try { Document doc = db.getDocument("doc1"); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -436,10 +444,12 @@ public void testSaveDocInDifferentDBInstance() throws CouchbaseLiteException { try { otherDB.save(doc); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorInvalidParameter, e.getCode()); - } finally { + } + finally { // close otherDb otherDB.close(); } @@ -463,10 +473,12 @@ public void testSaveDocInDifferentDB() throws CouchbaseLiteException { try { otherDB.save(doc); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorInvalidParameter, e.getCode()); - } finally { + } + finally { // delete otherDb deleteDatabase(otherDB); deleteDatabase("otherDB"); @@ -491,7 +503,8 @@ public void testSaveInBatch() throws CouchbaseLiteException { public void run() { try { createDocs(NUM_DOCS); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { throw new RuntimeException(e); } } @@ -510,7 +523,8 @@ public void testSaveDocToClosedDB() throws CouchbaseLiteException { try { save(doc); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -526,7 +540,8 @@ public void testSaveDocToDeletedDB() throws CouchbaseLiteException { try { save(doc); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -541,11 +556,12 @@ public void testDeletePreSaveDoc() { try { db.delete(doc); fail(); - } catch (CouchbaseLiteException e) { - if (e.getCode() == CBLError.Code.CBLErrorNotFound) + } + catch (CouchbaseLiteException e) { + if (e.getCode() == CBLError.Code.CBLErrorNotFound) { ;// expected - else - fail(); + } + else { fail(); } } } @@ -575,10 +591,12 @@ public void testDeleteDocInDifferentDBInstance() throws CouchbaseLiteException { try { otherDB.delete(doc); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorInvalidParameter, e.getCode()); - } finally { + } + finally { // close otherDb otherDB.close(); } @@ -600,10 +618,12 @@ public void testDeleteDocInDifferentDB() throws CouchbaseLiteException { try { otherDB.delete(doc); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorInvalidParameter, e.getCode()); - } finally { + } + finally { // close otherDb deleteDatabase(otherDB); deleteDatabase("otherDB"); @@ -625,7 +645,8 @@ public void run() { Document doc = db.getDocument(docID); try { db.delete(doc); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { throw new RuntimeException(e); } assertNull(db.getDocument(docID)); @@ -649,7 +670,8 @@ public void testDeleteDocOnClosedDB() throws CouchbaseLiteException { try { db.delete(doc); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -666,7 +688,8 @@ public void testDeleteDocOnDeletedDB() throws CouchbaseLiteException { try { db.delete(doc); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -680,11 +703,12 @@ public void testPurgePreSaveDoc() { try { db.purge(doc); fail(); - } catch (CouchbaseLiteException e) { - if (e.getCode() == CBLError.Code.CBLErrorNotFound) + } + catch (CouchbaseLiteException e) { + if (e.getCode() == CBLError.Code.CBLErrorNotFound) { ;// expected - else - fail(); + } + else { fail(); } } assertEquals(0, db.getCount()); } @@ -715,10 +739,12 @@ public void testPurgeDocInDifferentDBInstance() throws CouchbaseLiteException { try { otherDB.purge(doc); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorInvalidParameter, e.getCode()); - } finally { + } + finally { // close otherDb otherDB.close(); } @@ -740,10 +766,12 @@ public void testPurgeDocInDifferentDB() throws CouchbaseLiteException { try { otherDB.purge(doc); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorInvalidParameter, e.getCode()); - } finally { + } + finally { // close otherDb deleteDatabase(otherDB); deleteDatabase("otherDB"); @@ -782,7 +810,8 @@ public void run() { Document doc = db.getDocument(docID); try { purgeDocAndVerify(doc); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { throw new RuntimeException(e); } assertEquals((9 - i), db.getCount()); @@ -805,7 +834,8 @@ public void testPurgeDocOnClosedDB() throws CouchbaseLiteException { try { db.purge(doc); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -822,7 +852,8 @@ public void testPurgeDocOnDeletedDB() throws CouchbaseLiteException { try { db.purge(doc); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should be thrown IllegalStateException!! } } @@ -883,9 +914,8 @@ public void testCloseThenAccessBlob() throws CouchbaseLiteException { try { blob.getContent(); fail(); - } catch (IllegalStateException e) { - ; // expected } + catch (IllegalStateException expected) { } } @Test @@ -909,7 +939,8 @@ public void run() { try { db.close(); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorTransactionNotClosed, e.getCode()); // 26 } @@ -923,7 +954,8 @@ public void testCloseThenDeleteDatabase() throws CouchbaseLiteException { try { deleteDatabase(db); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should come here! } } @@ -945,7 +977,8 @@ public void testDeleteTwice() throws CouchbaseLiteException { try { db.delete(); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // should come here! } assertFalse(path.exists()); @@ -1013,7 +1046,8 @@ public void run() { try { db.delete(); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorTransactionNotClosed, e.getCode()); // 26 } @@ -1031,11 +1065,13 @@ public void testDeleteDBOpenedByOtherInstance() throws CouchbaseLiteException { try { db.delete(); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorBusy, e.getCode()); // 24 } - } finally { + } + finally { otherDB.close(); } } @@ -1059,11 +1095,13 @@ public void testDeleteWithDefaultDirDB() throws CouchbaseLiteException { try { Database.delete(dbName, null); fail(); - } catch (IllegalArgumentException ex) { + } + catch (IllegalArgumentException ex) { // ok } assertTrue(path.exists()); - } finally { + } + finally { Database.delete(dbName, getDir()); } } @@ -1083,12 +1121,10 @@ public void testDeleteOpeningDBWithDefaultDir() throws CouchbaseLiteException { try { Database.delete(dbName, null); fail(); - } catch (IllegalArgumentException ex) { - // ok - } finally { - ; } - } finally { + catch (IllegalArgumentException ignore) { } + } + finally { db.delete(); } } @@ -1115,13 +1151,13 @@ public void testDeleteOpeningDBByStaticMethod() throws CouchbaseLiteException { try { Database.delete("db", getDir()); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorBusy, e.getCode()); // 24 - } finally { - ; } - } finally { + } + finally { deleteDatabase(db); } } @@ -1131,9 +1167,11 @@ public void testDeleteNonExistingDBWithDefaultDir() { try { Database.delete("notexistdb", null); fail(); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // expected - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { e.printStackTrace(); } } @@ -1143,7 +1181,8 @@ public void testDeleteNonExistingDB() { try { Database.delete("notexistdb", getDir()); fail(); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { assertEquals(CBLErrorDomain, e.getDomain()); assertEquals(CBLErrorNotFound, e.getCode()); } @@ -1158,7 +1197,8 @@ public void testDatabaseExistsWithDefaultDir() { try { Database.exists("db", null); fail(); - } catch (IllegalArgumentException ex) { + } + catch (IllegalArgumentException ex) { } } @@ -1192,7 +1232,8 @@ public void testDatabaseExistsAgainstNonExistDBWithDefaultDir() { try { Database.exists("nonexist", null); fail(); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // expected } } @@ -1219,7 +1260,8 @@ public void run() { doc.setValue("number", i); try { savedDoc = save(doc); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { throw new RuntimeException(e); } } @@ -1279,11 +1321,11 @@ public void testOverwriteDocWithNewDocInstgance() throws CouchbaseLiteException assertNotNull(doc); // NOTE doc1 -> theirs, doc2 -> mine if (doc2.getRevID().compareTo(doc1.getRevID()) > 0) - // mine -> doc 2 win - assertEquals("newVar", doc.getString("someKey")); + // mine -> doc 2 win + { assertEquals("newVar", doc.getString("someKey")); } else - // their -> doc 1 win - assertEquals("someVar", doc.getString("someKey")); + // their -> doc 1 win + { assertEquals("someVar", doc.getString("someKey")); } } @Test @@ -1292,8 +1334,8 @@ public void testCopy() throws CouchbaseLiteException { // operation in the native library. This test can pass with real ARM device with // API 17. Also it can pass with x86 stack emulator with API 16. if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.JELLY_BEAN - && Build.FINGERPRINT.startsWith("generic") - && "armv7l".equals(System.getProperty("os.arch"))) { + && Build.FINGERPRINT.startsWith("generic") + && "armv7l".equals(System.getProperty("os.arch"))) { return; } @@ -1314,8 +1356,7 @@ public void testCopy() throws CouchbaseLiteException { File dir = new File(config.getDirectory()); // Make sure no an existing database at the new location: - if (Database.exists(dbName, dir)) - Database.delete(dbName, dir); + if (Database.exists(dbName, dir)) { Database.delete(dbName, dir); } // Copy: Database.copy(new File(db.getPath()), dbName, config); @@ -1387,10 +1428,10 @@ public void testCreateIndex() throws CouchbaseLiteException { @Test public void testIndexBuilderEmptyArgs() { thrown.expect(IllegalArgumentException.class); - IndexBuilder.fullTextIndex((FullTextIndexItem[])null); + IndexBuilder.fullTextIndex((FullTextIndexItem[]) null); thrown.expect(IllegalArgumentException.class); - IndexBuilder.valueIndex((ValueIndexItem[])null); + IndexBuilder.valueIndex((ValueIndexItem[]) null); } @Test @@ -1469,7 +1510,7 @@ public void testDeleteIndex() throws CouchbaseLiteException { // https://github.com/couchbase/couchbase-lite-android/issues/1416 @Test public void testDeleteAndOpenDB() throws CouchbaseLiteException { - DatabaseConfiguration config = new DatabaseConfiguration(this.context); + DatabaseConfiguration config = new DatabaseConfiguration(); config.setDirectory(getDir().toString()); // open "application" database @@ -1491,12 +1532,12 @@ public void run() { // each doc has 10 items doc.setInt("index", i); - for (int j = 0; j < 10; j++) - doc.setInt("item_" + j, j); + for (int j = 0; j < 10; j++) { doc.setInt("item_" + j, j); } try { database2.save(doc); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { fail(); } } @@ -1570,7 +1611,8 @@ void testSaveDocWithConflictUsingConcurrencyControl(ConcurrencyControl cc) throw Document savedDoc = db.getDocument(doc.getId()); assertEquals(doc1b.toMap(), savedDoc.toMap()); assertEquals(4, savedDoc.getSequence()); - } else { + } + else { assertFalse(db.save(doc1b, cc)); Document savedDoc = db.getDocument(doc.getId()); assertEquals(expected, savedDoc.toMap()); @@ -1604,7 +1646,8 @@ void testSaveDocWithNoParentConflictUsingConcurrencyControl(ConcurrencyControl c savedDoc = db.getDocument(doc1b.getId()); assertEquals(doc1b.toMap(), savedDoc.toMap()); assertEquals(2, savedDoc.getSequence()); - } else { + } + else { assertFalse(db.save(doc1b, cc)); savedDoc = db.getDocument(doc1b.getId()); assertEquals(doc1a.toMap(), savedDoc.toMap()); @@ -1642,7 +1685,8 @@ void testSaveDocWithDeletedConflictUsingConcurrencyControl(ConcurrencyControl cc Document savedDoc = db.getDocument(doc.getId()); assertEquals(doc1b.toMap(), savedDoc.toMap()); assertEquals(3, savedDoc.getSequence()); - } else { + } + else { assertFalse(db.save(doc1b, cc)); assertNull(db.getDocument(doc.getId())); } @@ -1729,7 +1773,8 @@ void testDeleteDocWithConflictUsingConcurrencyControl(ConcurrencyControl cc) thr assertTrue(db.delete(doc1b, cc)); assertEquals(3, doc1b.getSequence()); assertNull(db.getDocument(doc1b.getId())); - } else { + } + else { assertFalse(db.delete(doc1b, cc)); Document savedDoc = db.getDocument(doc.getId()); assertEquals(expected, savedDoc.toMap()); @@ -1752,11 +1797,12 @@ public void testDeleteNonExistingDoc() throws CouchbaseLiteException { try { db.delete(doc1a); fail(); - } catch (CouchbaseLiteException e) { - if (e.getCode() == CBLError.Code.CBLErrorNotFound) + } + catch (CouchbaseLiteException e) { + if (e.getCode() == CBLError.Code.CBLErrorNotFound) { ;// expected - else - fail(); + } + else { fail(); } } db.delete(doc1b); diff --git a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/MigrationTest.java b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/MigrationTest.java index 0995fa8c3..4e082717e 100644 --- a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/MigrationTest.java +++ b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/MigrationTest.java @@ -17,6 +17,8 @@ // package com.couchbase.lite; +import android.content.Context; + import com.couchbase.lite.utils.ZipUtils; import org.junit.Test; @@ -38,7 +40,7 @@ public class MigrationTest extends BaseTest { */ //NOTE: @Test public void testPrepareDB() throws CouchbaseLiteException { - Database db = new Database("android-sqlite", new DatabaseConfiguration(context)); + Database db = new Database("android-sqlite", new DatabaseConfiguration()); try { for (int i = 1; i <= 2; i++) { MutableDocument doc = new MutableDocument("doc" + i); @@ -56,15 +58,15 @@ public void testPrepareDB() throws CouchbaseLiteException { // TODO: 1.x DB's attachment is not automatically ditected as blob @Test public void testOpenExsitingDBv1x() throws Exception { - + final Context ctxt = CouchbaseLite.getContext(); // https://github.com/couchbase/couchbase-lite-android/issues/1237 // if db exist, delete it - deleteDB("android-sqlite", context.getFilesDir()); + deleteDB("android-sqlite", ctxt.getFilesDir()); - ZipUtils.unzip(getAsset("replacedb/android140-sqlite.cblite2.zip"), context.getFilesDir()); + ZipUtils.unzip(getAsset("replacedb/android140-sqlite.cblite2.zip"), ctxt.getFilesDir()); - Database db = new Database("android-sqlite", new DatabaseConfiguration(context)); + Database db = new Database("android-sqlite", new DatabaseConfiguration()); try { assertEquals(2, db.getCount()); for (int i = 1; i <= 2; i++) { @@ -85,20 +87,22 @@ public void testOpenExsitingDBv1x() throws Exception { // close db db.close(); // if db exist, delete it - deleteDB("android-sqlite", context.getFilesDir()); + deleteDB("android-sqlite", ctxt.getFilesDir()); } } @Test public void testOpenExsitingDBv1xNoAttachment() throws Exception { + final Context ctxt = CouchbaseLite.getContext(); + // https://github.com/couchbase/couchbase-lite-android/issues/1237 // if db exist, delete it - deleteDB("android-sqlite", context.getFilesDir()); + deleteDB("android-sqlite", ctxt.getFilesDir()); - ZipUtils.unzip(getAsset("replacedb/android140-sqlite-noattachment.cblite2.zip"), context.getFilesDir()); + ZipUtils.unzip(getAsset("replacedb/android140-sqlite-noattachment.cblite2.zip"), ctxt.getFilesDir()); - Database db = new Database("android-sqlite", new DatabaseConfiguration(context)); + Database db = new Database("android-sqlite", new DatabaseConfiguration()); try { assertEquals(2, db.getCount()); for (int i = 1; i <= 2; i++) { @@ -110,18 +114,20 @@ public void testOpenExsitingDBv1xNoAttachment() throws Exception { // close db db.close(); // if db exist, delete it - deleteDB("android-sqlite", context.getFilesDir()); + deleteDB("android-sqlite", ctxt.getFilesDir()); } } @Test public void testOpenExsitingDB() throws Exception { + final Context ctxt = CouchbaseLite.getContext(); + // if db exist, delete it - deleteDB("android-sqlite", context.getFilesDir()); + deleteDB("android-sqlite", ctxt.getFilesDir()); - ZipUtils.unzip(getAsset("replacedb/android200-sqlite.cblite2.zip"), context.getFilesDir()); + ZipUtils.unzip(getAsset("replacedb/android200-sqlite.cblite2.zip"), ctxt.getFilesDir()); - Database db = new Database("android-sqlite", new DatabaseConfiguration(context)); + Database db = new Database("android-sqlite", new DatabaseConfiguration()); try { assertEquals(2, db.getCount()); for (int i = 1; i <= 2; i++) { @@ -137,14 +143,16 @@ public void testOpenExsitingDB() throws Exception { // close db db.close(); // if db exist, delete it - deleteDB("android-sqlite", context.getFilesDir()); + deleteDB("android-sqlite", ctxt.getFilesDir()); } } // if db exist, delete it private void deleteDB(String name, File dir) throws CouchbaseLiteException { + final Context ctxt = CouchbaseLite.getContext(); + // database exist, delete it - if (Database.exists(name, context.getFilesDir())) { + if (Database.exists(name, ctxt.getFilesDir())) { // sometimes, db is still in used, wait for a while. Maximum 3 sec for (int i = 0; i < 10; i++) { try { diff --git a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/ReplicatorWithSyncGatewayDBTest.java b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/ReplicatorWithSyncGatewayDBTest.java index be2ccb7fe..284717d6a 100644 --- a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/ReplicatorWithSyncGatewayDBTest.java +++ b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/ReplicatorWithSyncGatewayDBTest.java @@ -19,14 +19,6 @@ import android.support.test.InstrumentationRegistry; -import com.couchbase.lite.internal.support.Log; -import com.couchbase.lite.utils.Config; - -import org.json.JSONObject; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -41,6 +33,12 @@ import okhttp3.OkHttpClient; import okhttp3.RequestBody; import okhttp3.Response; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.couchbase.lite.utils.Config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -66,8 +64,7 @@ public class ReplicatorWithSyncGatewayDBTest extends BaseReplicatorTest { @Before public void setUp() throws Exception { config = new Config(InstrumentationRegistry.getContext().getAssets().open(Config.TEST_PROPERTIES_FILE)); - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } super.setUp(); @@ -77,8 +74,7 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } remote_DELETE_db(DB_NAME); @@ -88,11 +84,13 @@ public void tearDown() throws Exception { private boolean remote_PUT_db(String db) throws IOException { OkHttpClient client = new OkHttpClient(); String url = String.format(Locale.ENGLISH, "http://%s:4985/%s/", this.config.remoteHost(), db); - RequestBody body = RequestBody.create(JSON, "{\"server\": \"walrus:\", \"users\": { \"GUEST\": { \"disabled\": false, \"admin_channels\": [\"*\"] } }, \"unsupported\": {\"replicator_2\":true}}"); + RequestBody body = RequestBody.create( + JSON, + "{\"server\": \"walrus:\", \"users\": { \"GUEST\": { \"disabled\": false, \"admin_channels\": [\"*\"] } }, \"unsupported\": {\"replicator_2\":true}}"); okhttp3.Request request = new okhttp3.Request.Builder() - .url(url) - .put(body) - .build(); + .url(url) + .put(body) + .build(); Response response = client.newCall(request).execute(); return response.code() >= 200 && response.code() < 300; } @@ -101,9 +99,9 @@ private boolean remote_DELETE_db(String db) throws IOException { OkHttpClient client = new OkHttpClient(); String url = String.format(Locale.ENGLISH, "http://%s:4985/%s/", this.config.remoteHost(), db); okhttp3.Request request = new okhttp3.Request.Builder() - .url(url) - .delete() - .build(); + .url(url) + .delete() + .build(); Response response = client.newCall(request).execute(); return response.code() >= 200 && response.code() < 300; } @@ -113,17 +111,16 @@ private boolean remote_PUT_db(String db, String docID, String jsonBody) throws I String url = String.format(Locale.ENGLISH, "http://%s:4984/%s/%s", this.config.remoteHost(), db, docID); RequestBody body = RequestBody.create(JSON, jsonBody); okhttp3.Request request = new okhttp3.Request.Builder() - .url(url) - .put(body) - .build(); + .url(url) + .put(body) + .build(); Response response = client.newCall(request).execute(); return response.code() >= 200 && response.code() < 300; } @Test public void testEmptyPushToRemoteDB() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } Endpoint target = getRemoteEndpoint(DB_NAME, false); ReplicatorConfiguration config = makeConfig(true, false, false, target); @@ -132,8 +129,7 @@ public void testEmptyPushToRemoteDB() throws Exception { @Test public void testPushToRemoteDB() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } // Create 100 docs in local db loadJSONResource("names_100.json"); @@ -153,8 +149,7 @@ public void testPushToRemoteDB() throws Exception { @Test public void testProgress() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } timeout = 60; @@ -174,8 +169,9 @@ public void testProgress() throws Exception { public void changed(ReplicatorChange change) { Replicator.Status status = change.getStatus(); Replicator.Progress progress = status.getProgress(); - if (progress.getCompleted() >= numDocs && progress.getCompleted() == progress.getTotal()) + if (progress.getCompleted() >= numDocs && progress.getCompleted() == progress.getTotal()) { progressLatch.countDown(); + } } }); run(r, 0, null); @@ -193,8 +189,9 @@ public void changed(ReplicatorChange change) { public void changed(ReplicatorChange change) { Replicator.Status status = change.getStatus(); Replicator.Progress progress = status.getProgress(); - if (progress.getCompleted() >= numDocs && progress.getCompleted() == progress.getTotal()) + if (progress.getCompleted() >= numDocs && progress.getCompleted() == progress.getTotal()) { progressLatch.countDown(); + } } }); run(r, 0, null); @@ -216,8 +213,7 @@ public void changed(ReplicatorChange change) { */ @Test public void testContinuousPush() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } loadJSONResource("names_100.json"); @@ -230,8 +226,7 @@ public void testContinuousPush() throws Exception { @Test public void testChannelPull() throws CouchbaseLiteException, InterruptedException, URISyntaxException { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } assertEquals(0, otherDB.getCount()); db.inBatch(new Runnable() { @@ -243,7 +238,8 @@ public void run() { doc.setValue("foo", "var"); try { db.save(doc); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { fail(); } } @@ -253,7 +249,8 @@ public void run() { doc.setValue("channels", "my_channel"); try { db.save(doc); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { fail(); } } @@ -276,8 +273,7 @@ public void run() { */ @Test public void testPushToRemoteDBWithAttachment() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } // store doc with attachment into db. { @@ -291,7 +287,8 @@ public void testPushToRemoteDBWithAttachment() throws Exception { doc1.setValue("name", "Tiger"); doc1.setBlob("image.jpg", blob); save(doc1); - } finally { + } + finally { is.close(); } assertEquals(1, db.getCount()); @@ -329,21 +326,22 @@ public void testContinuousPushNeverending() throws URISyntaxException, Interrupt repl.addChangeListener(executor, new ReplicatorChangeListener() { @Override public void changed(ReplicatorChange change) { - log(LogLevel.INFO,"changed() change -> " + change); + log(LogLevel.INFO, "changed() change -> " + change); } }); try { Thread.sleep(3 * 60 * 1000); - } catch (Exception e) { + } + catch (Exception e) { } } // https://github.com/couchbase/couchbase-lite-android/issues/1545 @Test - public void testPushDocAndDocChangeListener() throws CouchbaseLiteException, URISyntaxException, InterruptedException { - if (!config.replicatorTestsEnabled()) - return; + public void testPushDocAndDocChangeListener() + throws CouchbaseLiteException, URISyntaxException, InterruptedException { + if (!config.replicatorTestsEnabled()) { return; } String docID = "doc1"; @@ -414,8 +412,7 @@ public void changed(ReplicatorChange change) { @Test public void testPullReplicateMultipleDocs() throws IOException, URISyntaxException, InterruptedException { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } // create multiple documents on sync gateway final int N = 10; @@ -429,19 +426,19 @@ public void testPullReplicateMultipleDocs() throws IOException, URISyntaxExcepti @Override public void changed(DatabaseChange change) { // check getDocumentIDs values - if (change.getDocumentIDs() != null) - assertEquals(N, change.getDocumentIDs().size()); + if (change.getDocumentIDs() != null) { assertEquals(N, change.getDocumentIDs().size()); } // check query result Query q = QueryBuilder.select(SelectResult.expression(Meta.id)) - .from(DataSource.database(db)) - .where(Expression.property("type").equalTo(Expression.string("text"))); + .from(DataSource.database(db)) + .where(Expression.property("type").equalTo(Expression.string("text"))); try { ResultSet rs = q.execute(); List results = rs.allResults(); assertEquals(N, results.size()); - } catch (CouchbaseLiteException e) { + } + catch (CouchbaseLiteException e) { fail("Error in Query.execute(): " + e.getMessage()); } } @@ -464,8 +461,7 @@ public void changed(DatabaseChange change) { @Test public void testPullConflictDeleteWins_SG() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } URLEndpoint target = getRemoteEndpoint(DB_NAME, false); @@ -502,7 +498,8 @@ public void testPullConflictDeleteWins_SG() throws Exception { assertNull(db.getDocument(doc1.getId())); } - JSONObject sendRequestToEndpoint(URLEndpoint endpoint, String method, String path, String mediaType, byte[] body) throws Exception { + JSONObject sendRequestToEndpoint(URLEndpoint endpoint, String method, String path, String mediaType, byte[] body) + throws Exception { URI endpointURI = endpoint.getURL(); String _scheme = endpointURI.getScheme().equals(URLEndpoint.kURLEndpointTLSScheme) ? "https" : "http"; @@ -516,16 +513,20 @@ JSONObject sendRequestToEndpoint(URLEndpoint endpoint, String method, String pat okhttp3.Request.Builder builder = new okhttp3.Request.Builder().url(uri.toURL()); RequestBody requestBody = null; - if (body != null && body instanceof byte[]) - requestBody = RequestBody.create(MediaType.parse(mediaType), body); + if (body instanceof byte[]) { requestBody = RequestBody.create(MediaType.parse(mediaType), body); } builder.method(method, requestBody); okhttp3.Request request = builder.build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { - log(LogLevel.INFO, "Send request succeeded; URL=" + uri + " Method=" + method + " Status=" + response.code()); + log( + LogLevel.INFO, + "Send request succeeded; URL=" + uri + " Method=" + method + " Status=" + response.code()); return new JSONObject(response.body().string()); - } else { - log(LogLevel.ERROR, "Failed to send request; URL=" + uri + " Method=" + method + " Status=" + response.code()); + } + else { + log( + LogLevel.ERROR, + "Failed to send request; URL=" + uri + " Method=" + method + " Status=" + response.code()); return null; } } @@ -535,8 +536,7 @@ JSONObject sendRequestToEndpoint(URLEndpoint endpoint, String method, String pat // Currently CBL ignore the error wight setting code 26 (Unknown error). @Test public void testDocIDFilterSG() throws Exception { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } URLEndpoint target = getRemoteEndpoint(DB_NAME, false); @@ -565,8 +565,7 @@ public void testDocIDFilterSG() throws Exception { // https://github.com/couchbase/couchbase-lite-core/issues/447 @Test public void testResetCheckpoint() throws CouchbaseLiteException, InterruptedException, URISyntaxException { - if (!config.replicatorTestsEnabled()) - return; + if (!config.replicatorTestsEnabled()) { return; } URLEndpoint target = getRemoteEndpoint(DB_NAME, false); diff --git a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/internal/utils/Config.java b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/internal/utils/Config.java index 8225fd53b..36c630c70 100644 --- a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/internal/utils/Config.java +++ b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/internal/utils/Config.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; public class Config extends java.util.Properties { @@ -31,7 +32,7 @@ public Config() { public Config(InputStream in) throws IOException { try { - load(new InputStreamReader(in, "UTF-8")); + load(new InputStreamReader(in, StandardCharsets.UTF_8)); } finally { in.close(); diff --git a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/utils/Config.java b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/utils/Config.java index 2b6e58e41..df33999f3 100644 --- a/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/utils/Config.java +++ b/android/CouchbaseLite/src/androidTest/java/com/couchbase/lite/utils/Config.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; public class Config extends java.util.Properties { @@ -27,12 +28,8 @@ public class Config extends java.util.Properties { public static final String EE_TEST_PROPERTIES_FILE = "ee_test.properties"; public Config(InputStream in) throws IOException { - try { - load(new InputStreamReader(in, "UTF-8")); - } - finally { - in.close(); - } + try { load(new InputStreamReader(in, StandardCharsets.UTF_8)); } + finally { in.close(); } } public boolean deleteDatabaseInTearDown() { @@ -43,9 +40,7 @@ public boolean eeFeaturesTestsEnabled() { return Boolean.parseBoolean(getProperty("eeFeaturesTestsEnabled")); } - public boolean replicatorTestsEnabled() { - return Boolean.parseBoolean(getProperty("replicatorTestsEnabled")); - } + public boolean replicatorTestsEnabled() { return Boolean.parseBoolean(getProperty("replicatorTestsEnabled")); } public boolean concurrentTestsEnabled() { return Boolean.parseBoolean(getProperty("concurrentTestsEnabled")); diff --git a/android/CouchbaseLite/src/ce/java/com/couchbase/lite/DatabaseConfiguration.java b/android/CouchbaseLite/src/ce/java/com/couchbase/lite/DatabaseConfiguration.java index 1e826bd25..0bbe481f7 100644 --- a/android/CouchbaseLite/src/ce/java/com/couchbase/lite/DatabaseConfiguration.java +++ b/android/CouchbaseLite/src/ce/java/com/couchbase/lite/DatabaseConfiguration.java @@ -17,7 +17,6 @@ // package com.couchbase.lite; -import android.content.Context; import android.support.annotation.NonNull; @@ -30,8 +29,8 @@ public final class DatabaseConfiguration extends AbstractDatabaseConfiguration { // Constructors //--------------------------------------------- - public DatabaseConfiguration(@NonNull Context context) { - super(context); + public DatabaseConfiguration() { + super(); } public DatabaseConfiguration(@NonNull DatabaseConfiguration config) { diff --git a/android/CouchbaseLite/src/ce/java/com/couchbase/lite/Replicator.java b/android/CouchbaseLite/src/ce/java/com/couchbase/lite/Replicator.java index 7aee55396..d833e676c 100644 --- a/android/CouchbaseLite/src/ce/java/com/couchbase/lite/Replicator.java +++ b/android/CouchbaseLite/src/ce/java/com/couchbase/lite/Replicator.java @@ -10,7 +10,7 @@ public final class Replicator extends AbstractReplicator { /** * Initializes a replicator with the given configuration. * - * @param config + * @param config The Replicator configuration object */ public Replicator(@NonNull ReplicatorConfiguration config) { super(config); diff --git a/android/CouchbaseLite/src/ce/java/com/couchbase/lite/ReplicatorConfiguration.java b/android/CouchbaseLite/src/ce/java/com/couchbase/lite/ReplicatorConfiguration.java index bb0266fd0..0809b50c5 100644 --- a/android/CouchbaseLite/src/ce/java/com/couchbase/lite/ReplicatorConfiguration.java +++ b/android/CouchbaseLite/src/ce/java/com/couchbase/lite/ReplicatorConfiguration.java @@ -28,6 +28,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import com.couchbase.lite.internal.core.CBLVersion; + /** * Replicator configuration. @@ -82,7 +84,7 @@ public enum ReplicatorType { // member variables //--------------------------------------------- - private ReplicatorType replicatorType = ReplicatorType.PUSH_AND_PULL; + private ReplicatorType replicatorType; private boolean readonly; private Database database; private Endpoint target; diff --git a/android/CouchbaseLite/src/main/java/com/couchbase/lite/ConsoleLogger.java b/android/CouchbaseLite/src/main/java/com/couchbase/lite/ConsoleLogger.java index 72bb9f7d2..794d9c8b0 100644 --- a/android/CouchbaseLite/src/main/java/com/couchbase/lite/ConsoleLogger.java +++ b/android/CouchbaseLite/src/main/java/com/couchbase/lite/ConsoleLogger.java @@ -34,9 +34,7 @@ public final class ConsoleLogger implements Logger { private LogLevel logLevel = LogLevel.WARNING; private EnumSet logDomains = EnumSet.of(LogDomain.ALL); - //--------------------------------------------- - // Constructor should not be exposed (singleton) - //--------------------------------------------- + // Singleton instance accessible from Log.getConsole() ConsoleLogger() { } /** diff --git a/android/CouchbaseLite/src/main/java/com/couchbase/lite/CouchbaseLite.java b/android/CouchbaseLite/src/main/java/com/couchbase/lite/CouchbaseLite.java new file mode 100644 index 000000000..ffb26d04e --- /dev/null +++ b/android/CouchbaseLite/src/main/java/com/couchbase/lite/CouchbaseLite.java @@ -0,0 +1,59 @@ +// +// Copyright (c) 2019 Couchbase, Inc All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package com.couchbase.lite; + +import android.content.Context; +import android.support.annotation.NonNull; + +import java.io.File; +import java.lang.ref.SoftReference; + + +public final class CouchbaseLite { + private static SoftReference context; + + private CouchbaseLite() {} + + public static void init(@NonNull Context ctxt) { + CouchbaseLite.context = new SoftReference<>(ctxt.getApplicationContext()); + } + + @NonNull + static Context getContext() { + final Context ctxt = (context == null) ? null : context.get(); + if (ctxt == null) { + throw new IllegalStateException("Null context. Did you forget to call CouchbaseLite.init()?"); + } + return ctxt; + } + + static String getDbDirectoryPath() { + return getContext().getFilesDir().getAbsolutePath(); + } + + static String getTmpDirectory(@NonNull String name) { + return getTmpDirectory(getContext().getCacheDir().getAbsolutePath(), name); + } + + static String getTmpDirectory(String root, String name) { + final File dir = new File(root, name); + + final String path = dir.getAbsolutePath(); + if ((dir.exists() || dir.mkdirs()) && dir.isDirectory()) { return path; } + + throw new IllegalStateException("Cannot create or access temp directory at " + path); + } +} diff --git a/shared/src/main/java/com/couchbase/lite/FileLogger.java b/android/CouchbaseLite/src/main/java/com/couchbase/lite/FileLogger.java similarity index 91% rename from shared/src/main/java/com/couchbase/lite/FileLogger.java rename to android/CouchbaseLite/src/main/java/com/couchbase/lite/FileLogger.java index 2d2895990..f96faecb0 100644 --- a/shared/src/main/java/com/couchbase/lite/FileLogger.java +++ b/android/CouchbaseLite/src/main/java/com/couchbase/lite/FileLogger.java @@ -43,12 +43,8 @@ public final class FileLogger implements Logger { private LogLevel logLevel = LogLevel.INFO; private LogFileConfiguration config; - //--------------------------------------------- - // Constructor should not be exposed (singleton) - //--------------------------------------------- - FileLogger() { - setupDomainObjects(); - } + // Singleton instance accessible from Log.getConsole() + FileLogger() { setupDomainObjects(); } /** * Gets the configuration currently in use on the file logger. @@ -73,8 +69,8 @@ public void setConfig(LogFileConfiguration config) { if (config == null) { Log.w( DOMAIN, - "Database.log.getFile().getConfig() is now null, meaning file logging is disabled. Log files " - + "required for product support are not being generated."); + "Database.log.getFile().getConfig() is now null, meaning file logging is disabled. " + + "Log files required for product support are not being generated."); } updateConfig(); @@ -135,7 +131,7 @@ public void setLevel(@NonNull LogLevel level) { } @Override - public void log(LogLevel level, @NonNull LogDomain domain, @NonNull String message) { + public void log(@NonNull LogLevel level, @NonNull LogDomain domain, @NonNull String message) { if (level.compareTo(logLevel) < 0 || !domainObjects.containsKey(domain)) { return; } diff --git a/android/CouchbaseLite/src/main/java/com/couchbase/lite/AndroidNetworkReachabilityManager.java b/android/CouchbaseLite/src/main/java/com/couchbase/lite/NetworkReachabilityManager.java similarity index 94% rename from android/CouchbaseLite/src/main/java/com/couchbase/lite/AndroidNetworkReachabilityManager.java rename to android/CouchbaseLite/src/main/java/com/couchbase/lite/NetworkReachabilityManager.java index 6cbd5306a..029953557 100644 --- a/android/CouchbaseLite/src/main/java/com/couchbase/lite/AndroidNetworkReachabilityManager.java +++ b/android/CouchbaseLite/src/main/java/com/couchbase/lite/NetworkReachabilityManager.java @@ -1,5 +1,5 @@ // -// AndroidNetworkReachabilityManager.java +// NetworkReachabilityManager.java // // Copyright (c) 2017 Couchbase, Inc All rights reserved. // @@ -30,7 +30,7 @@ /** * NOTE: https://developer.android.com/training/basics/network-ops/managing.html */ -final class AndroidNetworkReachabilityManager extends NetworkReachabilityManager { +final class NetworkReachabilityManager extends AbstractNetworkReachabilityManager { private static final LogDomain DOMAIN = LogDomain.REPLICATOR; @@ -45,14 +45,15 @@ public void onReceive(Context context, Intent intent) { } } - private final Context context; private final NetworkReceiver receiver; + private final Context context; private boolean listening; - AndroidNetworkReachabilityManager(Context context) { - this.listening = false; - this.context = context; + NetworkReachabilityManager() { this.receiver = new NetworkReceiver(); + this.context = CouchbaseLite.getContext(); + + this.listening = false; } /** diff --git a/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/core/CBLVersion.java b/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/core/CBLVersion.java index 47ab99b1c..afb2f7c11 100644 --- a/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/core/CBLVersion.java +++ b/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/core/CBLVersion.java @@ -22,7 +22,6 @@ import java.util.Locale; import com.couchbase.lite.BuildConfig; -import com.couchbase.lite.internal.core.C4; public class CBLVersion { diff --git a/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/replicator/CBLWebSocket.java b/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/replicator/CBLWebSocket.java new file mode 100644 index 000000000..444fa5ea3 --- /dev/null +++ b/android/CouchbaseLite/src/main/java/com/couchbase/lite/internal/replicator/CBLWebSocket.java @@ -0,0 +1,79 @@ +package com.couchbase.lite.internal.replicator; + +import android.os.Build; +import android.support.annotation.NonNull; +import android.system.ErrnoException; + +import java.net.URISyntaxException; +import java.security.GeneralSecurityException; +import java.util.Map; + +import com.couchbase.lite.internal.core.C4Constants; + + +// +// Copyright (c) 2019 Couchbase, Inc All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +public class CBLWebSocket extends AbstractCBLWebSocket { + // Posix errno values with Android. + // from sysroot/usr/include/asm-generic/errno.h + private static final int ECONNRESET = 104; // java.net.SocketException + private static final int ECONNREFUSED = 111; // java.net.ConnectException + + + public CBLWebSocket( + long handle, + String scheme, + String hostname, + int port, + String path, + Map options) throws GeneralSecurityException, URISyntaxException { + super(handle, scheme, hostname, port, path, options); + } + + protected boolean handleClose(@NonNull Throwable error) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Throwable cause = error.getCause(); + if (cause != null) { + cause = cause.getCause(); + if (cause instanceof ErrnoException) { + final ErrnoException e = (ErrnoException) cause; + closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, e.errno, null); + return true; + } + } + } + + // ConnectException + if (error instanceof java.net.ConnectException) { + closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, ECONNREFUSED, null); + return true; + } + + // SocketException + else if (error instanceof java.net.SocketException) { + closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, ECONNRESET, null); + return true; + } + + // EOFException + if (error instanceof java.io.EOFException) { + closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, ECONNRESET, null); + return true; + } + + return false; + } +} diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index bdc69ab8e..1498dd79e 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,3 @@ -#Fri Mar 30 13:43:44 PDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/shared/src/main/java/com/couchbase/lite/AbstractDatabase.java b/shared/src/main/java/com/couchbase/lite/AbstractDatabase.java index 9a257d609..b5d7d19b7 100644 --- a/shared/src/main/java/com/couchbase/lite/AbstractDatabase.java +++ b/shared/src/main/java/com/couchbase/lite/AbstractDatabase.java @@ -74,7 +74,7 @@ abstract class AbstractDatabase { /** * Gets the logging controller for the Couchbase Lite library to configure the * logging settings and add custom logging. - * + *

* This is part of the Public API. */ @SuppressWarnings("ConstantName") @@ -249,9 +249,10 @@ public void run() { // Check file logging if (Database.log.getFile().getConfig() == null) { - Log.w(DOMAIN, "Database.log.getFile().getConfig() is null, meaning file " + - "logging is disabled. Log files required for product support are " + - "not being generated."); + Log.w( + DOMAIN, + "Database.log.getFile().getConfig() is null, meaning file logging is disabled. " + + "Log files required for product support are not being generated."); } } }); @@ -268,8 +269,8 @@ public void run() { this.shellMode = false; this.postExecutor = Executors.newSingleThreadScheduledExecutor(); this.queryExecutor = Executors.newSingleThreadScheduledExecutor(); - this.activeReplications = Collections.synchronizedSet(new HashSet()); - this.activeLiveQueries = Collections.synchronizedSet(new HashSet()); + this.activeReplications = Collections.synchronizedSet(new HashSet<>()); + this.activeLiveQueries = Collections.synchronizedSet(new HashSet<>()); // Set the temp directory based on Database Configuration: config.setTempDir(); diff --git a/shared/src/main/java/com/couchbase/lite/AbstractDatabaseConfiguration.java b/shared/src/main/java/com/couchbase/lite/AbstractDatabaseConfiguration.java index fc554e992..00df54903 100644 --- a/shared/src/main/java/com/couchbase/lite/AbstractDatabaseConfiguration.java +++ b/shared/src/main/java/com/couchbase/lite/AbstractDatabaseConfiguration.java @@ -16,11 +16,8 @@ // package com.couchbase.lite; -import android.content.Context; import android.support.annotation.NonNull; -import java.io.File; - import com.couchbase.lite.internal.core.C4Base; @@ -34,28 +31,25 @@ abstract class AbstractDatabaseConfiguration { //--------------------------------------------- private boolean readonly; - private Context context; - private String directory; private boolean customDir; + private String directory; //--------------------------------------------- // Constructors //--------------------------------------------- - protected AbstractDatabaseConfiguration(@NonNull Context context) { - if (context == null) { throw new IllegalArgumentException("context cannot be null."); } - this.readonly = false; - this.context = context; - this.directory = context.getFilesDir().getAbsolutePath(); - this.customDir = false; + protected AbstractDatabaseConfiguration() { + this(false, CouchbaseLite.getDbDirectoryPath()); } protected AbstractDatabaseConfiguration(@NonNull AbstractDatabaseConfiguration config) { - if (config == null) { throw new IllegalArgumentException("config cannot be null."); } + this(config.customDir, config.directory); + } + + private AbstractDatabaseConfiguration(boolean customDir, String directory) { this.readonly = false; - this.context = config.context; - this.directory = config.directory; - this.customDir = config.customDir; + this.customDir = customDir; + this.directory = directory; } //--------------------------------------------- @@ -96,10 +90,6 @@ protected void setReadonly(boolean readonly) { // Package level access //--------------------------------------------- - Context getContext() { - return context; - } - /** * Set the temp directory based on Database Configuration. * The default temp directory is APP_CACHE_DIR/Couchbase/tmp. @@ -116,23 +106,14 @@ void setTempDir() { } } - //--------------------------------------------- - // Private level access - //--------------------------------------------- - /** * Returns the temp directory. The default temp directory is APP_CACHE_DIR/Couchbase/tmp. * If a custom database directory is set, the temp directory will be * CUSTOM_DATABASE_DIR/Couchbase/tmp. */ private String getTempDir() { - final File temp = (customDir) - ? new File(directory, TEMP_DIR_NAME) - : new File(context.getCacheDir(), TEMP_DIR_NAME); - - if ((temp.exists() || temp.mkdirs()) && temp.isDirectory()) { return temp.getAbsolutePath(); } - - throw new IllegalStateException("Cannot create or access temp directory at " + - temp.getAbsolutePath()); + return (!customDir) + ? CouchbaseLite.getTmpDirectory(TEMP_DIR_NAME) + : CouchbaseLite.getTmpDirectory(directory, TEMP_DIR_NAME); } } diff --git a/shared/src/main/java/com/couchbase/lite/NetworkReachabilityManager.java b/shared/src/main/java/com/couchbase/lite/AbstractNetworkReachabilityManager.java similarity index 94% rename from shared/src/main/java/com/couchbase/lite/NetworkReachabilityManager.java rename to shared/src/main/java/com/couchbase/lite/AbstractNetworkReachabilityManager.java index 6d7240e94..a075aee87 100644 --- a/shared/src/main/java/com/couchbase/lite/NetworkReachabilityManager.java +++ b/shared/src/main/java/com/couchbase/lite/AbstractNetworkReachabilityManager.java @@ -1,5 +1,5 @@ // -// NetworkReachabilityManager.java +// AbstractNetworkReachabilityManager.java // // Copyright (c) 2017 Couchbase, Inc All rights reserved. // @@ -28,10 +28,10 @@ * (an example of a NetworkReachabilityListeners is a Replicator that wants to pause when * it's been detected that the network is not reachable) */ -abstract class NetworkReachabilityManager { +abstract class AbstractNetworkReachabilityManager { private final Set listeners - = Collections.synchronizedSet(new HashSet()); + = Collections.synchronizedSet(new HashSet<>()); /** * Add Network Reachability Listener diff --git a/shared/src/main/java/com/couchbase/lite/AbstractReplicator.java b/shared/src/main/java/com/couchbase/lite/AbstractReplicator.java index 0382ed21e..af518f7a9 100644 --- a/shared/src/main/java/com/couchbase/lite/AbstractReplicator.java +++ b/shared/src/main/java/com/couchbase/lite/AbstractReplicator.java @@ -295,7 +295,7 @@ private static int mkmode(boolean active, boolean continuous) { private CouchbaseLiteException lastError; private String desc; private ScheduledExecutorService handler; - private NetworkReachabilityManager reachabilityManager; + private AbstractNetworkReachabilityManager reachabilityManager; private Map responseHeaders; // Do something with these (for auth) private boolean shouldResetCheckpoint; // Reset the replicator checkpoint. @@ -311,11 +311,11 @@ public AbstractReplicator(@NonNull ReplicatorConfiguration config) { if (config == null) { throw new IllegalArgumentException("config cannot be null."); } this.config = config.readonlyCopy(); - this.changeListenerTokens = Collections.synchronizedSet(new HashSet()); - this.docEndedListenerTokens = Collections.synchronizedSet(new HashSet()); + this.changeListenerTokens = Collections.synchronizedSet(new HashSet<>()); + this.docEndedListenerTokens = Collections.synchronizedSet(new HashSet<>()); this.handler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { @Override - public Thread newThread(Runnable target) { + public Thread newThread(@NonNull Runnable target) { return new Thread(target, "ReplicatorListenerThread"); } }); @@ -618,7 +618,7 @@ public boolean validationFunction( c4ReplListener = new C4ReplicatorListener() { @Override public void statusChanged(final C4Replicator repl, final C4ReplicatorStatus status, final Object context) { - Log.i(DOMAIN, "C4ReplicatorListener.statusChanged() status -> " + status); + Log.i(DOMAIN, "C4ReplicatorListener.statusChanged, context: " + context + ", status: " + status); final AbstractReplicator replicator = (AbstractReplicator) context; if (repl == replicator.c4repl) { handler.execute(new Runnable() { @@ -859,7 +859,7 @@ private void startReachabilityObserver() { catch (UnknownHostException ignore) { } if (reachabilityManager == null) { - reachabilityManager = new AndroidNetworkReachabilityManager(config.getDatabase().getConfig().getContext()); + reachabilityManager = new NetworkReachabilityManager(); } reachabilityManager.addNetworkReachabilityListener(this); diff --git a/shared/src/main/java/com/couchbase/lite/DataSource.java b/shared/src/main/java/com/couchbase/lite/DataSource.java index ea32e9866..955037755 100644 --- a/shared/src/main/java/com/couchbase/lite/DataSource.java +++ b/shared/src/main/java/com/couchbase/lite/DataSource.java @@ -73,7 +73,7 @@ public static As database(@NonNull com.couchbase.lite.Database database) { } - private Object source; + private final Object source; private String alias; private DataSource(Object source) { diff --git a/shared/src/main/java/com/couchbase/lite/Document.java b/shared/src/main/java/com/couchbase/lite/Document.java index 0347e91c5..60a5f6c0c 100644 --- a/shared/src/main/java/com/couchbase/lite/Document.java +++ b/shared/src/main/java/com/couchbase/lite/Document.java @@ -369,9 +369,7 @@ public boolean equals(Object o) { // Step 3: Check content // NOTE: internalDict never null?? - if (!internalDict.equals(doc.internalDict)) { return false; } - - return true; + return internalDict.equals(doc.internalDict); } //--------------------------------------------- diff --git a/shared/src/main/java/com/couchbase/lite/DocumentReplication.java b/shared/src/main/java/com/couchbase/lite/DocumentReplication.java index b98fdf6d4..72770ec8f 100644 --- a/shared/src/main/java/com/couchbase/lite/DocumentReplication.java +++ b/shared/src/main/java/com/couchbase/lite/DocumentReplication.java @@ -32,7 +32,7 @@ public final class DocumentReplication { //--------------------------------------------- private final Replicator replicator; private final List documents; - private boolean pushing; + private final boolean pushing; //--------------------------------------------- // Constructors diff --git a/shared/src/main/java/com/couchbase/lite/Expression.java b/shared/src/main/java/com/couchbase/lite/Expression.java index b01859e72..95ae39f66 100644 --- a/shared/src/main/java/com/couchbase/lite/Expression.java +++ b/shared/src/main/java/com/couchbase/lite/Expression.java @@ -323,8 +323,8 @@ static final class FunctionExpression extends Expression { //--------------------------------------------- // member variables //--------------------------------------------- - private String func; - private List params; + private final String func; + private final List params; //--------------------------------------------- // Constructors diff --git a/shared/src/main/java/com/couchbase/lite/FullTextExpression.java b/shared/src/main/java/com/couchbase/lite/FullTextExpression.java index f7d4a50d1..8de4e745a 100644 --- a/shared/src/main/java/com/couchbase/lite/FullTextExpression.java +++ b/shared/src/main/java/com/couchbase/lite/FullTextExpression.java @@ -30,8 +30,8 @@ static final class FullTextMatchExpression extends Expression { //--------------------------------------------- // member variables //--------------------------------------------- - private String indexName; - private String text; + private final String indexName; + private final String text; //--------------------------------------------- // Constructors @@ -68,7 +68,7 @@ public static FullTextExpression index(@NonNull String name) { //--------------------------------------------- // member variables //--------------------------------------------- - private String name; + private final String name; //--------------------------------------------- // Constructors diff --git a/shared/src/main/java/com/couchbase/lite/Log.java b/shared/src/main/java/com/couchbase/lite/Log.java index 6f5575544..bffe58e5f 100644 --- a/shared/src/main/java/com/couchbase/lite/Log.java +++ b/shared/src/main/java/com/couchbase/lite/Log.java @@ -28,13 +28,15 @@ * custom. */ public final class Log { + // Singleton instance. private final ConsoleLogger consoleLogger = new ConsoleLogger(); + + // Singleton instance. private final FileLogger fileLogger = new FileLogger(); + private Logger customLogger; - //--------------------------------------------- - // Constructor should not be exposed (singleton) - //--------------------------------------------- + // Singleton instance accessible from Database.log Log() { C4Log.setCallbackLevel(LogLevel.WARNING.getValue()); } @@ -55,9 +57,7 @@ public ConsoleLogger getConsole() { * @return The logger that writes to log files */ @NonNull - public FileLogger getFile() { - return fileLogger; - } + public FileLogger getFile() { return fileLogger; } /** * Gets the custom logger that was registered by the diff --git a/shared/src/main/java/com/couchbase/lite/Logger.java b/shared/src/main/java/com/couchbase/lite/Logger.java index 81652a3ee..a09165639 100644 --- a/shared/src/main/java/com/couchbase/lite/Logger.java +++ b/shared/src/main/java/com/couchbase/lite/Logger.java @@ -26,7 +26,6 @@ * implementing this interface. */ public interface Logger { - /** * Gets the level that will be logged via this logger. * diff --git a/shared/src/main/java/com/couchbase/lite/NetworkReachabilityListener.java b/shared/src/main/java/com/couchbase/lite/NetworkReachabilityListener.java index 7197aa0c0..68ea0de68 100644 --- a/shared/src/main/java/com/couchbase/lite/NetworkReachabilityListener.java +++ b/shared/src/main/java/com/couchbase/lite/NetworkReachabilityListener.java @@ -18,7 +18,7 @@ package com.couchbase.lite; /** - * Classes that want to register to the NetworkReachabilityManager to be notified of + * Classes that want to register to the AbstractNetworkReachabilityManager to be notified of * network reachability events should implment this interface. */ abstract class NetworkReachabilityListener { diff --git a/shared/src/main/java/com/couchbase/lite/Parameters.java b/shared/src/main/java/com/couchbase/lite/Parameters.java index 6f85c3d54..28e732f2b 100644 --- a/shared/src/main/java/com/couchbase/lite/Parameters.java +++ b/shared/src/main/java/com/couchbase/lite/Parameters.java @@ -46,7 +46,7 @@ public final class Parameters { public Parameters() { this(null); } public Parameters(Parameters parameters) { - map = (parameters == null) ? new HashMap() : new HashMap<>(parameters.map); + map = (parameters == null) ? new HashMap<>() : new HashMap<>(parameters.map); } //--------------------------------------------- diff --git a/shared/src/main/java/com/couchbase/lite/internal/core/C4DatabaseObserver.java b/shared/src/main/java/com/couchbase/lite/internal/core/C4DatabaseObserver.java index 94cdaf55c..7ef009db4 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/core/C4DatabaseObserver.java +++ b/shared/src/main/java/com/couchbase/lite/internal/core/C4DatabaseObserver.java @@ -29,7 +29,7 @@ public class C4DatabaseObserver { // Long: handle of C4DatabaseObserver native address // C4DatabaseObserver: Java class holds handle private static final Map reverseLookupTable - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); /** * Callback invoked by a database observer. diff --git a/shared/src/main/java/com/couchbase/lite/internal/core/C4DocumentObserver.java b/shared/src/main/java/com/couchbase/lite/internal/core/C4DocumentObserver.java index b8339e23a..43d7ede95 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/core/C4DocumentObserver.java +++ b/shared/src/main/java/com/couchbase/lite/internal/core/C4DocumentObserver.java @@ -30,7 +30,7 @@ public class C4DocumentObserver { // Long: handle of C4DatabaseObserver native address // C4DocumentObserver: Java class holds handle private static final Map reverseLookupTable - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); /** * Callback invoked by a database observer. diff --git a/shared/src/main/java/com/couchbase/lite/internal/core/C4Error.java b/shared/src/main/java/com/couchbase/lite/internal/core/C4Error.java index 92baf0d79..c4edcd2a7 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/core/C4Error.java +++ b/shared/src/main/java/com/couchbase/lite/internal/core/C4Error.java @@ -18,9 +18,9 @@ package com.couchbase.lite.internal.core; public class C4Error { - private int domain; // C4Error.domain - private int code; // C4Error.code - private int internalInfo; // C4Error.internal_info + private final int domain; // C4Error.domain + private final int code; // C4Error.code + private final int internalInfo; // C4Error.internal_info public C4Error() { domain = 0; // C4Error.domain diff --git a/shared/src/main/java/com/couchbase/lite/internal/core/C4Replicator.java b/shared/src/main/java/com/couchbase/lite/internal/core/C4Replicator.java index 73e39ea89..4fa0411aa 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/core/C4Replicator.java +++ b/shared/src/main/java/com/couchbase/lite/internal/core/C4Replicator.java @@ -18,13 +18,13 @@ package com.couchbase.lite.internal.core; -import android.util.Log; - import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.couchbase.lite.LiteCoreException; +import com.couchbase.lite.LogDomain; +import com.couchbase.lite.internal.support.Log; /** @@ -32,9 +32,6 @@ * This class and its members are referenced by name, from native code. */ public class C4Replicator { - private static final String TAG = "C4Repl"; - - //------------------------------------------------------------------------- // Constants //------------------------------------------------------------------------- @@ -47,10 +44,10 @@ public class C4Replicator { // Long: handle of C4Replicator native address // C4Replicator: Java class holds handle private static final Map reverseLookupTable - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); private static final Map contextToC4ReplicatorMap - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); //------------------------------------------------------------------------- // Member Variables @@ -76,7 +73,7 @@ private static void statusChangedCallback(long handle, C4ReplicatorStatus status private static void documentEndedCallback(long handle, boolean pushing, C4DocumentEnded[] documentsEnded) { final C4Replicator repl = reverseLookupTable.get(handle); - Log.e(TAG, "documentErrorCallback() handle -> " + handle + ", pushing -> " + pushing); + Log.d(LogDomain.REPLICATOR, "documentErrorCallback() handle -> " + handle + ", pushing -> " + pushing); if (repl != null && repl.listener != null) { repl.listener.documentEnded(repl, pushing, documentsEnded, @@ -187,7 +184,7 @@ static native long createWithSocket( private long handle; // hold pointer to C4Replicator - private C4ReplicatorListener listener = null; + private C4ReplicatorListener listener; private C4ReplicationFilter pushFilter; private C4ReplicationFilter pullFilter; @@ -261,9 +258,13 @@ static native long createWithSocket( // It was introduced during the massive refactor to clean up the code, 3/13/2019 public void free() { if (handle != 0L) { - Log.d(TAG, "handle: " + handle); - Log.d(TAG, "replicatorContext: " + replicatorContext + " $" + replicatorContext.getClass()); - Log.d(TAG, "socketFactoryContext: " + socketFactoryContext + " $" + socketFactoryContext.getClass()); + Log.d(LogDomain.REPLICATOR, "handle: " + handle); + Log.d( + LogDomain.REPLICATOR, + "replicatorContext: " + replicatorContext + " $" + replicatorContext.getClass()); + Log.d( + LogDomain.REPLICATOR, + "socketFactoryContext: " + socketFactoryContext + " $" + socketFactoryContext.getClass()); free(handle, replicatorContext, socketFactoryContext); handle = 0L; } @@ -279,7 +280,7 @@ public void stop() { } public C4ReplicatorStatus getStatus() { - return (handle == 0L) ? null : getStatus(handle); + return (handle == 0L) ? null : getStatus(handle); } public byte[] getResponseHeaders() { diff --git a/shared/src/main/java/com/couchbase/lite/internal/core/C4Socket.java b/shared/src/main/java/com/couchbase/lite/internal/core/C4Socket.java index b91cd6954..5b815cd1d 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/core/C4Socket.java +++ b/shared/src/main/java/com/couchbase/lite/internal/core/C4Socket.java @@ -88,15 +88,15 @@ public abstract class C4Socket { // Long: handle of C4Socket native address // C4Socket: Java class holds handle protected static final Map reverseLookupTable - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); // Map between SocketFactory Context and SocketFactory Class public static final Map socketFactory - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); // Map between SocketFactory Context and Replicator public static final Map socketFactoryContext - = Collections.synchronizedMap(new HashMap()); + = Collections.synchronizedMap(new HashMap<>()); @SuppressWarnings("unchecked") private static void open( diff --git a/shared/src/main/java/com/couchbase/lite/internal/fleece/FLDict.java b/shared/src/main/java/com/couchbase/lite/internal/fleece/FLDict.java index 75b4fd97e..078641aa4 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/fleece/FLDict.java +++ b/shared/src/main/java/com/couchbase/lite/internal/fleece/FLDict.java @@ -40,7 +40,7 @@ public class FLDict { * @return FLValue */ static native long get(long dict, byte[] keyString); - private long handle; // hold pointer to FLDict + private final long handle; // hold pointer to FLDict //------------------------------------------------------------------------- // public methods diff --git a/shared/src/main/java/com/couchbase/lite/internal/fleece/MArray.java b/shared/src/main/java/com/couchbase/lite/internal/fleece/MArray.java index bd73d90af..647b3dc3a 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/fleece/MArray.java +++ b/shared/src/main/java/com/couchbase/lite/internal/fleece/MArray.java @@ -49,7 +49,7 @@ protected void initInSlot(MValue mv, MCollection parent, boolean isMutable) { public void initAsCopyOf(MArray array, boolean isMutable) { super.initAsCopyOf(array, isMutable); baseArray = array != null ? array.getBaseArray() : null; - values = array != null ? new ArrayList<>(array.values) : new ArrayList(); + values = array != null ? new ArrayList<>(array.values) : new ArrayList<>(); } /* Properties */ diff --git a/shared/src/main/java/com/couchbase/lite/internal/replicator/CBLWebSocket.java b/shared/src/main/java/com/couchbase/lite/internal/replicator/AbstractCBLWebSocket.java similarity index 90% rename from shared/src/main/java/com/couchbase/lite/internal/replicator/CBLWebSocket.java rename to shared/src/main/java/com/couchbase/lite/internal/replicator/AbstractCBLWebSocket.java index b96e25c8d..3ef78dbbb 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/replicator/CBLWebSocket.java +++ b/shared/src/main/java/com/couchbase/lite/internal/replicator/AbstractCBLWebSocket.java @@ -17,7 +17,7 @@ // package com.couchbase.lite.internal.replicator; -import android.system.ErrnoException; +import android.support.annotation.NonNull; import java.io.IOException; import java.io.InputStream; @@ -74,19 +74,8 @@ import com.couchbase.lite.internal.support.Log; -/** - * NOTE: CBLWebSocket class should be public as this class is instantiated - * from com.couchbase.litecore package. - */ -public final class CBLWebSocket extends C4Socket { - //------------------------------------------------------------------------- - // Constants - //------------------------------------------------------------------------- +public class AbstractCBLWebSocket extends C4Socket { private static final LogDomain TAG = LogDomain.NETWORK; - // Posix errno values with Android. - // from sysroot/usr/include/asm-generic/errno.h - private static final int ECONNRESET = 104; // java.net.SocketException - private static final int ECONNREFUSED = 111; // java.net.ConnectException /** * Workaround to enable both TLS1.1 and TLS1.2 for Android API 16 - 19. @@ -154,7 +143,7 @@ class CBLWebSocketListener extends WebSocketListener { @Override public void onOpen(WebSocket webSocket, Response response) { Log.v(TAG, "WebSocketListener.onOpen() response -> " + response); - CBLWebSocket.this.webSocket = webSocket; + AbstractCBLWebSocket.this.webSocket = webSocket; receivedHTTPResponse(response); Log.i(TAG, "CBLWebSocket CONNECTED!"); opened(handle); @@ -237,7 +226,7 @@ else if (scheme.equalsIgnoreCase(C4Replicator.C4_REPLICATOR_TLS_SCHEME_2)) { scheme = WEBSOCKET_SECURE_CONNECTION_SCHEME; } - final CBLWebSocket c4sock; + final AbstractCBLWebSocket c4sock; try { c4sock = new CBLWebSocket(socket, scheme, hostname, port, path, options); } @@ -268,7 +257,13 @@ else if (scheme.equalsIgnoreCase(C4Replicator.C4_REPLICATOR_TLS_SCHEME_2)) { //------------------------------------------------------------------------- // constructor //------------------------------------------------------------------------- - CBLWebSocket(long handle, String scheme, String hostname, int port, String path, Map options) + protected AbstractCBLWebSocket( + long handle, + String scheme, + String hostname, + int port, + String path, + Map options) throws GeneralSecurityException, URISyntaxException { super(handle); this.uri = new URI(checkScheme(scheme), null, hostname, port, path, null, null); @@ -286,12 +281,10 @@ protected void send(byte[] allocatedData) { } @Override - protected void completedReceive(long byteCount) { - } + protected void completedReceive(long byteCount) { } @Override - protected void close() { - } + protected void close() { } @Override protected void requestClose(int status, String message) { @@ -307,14 +300,17 @@ protected void requestClose(int status, String message) { } } + protected boolean handleClose(Throwable error) { return false; } + + //------------------------------------------------------------------------- + // private methods + //------------------------------------------------------------------------- + private void start() { Log.v(TAG, String.format(Locale.ENGLISH, "CBLWebSocket connecting to %s...", uri)); httpClient.newWebSocket(newRequest(), wsListener); } - //------------------------------------------------------------------------- - // private methods - //------------------------------------------------------------------------- private OkHttpClient setupOkHttpClient() throws GeneralSecurityException { final OkHttpClient.Builder builder = new OkHttpClient.Builder(); @@ -346,7 +342,7 @@ private Authenticator setupAuthenticator() { if (username != null && password != null) { return new Authenticator() { @Override - public Request authenticate(Route route, Response response) { + public Request authenticate(@NonNull Route route, @NonNull Response response) { // http://www.ietf.org/rfc/rfc2617.txt Log.v(TAG, "Authenticating for response: " + response); @@ -469,56 +465,42 @@ private void didClose(int code, String reason) { private void didClose(Throwable error) { if (error == null) { closed(handle, C4Constants.C4ErrorDomain.WebSocketDomain, 0, null); + return; } - // TODO: Following codes works with only Android. - else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP && - error.getCause() != null && - error.getCause().getCause() != null && - error.getCause().getCause() instanceof ErrnoException) { - final ErrnoException e = (ErrnoException) error.getCause().getCause(); - closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, e != null ? e.errno : 0, null); - } + + if (handleClose(error)) { return; } + // TLS Certificate error - else if (error.getCause() != null && - error.getCause() instanceof java.security.cert.CertificateException) { + if (error.getCause() instanceof java.security.cert.CertificateException) { closed( handle, C4Constants.C4ErrorDomain.NetworkDomain, C4Constants.NetworkError.kC4NetErrTLSCertUntrusted, null); + return; } + // SSLPeerUnverifiedException - else if (error instanceof javax.net.ssl.SSLPeerUnverifiedException) { + if (error instanceof javax.net.ssl.SSLPeerUnverifiedException) { closed( handle, C4Constants.C4ErrorDomain.NetworkDomain, C4Constants.NetworkError.kC4NetErrTLSCertUntrusted, null); + return; } - // ConnectException - else if (error instanceof java.net.ConnectException) { - closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, ECONNREFUSED, null); - } - // SocketException - else if (error instanceof java.net.SocketException) { - closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, ECONNRESET, null); - } - // EOFException - else if (error instanceof java.io.EOFException) { - closed(handle, C4Constants.C4ErrorDomain.POSIXDomain, ECONNRESET, null); - } + // UnknownHostException - this is thrown if Airplane mode, offline - else if (error instanceof UnknownHostException) { + if (error instanceof UnknownHostException) { closed( handle, C4Constants.C4ErrorDomain.NetworkDomain, C4Constants.NetworkError.kC4NetErrUnknownHost, null); + return; } - // Unknown - else { - closed(handle, C4Constants.C4ErrorDomain.WebSocketDomain, 0, null); - } + + closed(handle, C4Constants.C4ErrorDomain.WebSocketDomain, 0, null); } //------------------------------------------------------------------------- diff --git a/shared/src/main/java/com/couchbase/lite/internal/support/Log.java b/shared/src/main/java/com/couchbase/lite/internal/support/Log.java index e691b8aee..20d7ece25 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/support/Log.java +++ b/shared/src/main/java/com/couchbase/lite/internal/support/Log.java @@ -31,7 +31,6 @@ * Couchbase Lite Internal Log Utility. */ public final class Log { - public static final int C4LOG_DEBUG = C4Constants.C4LogLevel.kC4LogDebug; public static final int C4LOG_VERBOSE = C4Constants.C4LogLevel.kC4LogVerbose; public static final int C4LOG_INFO = C4Constants.C4LogLevel.kC4LogInfo; diff --git a/shared/src/main/java/com/couchbase/lite/internal/support/Run.java b/shared/src/main/java/com/couchbase/lite/internal/support/Run.java index 1126839bb..6f55ca0fb 100644 --- a/shared/src/main/java/com/couchbase/lite/internal/support/Run.java +++ b/shared/src/main/java/com/couchbase/lite/internal/support/Run.java @@ -23,7 +23,7 @@ public final class Run { - private static final HashSet Instances = new HashSet<>(); + private static final HashSet INSTANCES = new HashSet<>(); public static synchronized void once(@NonNull String tag, @NonNull Runnable action) { if (tag == null) { @@ -34,11 +34,11 @@ public static synchronized void once(@NonNull String tag, @NonNull Runnable acti throw new IllegalArgumentException("action cannot be null"); } - if (Instances.contains(tag)) { + if (INSTANCES.contains(tag)) { return; } - Instances.add(tag); + INSTANCES.add(tag); action.run(); } } diff --git a/shared/src/main/java/okhttp3/internal/tls/CustomHostnameVerifier.java b/shared/src/main/java/okhttp3/internal/tls/CustomHostnameVerifier.java index add50b153..a7e3c9935 100644 --- a/shared/src/main/java/okhttp3/internal/tls/CustomHostnameVerifier.java +++ b/shared/src/main/java/okhttp3/internal/tls/CustomHostnameVerifier.java @@ -14,7 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Original Code: https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/tls/OkHostnameVerifier.java + * Original Code: https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/tls + * /OkHostnameVerifier.java * Patch : https://github.com/square/okhttp/pull/2214/commits/56cf2e64306449adf63677f23d06e38503256ad4 * Issue & PR : https://github.com/square/okhttp/pull/2214 */ @@ -36,6 +37,7 @@ import static okhttp3.internal.Util.verifyAsIpAddress; + /** * A HostnameVerifier consistent with RFC 2818. */ @@ -57,15 +59,16 @@ public boolean verify(String host, SSLSession session) { try { Certificate[] certificates = session.getPeerCertificates(); return verify(host, (X509Certificate) certificates[0]); - } catch (SSLException e) { + } + catch (SSLException e) { return false; } } public boolean verify(String host, X509Certificate certificate) { return verifyAsIpAddress(host) - ? verifyIpAddress(host, certificate) - : verifyHostname(host, certificate); + ? verifyIpAddress(host, certificate) + : verifyHostname(host, certificate); } /** @@ -82,16 +85,9 @@ private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) { X500Principal principal = certificate.getSubjectX500Principal(); // RFC 2818 advises using the most specific name for matching. String cn = new DistinguishedNameParser(principal).findMostSpecific("cn"); - if (cn != null) { - if (ipAddress.equalsIgnoreCase(cn)) { - return true; - } - }else{ - // NOTE: In case of empty Common Name (CN), not checking - return true; - } - return false; + // NOTE: In case of empty Common Name (CN), not checking + return (cn == null) || ipAddress.equalsIgnoreCase(cn); } /** @@ -114,7 +110,8 @@ private boolean verifyHostname(String hostname, X509Certificate certificate) { String cn = new DistinguishedNameParser(principal).findMostSpecific("cn"); if (cn != null) { return verifyHostname(hostname, cn); - }else{ + } + else { // NOTE: In case of empty Common Name (CN), not checking return true; } @@ -156,7 +153,8 @@ private static List getSubjectAltNames(X509Certificate certificate, int } } return result; - } catch (CertificateParsingException e) { + } + catch (CertificateParsingException e) { return Collections.emptyList(); } } @@ -172,12 +170,12 @@ public boolean verifyHostname(String hostname, String pattern) { // Basic sanity checks // Check length == 0 instead of .isEmpty() to support Java 5. if ((hostname == null) || (hostname.length() == 0) || (hostname.startsWith(".")) - || (hostname.endsWith(".."))) { + || (hostname.endsWith(".."))) { // Invalid domain name return false; } if ((pattern == null) || (pattern.length() == 0) || (pattern.startsWith(".")) - || (pattern.endsWith(".."))) { + || (pattern.endsWith(".."))) { // Invalid pattern/domain name return false; } @@ -246,13 +244,7 @@ public boolean verifyHostname(String hostname, String pattern) { // Check that asterisk did not match across domain name labels. int suffixStartIndexInHostname = hostname.length() - suffix.length(); - if ((suffixStartIndexInHostname > 0) - && (hostname.lastIndexOf('.', suffixStartIndexInHostname - 1) != -1)) { - // Asterisk is matching across domain name labels -- not permitted. - return false; - } - - // hostname matches pattern - return true; + return (suffixStartIndexInHostname <= 0) + || (hostname.lastIndexOf('.', suffixStartIndexInHostname - 1) == -1); } }