diff --git a/common-api/src/main/kotlin/org/apache/http/util/EntityUtils.kt b/common-api/src/main/kotlin/org/apache/http/util/EntityUtils.kt
index 2145c31e..9d94aca6 100644
--- a/common-api/src/main/kotlin/org/apache/http/util/EntityUtils.kt
+++ b/common-api/src/main/kotlin/org/apache/http/util/EntityUtils.kt
@@ -87,7 +87,7 @@ object EntityUtils {
@JvmOverloads
fun toString(entity: HttpEntity, defaultCharset: Charset? = null): String? {
Args.notNull(entity, "Entity")
- return entity.content?.use { instream ->
+ return entity.content?.use { inStream ->
Args.check(entity.contentLength <= 2147483647L, "HTTP entity too large to be buffered in memory")
var i = entity.contentLength.toInt()
if (i < 0) {
@@ -115,7 +115,7 @@ object EntityUtils {
charset = HTTP.DEF_CONTENT_CHARSET
}
- val reader = InputStreamReader(instream, charset!!)
+ val reader = InputStreamReader(inStream, charset!!)
val buffer = CharArrayBuffer(i)
val tmp = CharArray(1024)
diff --git a/idea-plugin/build.gradle b/idea-plugin/build.gradle
index 7cb8a56c..2641e73b 100644
--- a/idea-plugin/build.gradle
+++ b/idea-plugin/build.gradle
@@ -96,12 +96,12 @@ dependencies {
// compile fileTree(dir: 'libs', include: ['*.jar'])
- compile('com.itangcent:intellij-idea:0.1.8-SNAPSHOT') {
+ compile('com.itangcent:intellij-idea:0.1.9-SNAPSHOT') {
exclude group: 'com.google.inject'
exclude group: 'com.google.code.gson'
}
- compile('com.itangcent:intellij-kotlin-support:0.1.8-SNAPSHOT') {
+ compile('com.itangcent:intellij-kotlin-support:0.1.9-SNAPSHOT') {
exclude group: 'com.google.inject'
exclude group: 'com.google.code.gson'
}
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt
index 784f83ae..61e7cab6 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt
@@ -7,13 +7,14 @@ import com.intellij.openapi.ui.Messages
import com.itangcent.common.model.Doc
import com.itangcent.idea.plugin.Worker
import com.itangcent.idea.plugin.api.export.ClassExporter
-import com.itangcent.idea.plugin.api.export.RequestHelper
+import com.itangcent.idea.plugin.settings.SettingBinder
+import com.itangcent.idea.utils.Charsets
import com.itangcent.idea.utils.FileSaveHelper
import com.itangcent.intellij.context.ActionContext
import com.itangcent.intellij.logger.Logger
+import com.itangcent.intellij.logger.traceError
import com.itangcent.intellij.psi.SelectedHelper
import com.itangcent.intellij.util.ActionUtils
-import com.itangcent.intellij.logger.traceError
import java.util.*
@Singleton
@@ -34,6 +35,9 @@ class MarkdownApiExporter {
@Inject
private val markdownFormatter: MarkdownFormatter? = null
+ @Inject
+ private val settingBinder: SettingBinder? = null
+
fun export() {
logger!!.info("Start find apis...")
@@ -78,7 +82,8 @@ class MarkdownApiExporter {
docs.clear()
actionContext!!.runAsync {
try {
- fileSaveHelper!!.saveOrCopy(apiInfo, {
+ fileSaveHelper!!.saveOrCopy(apiInfo, Charsets.forName(settingBinder!!.read().outputCharset)?.charset()
+ ?: kotlin.text.Charsets.UTF_8, {
logger.info("Exported data are copied to clipboard,you can paste to a md file now")
}, {
logger.info("Apis save success")
@@ -86,12 +91,12 @@ class MarkdownApiExporter {
logger.info("Apis save failed")
}
} catch (e: Exception) {
- logger.traceError("Apis save failed",e)
+ logger.traceError("Apis save failed", e)
}
}
} catch (e: Exception) {
- logger.traceError("Apis save failed",e)
+ logger.traceError("Apis save failed", e)
}
}
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt
index 931a8908..e0777ed4 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt
@@ -26,6 +26,7 @@ import com.itangcent.idea.plugin.script.GroovyActionExtLoader
import com.itangcent.idea.plugin.script.LoggerBuffer
import com.itangcent.idea.plugin.settings.SettingBinder
import com.itangcent.idea.psi.PsiResource
+import com.itangcent.idea.utils.Charsets
import com.itangcent.idea.utils.CustomizedPsiClassHelper
import com.itangcent.idea.utils.FileSaveHelper
import com.itangcent.intellij.config.ConfigReader
@@ -63,7 +64,6 @@ class SuvApiExporter {
@Inject
private val classExporter: ClassExporter? = null
-
@Suppress("UNCHECKED_CAST")
fun showExportWindow() {
@@ -447,6 +447,9 @@ class SuvApiExporter {
@Inject
private val markdownFormatter: MarkdownFormatter? = null
+ @Inject
+ private val settingBinder: SettingBinder? = null
+
override fun actionName(): String {
return "MarkdownExportAction"
}
@@ -481,7 +484,8 @@ class SuvApiExporter {
docs.clear()
actionContext!!.runAsync {
try {
- fileSaveHelper!!.saveOrCopy(apiInfo, {
+ fileSaveHelper!!.saveOrCopy(apiInfo, Charsets.forName(settingBinder!!.read().outputCharset)?.charset()
+ ?: kotlin.text.Charsets.UTF_8, {
logger!!.info("Exported data are copied to clipboard,you can paste to a md file now")
}, {
logger!!.info("Apis save success")
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt
index 9f2518ca..0cfe6e8e 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt
@@ -126,7 +126,7 @@ class RecommendConfigReader : ConfigReader {
private const val config_name = ".recommend.easy.api.config"
// private const val config_version = ".recommend.easy.api.config.version"
- private const val curr_version = "0.0.7"
+ private const val curr_version = "0.0.8"
//$version$content
private fun loadRecommendConfig(): String {
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form
index af3f975e..fdb22ff0 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form
@@ -239,19 +239,52 @@
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt
index 7bb462c5..7f616b6e 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt
@@ -20,6 +20,7 @@ import com.itangcent.idea.icons.EasyIcons
import com.itangcent.idea.icons.iconOnly
import com.itangcent.idea.plugin.config.RecommendConfigReader
import com.itangcent.idea.plugin.settings.Settings
+import com.itangcent.idea.utils.Charsets
import com.itangcent.idea.utils.ConfigurableLogger
import com.itangcent.idea.utils.SwingUtils
import com.itangcent.intellij.extend.rx.AutoComputer
@@ -29,7 +30,6 @@ import com.itangcent.intellij.logger.Logger
import com.itangcent.suv.http.ConfigurableHttpClientProvider
import org.apache.commons.io.FileUtils
import java.io.File
-import java.nio.charset.Charset
import java.util.*
import javax.swing.*
@@ -73,6 +73,8 @@ class EasyApiSettingGUI {
private var outputDemoCheckBox: JCheckBox? = null
+ private var outputCharsetComboBox: JComboBox? = null
+
private var inferEnableCheckBox: JCheckBox? = null
private var maxDeepTextField: JTextField? = null
@@ -186,6 +188,13 @@ class EasyApiSettingGUI {
.filter { throttleHelper.acquire("settings.logLevel", 300) }
.eval { (it ?: ConfigurableLogger.CoarseLogLevel.LOW).getLevel() }
+ outputCharsetComboBox!!.model = DefaultComboBoxModel(Charsets.SUPPORTED_CHARSETS)
+
+ autoComputer.bind(this, "settings.outputCharset")
+ .with(this.outputCharsetComboBox!!)
+ .filter { throttleHelper.acquire("settings.outputCharset", 300) }
+ .eval { (it ?: Charsets.UTF_8).displayName() }
+
autoComputer.bind(this.previewTextArea!!)
.with(this, "settings.recommendConfigs")
.eval { configs -> RecommendConfigReader.buildRecommendConfig(configs.split(",")) }
@@ -226,6 +235,7 @@ class EasyApiSettingGUI {
autoComputer.value(this::settings, settings.copy())
this.logLevelComboBox!!.selectedItem = ConfigurableLogger.CoarseLogLevel.toLevel(settings.logLevel)
+ this.outputCharsetComboBox!!.selectedItem = Charsets.forName(settings.outputCharset)
val configs = settings.recommendConfigs.split(",")
RecommendConfigReader.RECOMMEND_CONFIG_CODES.forEach {
@@ -378,7 +388,7 @@ class EasyApiSettingGUI {
}
val fileWrapper = chooser.save(toSelect, "setting.json")
if (fileWrapper != null) {
- com.itangcent.intellij.util.FileUtils.forceSave(fileWrapper.file.path, GsonUtils.toJson(settings).toByteArray(Charset.defaultCharset()))
+ com.itangcent.intellij.util.FileUtils.forceSave(fileWrapper.file.path, GsonUtils.toJson(settings).toByteArray(kotlin.text.Charsets.UTF_8))
}
}
@@ -397,8 +407,10 @@ class EasyApiSettingGUI {
val files = chooser.choose(null, toSelect)
if (!files.isNullOrEmpty()) {
val virtualFile = files[0]
- val read = com.itangcent.common.utils.FileUtils.read(File(virtualFile.path))
- setSettings(GsonUtils.fromJson(read, Settings::class))
+ val read = com.itangcent.common.utils.FileUtils.read(File(virtualFile.path), kotlin.text.Charsets.UTF_8)
+ if (!read.isNullOrEmpty()) {
+ setSettings(GsonUtils.fromJson(read, Settings::class))
+ }
}
}
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt
index 1c05ea30..6bbae4f9 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt
@@ -1,6 +1,7 @@
package com.itangcent.idea.plugin.settings
import com.itangcent.idea.plugin.config.RecommendConfigReader
+import com.itangcent.idea.utils.Charsets
import com.itangcent.idea.utils.ConfigurableLogger
class Settings {
@@ -29,6 +30,8 @@ class Settings {
var outputDemo: Boolean = true
+ var outputCharset: String = Charsets.UTF_8.displayName()
+
fun copy(): Settings {
val newSetting = Settings()
newSetting.postmanToken = this.postmanToken
@@ -42,6 +45,7 @@ class Settings {
newSetting.recommendConfigs = this.recommendConfigs
newSetting.logLevel = this.logLevel
newSetting.outputDemo = this.outputDemo
+ newSetting.outputCharset = this.outputCharset
return newSetting
}
@@ -62,6 +66,7 @@ class Settings {
if (recommendConfigs != other.recommendConfigs) return false
if (logLevel != other.logLevel) return false
if (outputDemo != other.outputDemo) return false
+ if (outputCharset != other.outputCharset) return false
return true
}
@@ -78,10 +83,10 @@ class Settings {
result = 31 * result + recommendConfigs.hashCode()
result = 31 * result + logLevel
result = 31 * result + outputDemo.hashCode()
+ result = 31 * result + outputCharset.hashCode()
return result
}
-
companion object {
const val DEFAULT_INFER_MAX_DEEP = 4
}
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/Charsets.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/Charsets.kt
new file mode 100644
index 00000000..2c9af858
--- /dev/null
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/Charsets.kt
@@ -0,0 +1,87 @@
+package com.itangcent.idea.utils
+
+import java.nio.charset.Charset
+
+abstract class Charsets {
+
+ companion object {
+
+ val UTF_8 = ImmutableCharset(kotlin.text.Charsets.UTF_8)
+ val US_ASCII = ImmutableCharset(kotlin.text.Charsets.US_ASCII)
+ val UTF_16 = ImmutableCharset(kotlin.text.Charsets.UTF_16)
+ val ISO_8859_1 = ImmutableCharset(kotlin.text.Charsets.ISO_8859_1)
+ val UTF_32 = ImmutableCharset(kotlin.text.Charsets.UTF_32)
+ val GBK = tryLoadCharset("GBK")
+ val FOLLOW_SYSTEM = object : MutableCharset("follow system") {
+ override fun charset(): Charset {
+ return Charset.defaultCharset()
+ }
+ }
+
+ fun forName(charset: String): Charsets? {
+ return SUPPORTED_CHARSETS.firstOrNull { it.displayName() == charset }
+ ?: tryLoadCharset(charset)
+ }
+
+ private fun tryLoadCharset(charset: String): Charsets? {
+ return try {
+ ImmutableCharset(Charset.forName(charset))
+ } catch (e: Exception) {
+ null
+ }
+ }
+
+ val SUPPORTED_CHARSETS: Array
+
+ init {
+ val charsets = ArrayList()
+ charsets.add(FOLLOW_SYSTEM)
+ charsets.add(UTF_8)
+ GBK?.let { charsets.add(it) }
+ charsets.add(US_ASCII)
+ charsets.add(UTF_16)
+ charsets.add(ISO_8859_1)
+ charsets.add(UTF_32)
+ SUPPORTED_CHARSETS = charsets.toTypedArray()
+ }
+ }
+
+ abstract fun charset(): Charset
+
+ abstract fun displayName(): String
+
+ override fun toString(): String {
+ return displayName()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ return charset() == (other as Charsets).charset()
+ }
+
+ override fun hashCode(): Int {
+ return charset().hashCode()
+ }
+
+
+ class ImmutableCharset(private val charset: Charset) : Charsets() {
+
+ override fun charset(): Charset {
+ return this.charset
+ }
+
+ override fun displayName(): String {
+ return charset().displayName()
+ }
+
+ }
+
+ abstract class MutableCharset(private val displayName: String?) : Charsets() {
+
+ override fun displayName(): String {
+ return displayName ?: charset().displayName()
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/FileSaveHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/FileSaveHelper.kt
index 35213367..4e329923 100644
--- a/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/FileSaveHelper.kt
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/FileSaveHelper.kt
@@ -15,6 +15,7 @@ import com.itangcent.intellij.util.FileUtils
import com.itangcent.intellij.util.ToolUtils
import java.io.File
import java.nio.charset.Charset
+import kotlin.text.Charsets
class FileSaveHelper {
@@ -36,6 +37,14 @@ class FileSaveHelper {
onCopy: () -> Unit,
onSaveSuccess: () -> Unit,
onSaveFailed: () -> Unit) {
+ saveOrCopy(info, Charsets.UTF_8, onCopy, onSaveSuccess, onSaveFailed)
+ }
+
+ fun saveOrCopy(info: String?,
+ charset: Charset,
+ onCopy: () -> Unit,
+ onSaveSuccess: () -> Unit,
+ onSaveFailed: () -> Unit) {
if (info == null) return
@@ -59,7 +68,7 @@ class FileSaveHelper {
if (file.isDirectory) {
try {
val defaultFile = getDefaultExportedFile()
- FileUtils.forceSave("${file.path}${File.separator}$defaultFile", info.toByteArray(Charset.defaultCharset()))
+ FileUtils.forceSave("${file.path}${File.separator}$defaultFile", info.toByteArray(charset))
onSaveSuccess()
} catch (e: Exception) {
onSaveFailed()
@@ -69,7 +78,7 @@ class FileSaveHelper {
}
} else {
try {
- FileUtils.forceSave(file, info.toByteArray(Charset.defaultCharset()))
+ FileUtils.forceSave(file, info.toByteArray(charset))
onSaveSuccess()
} catch (e: Exception) {
onSaveFailed()
diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/IOUtils.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/IOUtils.kt
new file mode 100644
index 00000000..1ed7a82b
--- /dev/null
+++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/IOUtils.kt
@@ -0,0 +1,94 @@
+package com.itangcent.idea.utils
+
+import java.io.InputStream
+
+/**
+ * - there's some function copy from [com.sun.org.apache.xerces.internal.xinclude.XIncludeTextReader]
+ */
+object IOUtils {
+
+ fun getEncodingName(stream: InputStream): String? {
+ val b4 = ByteArray(4)
+ var encoding: String? = null
+
+ // this has the potential to throw an exception
+ // it will be fixed when we ensure the stream is rewindable (see note above)
+ stream.mark(4)
+ val count = stream.read(b4, 0, 4)
+ stream.reset()
+ if (count == 4) {
+ encoding = getEncodingName(b4)
+ }
+
+ return encoding
+ }
+
+ /**
+ * REVISIT: This code is taken from com.sun.org.apache.xerces.internal.impl.XMLEntityManager.
+ * Is there any way we can share the code, without having it implemented twice?
+ * I think we should make it public and static in XMLEntityManager. --PJM
+ *
+ * Returns the IANA encoding name that is auto-detected from
+ * the bytes specified, with the endian-ness of that encoding where appropriate.
+ *
+ * @param b4 The first four bytes of the input.
+ * @return the encoding name, or null if no encoding could be detected
+ */
+ fun getEncodingName(b4: ByteArray): String? {
+
+ // UTF-16, with BOM
+ val b0: Int = (b4[0].toInt() and 0xFF)
+ val b1: Int = (b4[1].toInt() and 0xFF)
+ if (b0 == 0xFE && b1 == 0xFF) {
+ // UTF-16, big-endian
+ return "UTF-16BE"
+ }
+ if (b0 == 0xFF && b1 == 0xFE) {
+ // UTF-16, little-endian
+ return "UTF-16LE"
+ }
+
+ // UTF-8 with a BOM
+ val b2: Int = (b4[2].toInt() and 0xFF)
+ if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
+ return "UTF-8"
+ }
+
+ // other encodings
+ val b3: Int = (b4[3].toInt() and 0xFF)
+ if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
+ // UCS-4, big endian (1234)
+ return "ISO-10646-UCS-4"
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
+ // UCS-4, little endian (4321)
+ return "ISO-10646-UCS-4"
+ }
+ if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
+ // UCS-4, unusual octet order (2143)
+ return "ISO-10646-UCS-4"
+ }
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
+ // UCS-4, unusual octect order (3412)
+ return "ISO-10646-UCS-4"
+ }
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
+ // UTF-16, big-endian, no BOM
+ // (or could turn out to be UCS-2...
+ return "UTF-16BE"
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
+ // UTF-16, little-endian, no BOM
+ // (or could turn out to be UCS-2...
+ return "UTF-16LE"
+ }
+ if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
+ // EBCDIC
+ // a la xerces1, return CP037 instead of EBCDIC here
+ return "CP037"
+ }
+
+ // this signals us to use the value from the encoding attribute
+ return null
+ }
+}
\ No newline at end of file
diff --git a/idea-plugin/src/main/resources/.recommend.easy.api.config b/idea-plugin/src/main/resources/.recommend.easy.api.config
index 6b265626..03e2d5d6 100644
--- a/idea-plugin/src/main/resources/.recommend.easy.api.config
+++ b/idea-plugin/src/main/resources/.recommend.easy.api.config
@@ -82,9 +82,11 @@ type.is_file=groovy:it.isExtend("org.springframework.web.multipart.MultipartFile
#[import_spring_properties]
#Import spring properties
+###set ignoreNotFoundFile = true
properties.additional=${module_path}/src/main/resources/application.properties
properties.additional=${module_path}/src/main/resources/application.yml
properties.additional=${module_path}/src/main/resources/application.yaml
+###set ignoreNotFoundFile = false
#[resolve_spring_properties]
#Resolve spring properties