Update extension loader

This commit is contained in:
len 2017-01-21 17:49:34 +01:00
parent 7425478a55
commit 03967b67cf
2 changed files with 29 additions and 49 deletions

View file

@ -80,78 +80,58 @@ open class SourceManager(private val context: Context) {
return sources return sources
} }
private fun createExtensionSources(): List<HttpSource> { private fun createExtensionSources(): List<Source> {
val pkgManager = context.packageManager val pkgManager = context.packageManager
val flags = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES val flags = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES
val installedPkgs = pkgManager.getInstalledPackages(flags) val installedPkgs = pkgManager.getInstalledPackages(flags)
val extPkgs = installedPkgs.filter { it.reqFeatures.orEmpty().any { it.name == FEATURE } } val extPkgs = installedPkgs.filter { it.reqFeatures.orEmpty().any { it.name == EXTENSION_FEATURE } }
val sources = mutableListOf<HttpSource>() val sources = mutableListOf<Source>()
for (pkgInfo in extPkgs) { for (pkgInfo in extPkgs) {
val appInfo = pkgManager.getApplicationInfo(pkgInfo.packageName, val appInfo = pkgManager.getApplicationInfo(pkgInfo.packageName,
PackageManager.GET_META_DATA) ?: continue PackageManager.GET_META_DATA) ?: continue
val extName = pkgManager.getApplicationLabel(appInfo).toString()
val data = appInfo.metaData .substringAfter("Tachiyomi: ")
val extName = data.getString(NAME) val version = pkgInfo.versionName
val version = data.getInt(VERSION) var sourceClass = appInfo.metaData.getString(METADATA_SOURCE_CLASS)
val sourceClass = extendClassName(data.getString(SOURCE), pkgInfo.packageName) if (sourceClass.startsWith(".")) {
sourceClass = pkgInfo.packageName + sourceClass
val ext = Extension(extName, appInfo, version, sourceClass)
if (!validateExtension(ext)) {
continue
} }
val instance = loadExtension(ext, pkgManager) val extension = Extension(extName, appInfo, version, sourceClass)
if (instance == null) { try {
Timber.e("Extension error: failed to instance $extName") val instance = loadExtension(extension)
continue sources.add(instance)
} catch (e: Exception) {
Timber.e("Extension load error: $extName. Reason: ${e.message}")
} catch (e: LinkageError) {
Timber.e("Extension load error: $extName. Reason: ${e.message}")
} }
sources.add(instance)
} }
return sources return sources
} }
private fun validateExtension(ext: Extension): Boolean { private fun loadExtension(ext: Extension): Source {
if (ext.version < LIB_VERSION_MIN || ext.version > LIB_VERSION_MAX) { // Validate lib version
Timber.e("Extension error: ${ext.name} has version ${ext.version}, while only versions " val majorLibVersion = ext.version.substringBefore('.').toInt()
if (majorLibVersion < LIB_VERSION_MIN || majorLibVersion > LIB_VERSION_MAX) {
throw Exception("Lib version is $majorLibVersion, while only versions "
+ "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed") + "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed")
return false
} }
return true
}
private fun loadExtension(ext: Extension, pkgManager: PackageManager): HttpSource? { val classLoader = PathClassLoader(ext.appInfo.sourceDir, null, context.classLoader)
return try { return Class.forName(ext.sourceClass, false, classLoader).newInstance() as Source
val classLoader = PathClassLoader(ext.appInfo.sourceDir, null, context.classLoader)
val resources = pkgManager.getResourcesForApplication(ext.appInfo)
Class.forName(ext.sourceClass, false, classLoader).newInstance() as? HttpSource
} catch (e: Exception) {
null
} catch (e: LinkageError) {
null
}
}
private fun extendClassName(className: String, packageName: String): String {
return if (className.startsWith(".")) {
packageName + className
} else {
className
}
} }
class Extension(val name: String, class Extension(val name: String,
val appInfo: ApplicationInfo, val appInfo: ApplicationInfo,
val version: Int, val version: String,
val sourceClass: String) val sourceClass: String)
private companion object { private companion object {
const val FEATURE = "tachiyomi.extension" const val EXTENSION_FEATURE = "tachiyomi.extension"
const val NAME = "tachiyomi.extension.name" const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
const val VERSION = "tachiyomi.extension.version"
const val SOURCE = "tachiyomi.extension.source"
const val LIB_VERSION_MIN = 1 const val LIB_VERSION_MIN = 1
const val LIB_VERSION_MAX = 1 const val LIB_VERSION_MAX = 1
} }

View file

@ -25,12 +25,12 @@ abstract class HttpSource : CatalogueSource {
/** /**
* Network service. * Network service.
*/ */
val network: NetworkHelper by injectLazy() protected val network: NetworkHelper by injectLazy()
/** /**
* Preferences helper. * Preferences helper.
*/ */
val preferences: PreferencesHelper by injectLazy() protected val preferences: PreferencesHelper by injectLazy()
/** /**
* Base url of the website without the trailing slash, like: http://mysite.com * Base url of the website without the trailing slash, like: http://mysite.com