diff --git a/plugins/org.jkiss.dbeaver.model/META-INF/MANIFEST.MF b/plugins/org.jkiss.dbeaver.model/META-INF/MANIFEST.MF index 82c909d20523ded066398f1f5e29013e57ab4135..0d75127e02ee28d114f832afb66a49da469b2566 100644 --- a/plugins/org.jkiss.dbeaver.model/META-INF/MANIFEST.MF +++ b/plugins/org.jkiss.dbeaver.model/META-INF/MANIFEST.MF @@ -74,6 +74,7 @@ Export-Package: org.jkiss.dbeaver, org.jkiss.dbeaver.runtime.resource.links, org.jkiss.dbeaver.runtime.ui, org.jkiss.dbeaver.runtime.ui.console, + org.jkiss.dbeaver.runtime.utils, org.jkiss.dbeaver.utils Bundle-ClassPath: . Require-Bundle: org.eclipse.equinox.security, diff --git a/plugins/org.jkiss.dbeaver.model/OSGI-INF/l10n/bundle.properties b/plugins/org.jkiss.dbeaver.model/OSGI-INF/l10n/bundle.properties index 29e4e030ef54b2099433bfe4714db58e74a4c707..9766a707f87fa731fb16deb303434bd7b58955d9 100644 --- a/plugins/org.jkiss.dbeaver.model/OSGI-INF/l10n/bundle.properties +++ b/plugins/org.jkiss.dbeaver.model/OSGI-INF/l10n/bundle.properties @@ -8,6 +8,7 @@ extension-point.org.jkiss.dbeaver.pluginService.name = Plugin service extension-point.org.jkiss.dbeaver.dataFormatter.name = Data value formatters extension-point.org.jkiss.dbeaver.aggregateFunction.name = Aggregate Functions extension-point.org.jkiss.dbeaver.dataTypeProvider.name = DataType provider +extension-point.org.jkiss.dbeaver.utils.name = Database utilities extension.org.jkiss.dbeaver.DBeaverNature.name = DBeaver Nature diff --git a/plugins/org.jkiss.dbeaver.model/plugin.xml b/plugins/org.jkiss.dbeaver.model/plugin.xml index 912c91e12a0d27b30db22e84dac9327f71571840..8b9d1d14adb1f9d18564a2fb7ecdc52e3a83af61 100644 --- a/plugins/org.jkiss.dbeaver.model/plugin.xml +++ b/plugins/org.jkiss.dbeaver.model/plugin.xml @@ -23,6 +23,7 @@ + diff --git a/plugins/org.jkiss.dbeaver.model/schema/org.jkiss.dbeaver.utils.exsd b/plugins/org.jkiss.dbeaver.model/schema/org.jkiss.dbeaver.utils.exsd new file mode 100644 index 0000000000000000000000000000000000000000..88a11ac6cfcfb4fea94d5ff7f0c19708fba80244 --- /dev/null +++ b/plugins/org.jkiss.dbeaver.model/schema/org.jkiss.dbeaver.utils.exsd @@ -0,0 +1,213 @@ + + + + + + + + + Headless database utilities + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/impl/app/ContentEncrypter.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/encode/ContentEncrypter.java similarity index 98% rename from plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/impl/app/ContentEncrypter.java rename to plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/encode/ContentEncrypter.java index 58e09ad702fd258447678b5917640fce034112c6..474e94e43f3ae3d76d928454eb706940a3447737 100644 --- a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/model/impl/app/ContentEncrypter.java +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/encode/ContentEncrypter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jkiss.dbeaver.model.impl.app; +package org.jkiss.dbeaver.runtime.encode; import org.jkiss.utils.IOUtils; diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUActionUtility.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUActionUtility.java new file mode 100644 index 0000000000000000000000000000000000000000..cb75ae9ce1113390e0794de161146a18ba9d2f9f --- /dev/null +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUActionUtility.java @@ -0,0 +1,30 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org) + * + * 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 org.jkiss.dbeaver.runtime.utils; + +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; + +/** + * Action utility. + */ +public interface DBUActionUtility extends DBUUtility { + + void runUtility(DBRProgressMonitor monitor) throws DBException; + +} diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUScriptUtility.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUScriptUtility.java new file mode 100644 index 0000000000000000000000000000000000000000..800f6573ea6b405d47ed6ec9c71e70b5a1d55343 --- /dev/null +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUScriptUtility.java @@ -0,0 +1,34 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org) + * + * 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 org.jkiss.dbeaver.runtime.utils; + +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; + +/** + * Script utility. + * Generates target database script as a result of utility work + */ +public interface DBUScriptUtility extends DBUUtility { + + String generateScript(DBRProgressMonitor monitor) + throws DBException; + + + +} diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUUtility.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUUtility.java new file mode 100644 index 0000000000000000000000000000000000000000..b800d6bac4ab7ef3745a9565708e6a53f3fafb58 --- /dev/null +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/DBUUtility.java @@ -0,0 +1,39 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org) + * + * 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 org.jkiss.dbeaver.runtime.utils; + +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.app.DBPProject; +import org.jkiss.dbeaver.model.struct.DBSObject; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +/** + * Database utility. + */ +public interface DBUUtility { + + void initTool(DBPProject project, Collection objects) + throws DBException; + + void updateToolSettings(Locale locale, Map properties) + throws DBException; + +} diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/UtilityTaskDescriptor.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/UtilityTaskDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..96626d8509e902ff5a942b9fedde295b1769d1e0 --- /dev/null +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/UtilityTaskDescriptor.java @@ -0,0 +1,88 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org) + * + * 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 org.jkiss.dbeaver.runtime.utils; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.jkiss.dbeaver.Log; +import org.jkiss.dbeaver.model.data.DBDDataFormatter; +import org.jkiss.dbeaver.model.impl.AbstractContextDescriptor; +import org.jkiss.dbeaver.model.impl.PropertyDescriptor; +import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor; + +import java.util.ArrayList; +import java.util.List; + +/** + * DataFormatterDescriptor + */ +public class UtilityTaskDescriptor extends AbstractContextDescriptor +{ + private static final Log log = Log.getLog(UtilityTaskDescriptor.class); + + public static final String EXTENSION_ID = "org.jkiss.dbeaver.utils"; //$NON-NLS-1$ + + private String id; + private String name; + private String description; + private List properties = new ArrayList<>(); + private ObjectType utilityType; + + UtilityTaskDescriptor(IConfigurationElement config) + { + super(config); + + this.id = config.getAttribute("id"); + this.utilityType = new ObjectType(config.getAttribute("class")); + this.name = config.getAttribute("label"); + this.description = config.getAttribute("description"); + + IConfigurationElement[] propElements = config.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP); + for (IConfigurationElement prop : propElements) { + properties.addAll(PropertyDescriptor.extractProperties(prop)); + } + } + + public String getId() + { + return id; + } + + public String getName() + { + return name; + } + + public String getDescription() + { + return description; + } + + public List getProperties() { + return properties; + } + + public DBDDataFormatter createFormatter() throws IllegalAccessException, InstantiationException + { + Class clazz = utilityType.getObjectClass(DBDDataFormatter.class); + if (clazz == null) { + return null; + } + return clazz.newInstance(); + } + +} diff --git a/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/UtilityTaskRegistry.java b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/UtilityTaskRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..96690a2bfc48bf9eb52a0688a351e1fdd8c5bf5d --- /dev/null +++ b/plugins/org.jkiss.dbeaver.model/src/org/jkiss/dbeaver/runtime/utils/UtilityTaskRegistry.java @@ -0,0 +1,253 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org) + * + * 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 org.jkiss.dbeaver.runtime.utils; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.Log; +import org.jkiss.dbeaver.model.app.DBPDataFormatterRegistry; +import org.jkiss.dbeaver.model.data.DBDDataFormatterProfile; +import org.jkiss.dbeaver.model.impl.preferences.SimplePreferenceStore; +import org.jkiss.dbeaver.registry.formatter.DataFormatterProfile; +import org.jkiss.dbeaver.runtime.DBWorkbench; +import org.jkiss.dbeaver.utils.GeneralUtils; +import org.jkiss.utils.CommonUtils; +import org.jkiss.utils.xml.SAXListener; +import org.jkiss.utils.xml.SAXReader; +import org.jkiss.utils.xml.XMLBuilder; +import org.jkiss.utils.xml.XMLException; +import org.xml.sax.Attributes; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class UtilityTaskRegistry implements DBPDataFormatterRegistry +{ + private static final Log log = Log.getLog(UtilityTaskRegistry.class); + + public static final String CONFIG_FILE_NAME = "dataformat-profiles.xml"; //$NON-NLS-1$ + + private static UtilityTaskRegistry instance = null; + + public synchronized static UtilityTaskRegistry getInstance() + { + if (instance == null) { + instance = new UtilityTaskRegistry(Platform.getExtensionRegistry()); + } + return instance; + } + + private final List dataFormatterList = new ArrayList<>(); + private final Map dataFormatterMap = new HashMap<>(); + private DBDDataFormatterProfile globalProfile; + private List customProfiles = null; + + private UtilityTaskRegistry(IExtensionRegistry registry) + { + // Load data formatters from external plugins + { + IConfigurationElement[] extElements = registry.getConfigurationElementsFor(UtilityTaskDescriptor.EXTENSION_ID); + for (IConfigurationElement ext : extElements) { + UtilityTaskDescriptor formatterDescriptor = new UtilityTaskDescriptor(ext); + dataFormatterList.add(formatterDescriptor); + dataFormatterMap.put(formatterDescriptor.getId(), formatterDescriptor); + } + } + } + + public void dispose() + { + this.dataFormatterList.clear(); + this.dataFormatterMap.clear(); + this.globalProfile = null; + } + + //////////////////////////////////////////////////// + // Data formatters + + public List getDataFormatters() + { + return dataFormatterList; + } + + public UtilityTaskDescriptor getDataFormatter(String typeId) + { + return dataFormatterMap.get(typeId); + } + + @Override + public synchronized DBDDataFormatterProfile getGlobalProfile() + { + if (globalProfile == null) { + globalProfile = new DataFormatterProfile( + "Global", + DBWorkbench.getPlatform().getPreferenceStore()); + } + return globalProfile; + } + + @Override + @Nullable + public DBDDataFormatterProfile getCustomProfile(String name) + { + for (DBDDataFormatterProfile profile : getCustomProfiles()) { + if (profile.getProfileName().equals(name)) { + return profile; + } + } + return null; + } + + @Override + public synchronized List getCustomProfiles() + { + if (customProfiles == null) { + loadProfiles(); + } + return customProfiles; + } + + private void loadProfiles() + { + customProfiles = new ArrayList<>(); + + File storeFile = DBWorkbench.getPlatform().getConfigurationFile(CONFIG_FILE_NAME); + if (!storeFile.exists()) { + return; + } + try { + try (InputStream is = new FileInputStream(storeFile)) { + SAXReader parser = new SAXReader(is); + try { + parser.parse(new FormattersParser()); + } catch (XMLException ex) { + throw new DBException("Datasource config parse error", ex); + } + } catch (DBException ex) { + log.warn("Can't load profiles config from " + storeFile.getPath(), ex); + } + } + catch (IOException ex) { + log.warn("IO error", ex); + } + } + + + private void saveProfiles() + { + if (customProfiles == null) { + return; + } + File storeFile = DBWorkbench.getPlatform().getConfigurationFile(CONFIG_FILE_NAME); + try (OutputStream os = new FileOutputStream(storeFile)) { + XMLBuilder xml = new XMLBuilder(os, GeneralUtils.UTF8_ENCODING); + xml.setButify(true); + xml.startElement("profiles"); + for (DBDDataFormatterProfile profile : customProfiles) { + xml.startElement("profile"); + xml.addAttribute("name", profile.getProfileName()); + SimplePreferenceStore store = (SimplePreferenceStore) profile.getPreferenceStore(); + Map props = store.getProperties(); + if (props != null) { + for (Map.Entry entry : props.entrySet()) { + xml.startElement("property"); + xml.addAttribute("name", entry.getKey()); + xml.addAttribute("value", entry.getValue()); + xml.endElement(); + } + } + xml.endElement(); + } + xml.endElement(); + xml.flush(); + } + catch (IOException ex) { + log.warn("IO error", ex); + } + } + + public DBDDataFormatterProfile createCustomProfile(String profileName) + { + getCustomProfiles(); + DBDDataFormatterProfile profile = new DataFormatterProfile(profileName, new CustomProfileStore()); + customProfiles.add(profile); + saveProfiles(); + return profile; + } + + public void deleteCustomProfile(DBDDataFormatterProfile profile) + { + getCustomProfiles(); + if (customProfiles.remove(profile)) { + saveProfiles(); + } + } + + private class CustomProfileStore extends SimplePreferenceStore { + private CustomProfileStore() + { + super(DBWorkbench.getPlatform().getPreferenceStore()); + } + + @Override + public void save() throws IOException + { + saveProfiles(); + } + } + + private class FormattersParser extends SAXListener.BaseListener + { + private String profileName; + private SimplePreferenceStore curStore; + + @Override + public void saxStartElement(SAXReader reader, String namespaceURI, String localName, Attributes atts) + throws XMLException + { + if (localName.equals("profile")) { + curStore = new CustomProfileStore(); + profileName = atts.getValue("name"); + } else if (localName.equals("property")) { + if (curStore != null) { + curStore.setValue( + atts.getValue("name"), + atts.getValue("value")); + } + } + } + + @Override + public void saxEndElement(SAXReader reader, String namespaceURI, String localName) + throws XMLException + { + if (localName.equals("profile")) { + if (!CommonUtils.isEmpty(profileName)) { + DataFormatterProfile profile = new DataFormatterProfile(profileName, curStore); + customProfiles.add(profile); + } + } + } + } + +} diff --git a/plugins/org.jkiss.dbeaver.registry/src/org/jkiss/dbeaver/registry/DataSourceSerializerModern.java b/plugins/org.jkiss.dbeaver.registry/src/org/jkiss/dbeaver/registry/DataSourceSerializerModern.java index e09a4e31cbdf2823940ba76f276fdc5b82ca0f8e..adee0d310b93ef8a3347a9abd14066a848292232 100644 --- a/plugins/org.jkiss.dbeaver.registry/src/org/jkiss/dbeaver/registry/DataSourceSerializerModern.java +++ b/plugins/org.jkiss.dbeaver.registry/src/org/jkiss/dbeaver/registry/DataSourceSerializerModern.java @@ -33,7 +33,7 @@ import org.jkiss.dbeaver.model.app.DBASecureStorage; import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry; import org.jkiss.dbeaver.model.connection.*; import org.jkiss.dbeaver.model.data.json.JSONUtils; -import org.jkiss.dbeaver.model.impl.app.ContentEncrypter; +import org.jkiss.dbeaver.runtime.encode.ContentEncrypter; import org.jkiss.dbeaver.model.impl.preferences.SimplePreferenceStore; import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration; import org.jkiss.dbeaver.model.net.DBWNetworkProfile;