Created
February 27, 2023 19:45
-
-
Save tomix26/9e1ea63353707ef3b5cf4869fc50eec2 to your computer and use it in GitHub Desktop.
Plugin that watches for the occurrence of connection strings in the log and updates the database settings in IntelliJ IDEA accordingly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.intellij.database.psi.DbPsiFacade | |
import com.intellij.database.util.DbImplUtil | |
import com.intellij.execution.filters.ConsoleInputFilterProvider | |
import com.intellij.execution.filters.InputFilter | |
import com.intellij.execution.ui.ConsoleViewContentType as ContentType | |
import com.intellij.openapi.extensions.Extensions | |
import com.intellij.openapi.progress.ProcessCanceledException | |
import com.intellij.openapi.project.Project | |
import com.intellij.openapi.util.Pair | |
import java.util.regex.Matcher | |
import java.util.regex.Pattern | |
import static com.intellij.execution.filters.ConsoleInputFilterProvider.INPUT_FILTER_PROVIDERS | |
import static com.intellij.openapi.util.text.StringUtil.newBombedCharSequence | |
import static liveplugin.PluginUtil.changeGlobalVar | |
import static liveplugin.PluginUtil.show | |
// depends-on-plugin com.intellij.database | |
if (isIdeStartup) return | |
// ===================================================================================== | |
// Customizable mappings of application's data sources to IntelliJ IDEA's database names | |
// ===================================================================================== | |
def dataSourceMapping = [ | |
[ds: "dataSource", db: 'embedded-postgres', driver: 'postgresql'], | |
[ds: "dataSource", db: 'embedded-sqlserver', driver: 'sqlserver'], | |
[ds: "dataSource", db: 'embedded-mariadb', driver: 'mariadb'], | |
[ds: "dataSource", db: 'embedded-mysql', driver: 'mysql'], | |
[ds: "dataSource", db: 'embedded-h2', driver: 'h2'] | |
] | |
Pattern pattern = Pattern.compile(".*JDBC URL to connect to '([^']+)': url='(jdbc:([^:]+):[^']+)'.*") | |
static CharSequence limitAndCutNewline(String text, int maxLength, milliseconds) { | |
int endIndex = text.length() | |
if (text.endsWith("\n")) { | |
--endIndex | |
} | |
if (maxLength >= 0) { | |
endIndex = Math.min(endIndex, maxLength) | |
} | |
def substring = text.substring(0, endIndex) | |
if (milliseconds > 0) { | |
return newBombedCharSequence(substring, milliseconds) | |
} | |
return substring | |
} | |
static def updateDatabase(Project project, String dbName, String jdbcUrl) { | |
DbPsiFacade.getInstance(project).getDataSources() | |
.collect { DbImplUtil.getMaybeLocalDataSource(it) } | |
.findAll { it != null } | |
.findAll { it.name == dbName } | |
.findAll { it.url != jdbcUrl } | |
.forEach { ds -> | |
ds.url = jdbcUrl | |
show("Database '" + ds.name + "' has been updated to '" + jdbcUrl + "'") | |
} | |
} | |
static def databaseUpdater(Project project, Pattern pattern, List<Map<String, String>> mappings) { | |
new InputFilter() { | |
List<Pair<String, ContentType>> applyFilter(String consoleText, ContentType contentType) { | |
if (!consoleText.contains("EmbeddedDatabaseReporter")) { | |
return null | |
} | |
try { | |
CharSequence textForMatching = limitAndCutNewline(consoleText, 500, 1000) | |
Matcher matcher = pattern.matcher(textForMatching) | |
if (matcher.matches()) { | |
def dsName = matcher.group(1) | |
def jdbcUrl = matcher.group(2) | |
def driver = matcher.group(3) | |
def mapping = mappings.find { it.get("ds") == dsName && it.get("driver") == driver } | |
if (mapping) { | |
updateDatabase(project, mapping.get("db"), jdbcUrl) | |
} | |
} | |
} catch (ProcessCanceledException ex) { | |
show("Processing took too long for: " + consoleText) | |
} | |
return null | |
} | |
} | |
} | |
def extensionPoint = Extensions.rootArea.getExtensionPoint(INPUT_FILTER_PROVIDERS) | |
def inputFilterProvider = changeGlobalVar("EmbeddedDatabaseUpdater") { prevInputFilterProvider -> | |
if (prevInputFilterProvider != null && extensionPoint.hasExtension(prevInputFilterProvider)) { | |
extensionPoint.unregisterExtension(prevInputFilterProvider) | |
} | |
new ConsoleInputFilterProvider() { | |
InputFilter[] getDefaultFilters(Project project) { | |
[databaseUpdater(project, pattern, dataSourceMapping)] | |
} | |
} | |
} | |
extensionPoint.registerExtension(inputFilterProvider) |
Hi there,
loving this plugin, worked like a charm the first time. But after the plugin (correctly!) replaces port and db-name in the data source, IntelliJ still displays the old db only:
Even after refreshing and/or reconnecting, it's not possible to connect to the current DB (I refresh the DB after each test):
Maybe it would be better to (re)create the date source instead of editing it?
Update: Seems like IntelliJ insists of using the first found "default database".
Maybe this could be updated and refreshed (sorry, don't know the internals)...?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use it:
plugin.groovy
fileembedded-postgres
,embedded-sqlserver
, etc. - names and types are configurable at the beginning of the script)