/** Data type resolver */ public class SQLDataTypeResolver extends TemplateVariableResolver { private static final Log log = Log.getLog(SQLDataTypeResolver.class); public SQLDataTypeResolver() { super("type", "Data type"); } @Override protected String[] resolveAll(final TemplateContext context) { final DBCExecutionContext executionContext = ((DBPContextProvider) context).getExecutionContext(); if (executionContext == null) { return super.resolveAll(context); } DBPDataTypeProvider dataTypeProvider = DBUtils.getAdapter(DBPDataTypeProvider.class, executionContext.getDataSource()); if (dataTypeProvider != null) { final Collection<? extends DBSDataType> localDataTypes = dataTypeProvider.getLocalDataTypes(); if (!CommonUtils.isEmpty(localDataTypes)) { String[] result = new String[localDataTypes.size()]; int index = 0; for (DBSDataType dataType : localDataTypes) { result[index++] = dataType.getName(); } return result; } } return super.resolveAll(context); } }
/** Entity resolver */ public class SQLAttributeResolver extends TemplateVariableResolver { private static final Log log = Log.getLog(SQLAttributeResolver.class); public SQLAttributeResolver() { super("column", "Table column"); } @Override protected String[] resolveAll(final TemplateContext context) { final DBCExecutionContext executionContext = ((DBPContextProvider) context).getExecutionContext(); if (executionContext == null) { return super.resolveAll(context); } TemplateVariable tableVariable = ((SQLContext) context).getTemplateVariable("table"); final String tableName = tableVariable == null ? null : tableVariable.getDefaultValue(); if (!CommonUtils.isEmpty(tableName)) { final List<DBSEntityAttribute> attributes = new ArrayList<>(); DBRRunnableWithProgress runnable = new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { List<DBSEntity> entities = new ArrayList<>(); SQLEntityResolver.resolveTables(monitor, executionContext, context, entities); if (!CommonUtils.isEmpty(entities)) { DBSEntity table = DBUtils.findObject(entities, tableName); if (table != null) { attributes.addAll(CommonUtils.safeCollection(table.getAttributes(monitor))); } } } catch (DBException e) { throw new InvocationTargetException(e); } } }; RuntimeUtils.runTask(runnable, "Resolve attributes", 1000); if (!CommonUtils.isEmpty(attributes)) { String[] result = new String[attributes.size()]; for (int i = 0; i < attributes.size(); i++) { DBSEntityAttribute entity = attributes.get(i); result[i] = entity.getName(); } return result; } } return super.resolveAll(context); } @Override public void resolve(TemplateVariable variable, TemplateContext context) { super.resolve(variable, context); if (variable instanceof SQLVariable) { ((SQLVariable) variable).setResolver(this); } } }
static class LoadingUIJob<RESULT> extends AbstractUIJob { private static final Log log = Log.getLog(LoadingUIJob.class); private static final long DELAY = 200; private ILoadService<RESULT> loadService; private ILoadVisualizer<RESULT> visualizer; private DBRProgressMonitor mainMonitor; LoadingUIJob(LoadingJob<RESULT> loadingJob, DBRProgressMonitor mainMonitor) { super(loadingJob.getName()); this.loadService = loadingJob.getLoadingService(); this.visualizer = loadingJob.getVisualizer(); this.mainMonitor = mainMonitor; setSystem(true); } @Override public IStatus runInUIThread(DBRProgressMonitor monitor) { /* if (mainMonitor.isCanceled()) { // Try to cancel current load service try { loadService.cancel(); } catch (InvocationTargetException e) { log.warn("Error while canceling service", e.getTargetException()); } return Status.CANCEL_STATUS; } else { */ if (!visualizer.isCompleted()) { visualizer.visualizeLoading(); schedule(DELAY); } // } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return family == LOADING_FAMILY; } @Override protected void canceling() { super.canceling(); } }
/** Abstract oracle schema object */ public abstract class OracleGlobalObject implements DBSObject, DBPSaveableObject { static final Log log = Log.getLog(OracleGlobalObject.class); private final OracleDataSource dataSource; private boolean persisted; protected OracleGlobalObject(OracleDataSource dataSource, boolean persisted) { this.dataSource = dataSource; this.persisted = persisted; } @Nullable @Override public String getDescription() { return null; } @Override public DBSObject getParentObject() { return dataSource.getContainer(); } @NotNull @Override public OracleDataSource getDataSource() { return dataSource; } @Override public boolean isPersisted() { return persisted; } @Override public void setPersisted(boolean persisted) { this.persisted = persisted; } }
/** PostgreDatabase */ public class PostgreDatabase implements DBSInstance, DBSCatalog, DBPRefreshableObject, DBPStatefulObject, PostgreObject, DBSObjectSelector { private static final Log log = Log.getLog(PostgreDatabase.class); private PostgreDataSource dataSource; private long oid; private String name; private long ownerId; private long encodingId; private String collate; private String ctype; private boolean isTemplate; private boolean allowConnect; private int connectionLimit; private long tablespaceId; public final AuthIdCache authIdCache = new AuthIdCache(); public final AccessMethodCache accessMethodCache = new AccessMethodCache(); public final ForeignDataWrapperCache foreignDataWrapperCache = new ForeignDataWrapperCache(); public final ForeignServerCache foreignServerCache = new ForeignServerCache(); public final LanguageCache languageCache = new LanguageCache(); public final EncodingCache encodingCache = new EncodingCache(); public final TablespaceCache tablespaceCache = new TablespaceCache(); public final SchemaCache schemaCache = new SchemaCache(); public final LongKeyMap<PostgreDataType> dataTypeCache = new LongKeyMap<>(); public PostgreDatabase(PostgreDataSource dataSource, JDBCResultSet dbResult) throws SQLException { this.dataSource = dataSource; this.loadInfo(dbResult); } private void loadInfo(JDBCResultSet dbResult) throws SQLException { this.oid = JDBCUtils.safeGetLong(dbResult, "oid"); this.name = JDBCUtils.safeGetString(dbResult, "datname"); this.ownerId = JDBCUtils.safeGetLong(dbResult, "datdba"); this.encodingId = JDBCUtils.safeGetLong(dbResult, "encoding"); this.collate = JDBCUtils.safeGetString(dbResult, "datcollate"); this.ctype = JDBCUtils.safeGetString(dbResult, "datctype"); this.isTemplate = JDBCUtils.safeGetBoolean(dbResult, "datistemplate"); this.allowConnect = JDBCUtils.safeGetBoolean(dbResult, "datallowconn"); this.connectionLimit = JDBCUtils.safeGetInt(dbResult, "datconnlimit"); this.tablespaceId = JDBCUtils.safeGetLong(dbResult, "dattablespace"); } @NotNull @Override public PostgreDatabase getDatabase() { return this; } @Override public long getObjectId() { return this.oid; } @NotNull @Override @Property(viewable = true, order = 2) public String getName() { return name; } @Nullable @Override public String getDescription() { return null; } @Override public DBSObject getParentObject() { return dataSource.getContainer(); } @NotNull @Override public PostgreDataSource getDataSource() { return dataSource; } @Override public boolean isPersisted() { return true; } /////////////////////////////////////////////////// // Properties @Property(viewable = false, order = 3) public PostgreAuthId getDBA(DBRProgressMonitor monitor) throws DBException { return PostgreUtils.getObjectById(monitor, authIdCache, this, ownerId); } @Property(viewable = false, order = 4) public PostgreTablespace getDefaultTablespace(DBRProgressMonitor monitor) throws DBException { return PostgreUtils.getObjectById(monitor, tablespaceCache, this, tablespaceId); } @Property(viewable = false, order = 5) public PostgreCharset getDefaultEncoding(DBRProgressMonitor monitor) throws DBException { return PostgreUtils.getObjectById(monitor, encodingCache, this, encodingId); } @Property(viewable = false, order = 10) public String getCollate() { return collate; } @Property(viewable = false, order = 11) public String getCtype() { return ctype; } @Property(viewable = false, order = 12) public boolean isTemplate() { return isTemplate; } @Property(viewable = false, order = 13) public boolean isAllowConnect() { return allowConnect; } @Property(viewable = false, order = 14) public int getConnectionLimit() { return connectionLimit; } /////////////////////////////////////////////////// // Instance methods @NotNull @Override public DBCExecutionContext getDefaultContext(boolean meta) { return dataSource.getDefaultContext(meta); } @NotNull @Override public DBCExecutionContext[] getAllContexts() { return dataSource.getAllContexts(); } @NotNull @Override public DBCExecutionContext openIsolatedContext( @NotNull DBRProgressMonitor monitor, @NotNull String purpose) throws DBException { return dataSource.openIsolatedContext(monitor, purpose); } @Override public void close() {} /////////////////////////////////////////////// // Infos @Association public Collection<PostgreAuthId> getAuthIds(DBRProgressMonitor monitor) throws DBException { return authIdCache.getAllObjects(monitor, this); } @Association public Collection<PostgreAccessMethod> getAccessMethods(DBRProgressMonitor monitor) throws DBException { return accessMethodCache.getAllObjects(monitor, this); } @Association public Collection<PostgreForeignDataWrapper> getForeignDataWrappers(DBRProgressMonitor monitor) throws DBException { return foreignDataWrapperCache.getAllObjects(monitor, this); } @Association public Collection<PostgreForeignServer> getForeignServers(DBRProgressMonitor monitor) throws DBException { return foreignServerCache.getAllObjects(monitor, this); } @Association public Collection<PostgreLanguage> getLanguages(DBRProgressMonitor monitor) throws DBException { return languageCache.getAllObjects(monitor, this); } @Association public Collection<PostgreCharset> getEncodings(DBRProgressMonitor monitor) throws DBException { return encodingCache.getAllObjects(monitor, this); } @Association public Collection<PostgreTablespace> getTablespaces(DBRProgressMonitor monitor) throws DBException { return tablespaceCache.getAllObjects(monitor, this); } /////////////////////////////////////////////// // Object container @Association public Collection<PostgreSchema> getSchemas(DBRProgressMonitor monitor) throws DBException { if (this != dataSource.getDefaultInstance()) { throw new DBException("Can't access non-default database"); } // Get all schemas return schemaCache.getAllObjects(monitor, this); } @Nullable public PostgreSchema getCatalogSchema(DBRProgressMonitor monitor) throws DBException { return getSchema(monitor, PostgreConstants.CATALOG_SCHEMA_NAME); } @Nullable PostgreSchema getCatalogSchema() { return schemaCache.getCachedObject(PostgreConstants.CATALOG_SCHEMA_NAME); } void cacheDataTypes(DBRProgressMonitor monitor) throws DBException { dataTypeCache.clear(); // Cache data types for (final PostgreSchema pgSchema : getSchemas(monitor)) { pgSchema.getDataTypes(monitor); } } public PostgreSchema getSchema(DBRProgressMonitor monitor, String name) throws DBException { if (this != dataSource.getDefaultInstance()) { throw new DBException("Can't access non-default database"); } return schemaCache.getObject(monitor, this, name); } public PostgreSchema getSchema(DBRProgressMonitor monitor, long oid) throws DBException { if (this != dataSource.getDefaultInstance()) { throw new DBException("Can't access non-default database"); } for (PostgreSchema schema : schemaCache.getAllObjects(monitor, this)) { if (schema.getObjectId() == oid) { return schema; } } return null; } PostgreTableBase findTable(DBRProgressMonitor monitor, long schemaId, long tableId) throws DBException { PostgreSchema schema = getSchema(monitor, schemaId); if (schema == null) { log.error("Catalog " + schemaId + " not found"); return null; } return schema.getTable(monitor, tableId); } @Override public Collection<? extends DBSObject> getChildren(@NotNull DBRProgressMonitor monitor) throws DBException { return getSchemas(monitor); } @Override public DBSObject getChild(@NotNull DBRProgressMonitor monitor, @NotNull String childName) throws DBException { return getSchema(monitor, childName); } @Override public Class<? extends DBSObject> getChildType(@NotNull DBRProgressMonitor monitor) throws DBException { return PostgreSchema.class; } @Override public void cacheStructure(@NotNull DBRProgressMonitor monitor, int scope) throws DBException {} @Override public DBSObjectState getObjectState() { if (this == dataSource.getDefaultInstance()) { return DBSObjectState.NORMAL; } else { return PostgreConstants.STATE_UNAVAILABLE; } } @Override public void refreshObjectState(@NotNull DBRProgressMonitor monitor) throws DBCException {} @Override public DBSObject refreshObject(@NotNull DBRProgressMonitor monitor) throws DBException { authIdCache.clearCache(); accessMethodCache.clearCache(); languageCache.clearCache(); encodingCache.clearCache(); tablespaceCache.clearCache(); schemaCache.clearCache(); cacheDataTypes(monitor); return this; } public Collection<PostgreAuthId> getUsers(DBRProgressMonitor monitor) throws DBException { return authIdCache.getAllObjects(monitor, this); } @Override public boolean supportsDefaultChange() { return true; } @Nullable @Override public PostgreSchema getDefaultObject() { return schemaCache.getCachedObject(dataSource.getActiveSchemaName()); } @Override public void setDefaultObject(@NotNull DBRProgressMonitor monitor, @NotNull DBSObject object) throws DBException { if (object instanceof PostgreSchema) { PostgreSchema oldActive = getDefaultObject(); if (oldActive == object) { return; } for (JDBCExecutionContext context : dataSource.getAllContexts()) { setSearchPath(monitor, (PostgreSchema) object, context); } dataSource.setActiveSchemaName(object.getName()); dataSource.setSearchPath(object.getName()); if (oldActive != null) { DBUtils.fireObjectSelect(oldActive, false); } DBUtils.fireObjectSelect(object, true); } } @Override public boolean refreshDefaultObject(@NotNull DBCSession session) throws DBException { return dataSource.refreshDefaultObject(session); } void setSearchPath(DBRProgressMonitor monitor, PostgreSchema schema, JDBCExecutionContext context) throws DBCException { try (JDBCSession session = context.openSession(monitor, DBCExecutionPurpose.UTIL, "Change search path")) { JDBCUtils.executeSQL( session, "SET search_path = \"$user\"," + DBUtils.getQuotedIdentifier(schema)); } catch (SQLException e) { throw new DBCException("Error setting search path", e, dataSource); } } public PostgreProcedure getProcedure(DBRProgressMonitor monitor, long schemaId, long procId) throws DBException { final PostgreSchema schema = getSchema(monitor, schemaId); if (schema != null) { return PostgreUtils.getObjectById(monitor, schema.proceduresCache, schema, procId); } return null; } public PostgreDataType getDataType(long typeId) { if (typeId <= 0) { return null; } PostgreDataType dataType = dataTypeCache.get(typeId); if (dataType != null) { return dataType; } for (PostgreSchema schema : getDatabase().schemaCache.getCachedObjects()) { dataType = schema.dataTypeCache.getDataType(typeId); if (dataType != null) { dataTypeCache.put(typeId, dataType); return dataType; } } log.debug("Data type '" + typeId + "' not found"); return null; } public PostgreDataType getDataType(String typeName) { if (typeName.endsWith("[]")) { // In some cases ResultSetMetadata returns it as [] typeName = "_" + typeName.substring(0, typeName.length() - 2); } String alias = PostgreConstants.DATA_TYPE_ALIASES.get(typeName); if (alias != null) { typeName = alias; } { // First check system catalog final PostgreSchema schema = getCatalogSchema(); if (schema != null) { final PostgreDataType dataType = schema.dataTypeCache.getCachedObject(typeName); if (dataType != null) { return dataType; } } } // Check schemas in search path final List<String> searchPath = dataSource.getSearchPath(); for (String schemaName : searchPath) { final PostgreSchema schema = schemaCache.getCachedObject(schemaName); if (schema != null) { final PostgreDataType dataType = schema.dataTypeCache.getCachedObject(typeName); if (dataType != null) { return dataType; } } } // Check the rest for (PostgreSchema schema : schemaCache.getCachedObjects()) { if (searchPath.contains(schema.getName())) { continue; } final PostgreDataType dataType = schema.dataTypeCache.getCachedObject(typeName); if (dataType != null) { return dataType; } } log.debug("Data type '" + typeName + "' not found in database '" + getName() + "'"); return null; } @Override public String toString() { return name; } class AuthIdCache extends JDBCObjectCache<PostgreDatabase, PostgreAuthId> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT a.oid,a.* FROM pg_catalog.pg_authid a " + "\nORDER BY a.oid"); } @Override protected PostgreAuthId fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreAuthId(owner, dbResult); } @Override protected boolean handleCacheReadError(DBException error) { // #271, #501: in some databases (AWS?) pg_authid is not accessible // FIXME: maybe some better workaround? if (PostgreConstants.EC_PERMISSION_DENIED.equals(error.getDatabaseState())) { log.warn(error); setCache(Collections.<PostgreAuthId>emptyList()); return true; } return false; } } class AccessMethodCache extends JDBCObjectCache<PostgreDatabase, PostgreAccessMethod> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT am.oid,am.* FROM pg_catalog.pg_am am " + "\nORDER BY am.oid"); } @Override protected PostgreAccessMethod fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreAccessMethod(owner, dbResult); } } class EncodingCache extends JDBCObjectCache<PostgreDatabase, PostgreCharset> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT c.contoencoding as encid,pg_catalog.pg_encoding_to_char(c.contoencoding) as encname\n" + "FROM pg_catalog.pg_conversion c\n" + "GROUP BY c.contoencoding\n" + "ORDER BY 2\n"); } @Override protected PostgreCharset fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreCharset(owner, dbResult); } } class LanguageCache extends JDBCObjectCache<PostgreDatabase, PostgreLanguage> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT l.oid,l.* FROM pg_catalog.pg_language l " + "\nORDER BY l.oid"); } @Override protected PostgreLanguage fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreLanguage(owner, dbResult); } } class ForeignDataWrapperCache extends JDBCObjectCache<PostgreDatabase, PostgreForeignDataWrapper> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT l.oid,l.*,p.pronamespace as handler_schema_id " + "\nFROM pg_catalog.pg_foreign_data_wrapper l" + "\nLEFT OUTER JOIN pg_catalog.pg_proc p ON p.oid=l.fdwhandler " + "\nORDER BY l.fdwname"); } @Override protected PostgreForeignDataWrapper fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreForeignDataWrapper(owner, dbResult); } } class ForeignServerCache extends JDBCObjectCache<PostgreDatabase, PostgreForeignServer> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT l.oid,l.* FROM pg_catalog.pg_foreign_server l" + "\nORDER BY l.srvname"); } @Override protected PostgreForeignServer fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreForeignServer(owner, dbResult); } } class TablespaceCache extends JDBCObjectCache<PostgreDatabase, PostgreTablespace> { @Override protected JDBCStatement prepareObjectsStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase owner) throws SQLException { return session.prepareStatement( "SELECT t.oid,t.* FROM pg_catalog.pg_tablespace t " + "\nORDER BY t.oid"); } @Override protected PostgreTablespace fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult) throws SQLException, DBException { return new PostgreTablespace(owner, dbResult); } } static class SchemaCache extends JDBCObjectLookupCache<PostgreDatabase, PostgreSchema> { @NotNull @Override public JDBCStatement prepareLookupStatement( @NotNull JDBCSession session, @NotNull PostgreDatabase database, @Nullable PostgreSchema object, @Nullable String objectName) throws SQLException { /* // Do not apply filters // We need all schemas to have access to types return session.prepareStatement( "SELECT n.oid,n.* FROM pg_catalog.pg_namespace n ORDER BY nspname"); */ StringBuilder catalogQuery = new StringBuilder("SELECT n.oid,n.* FROM pg_catalog.pg_namespace n"); DBSObjectFilter catalogFilters = database.getDataSource().getContainer().getObjectFilter(PostgreSchema.class, null, false); if ((catalogFilters != null && !catalogFilters.isNotApplicable()) || object != null || objectName != null) { if (object != null || objectName != null) { catalogFilters = new DBSObjectFilter(); catalogFilters.addInclude(object != null ? object.getName() : objectName); } else { catalogFilters = new DBSObjectFilter(catalogFilters); // Always read catalog schema catalogFilters.addInclude(PostgreConstants.CATALOG_SCHEMA_NAME); } JDBCUtils.appendFilterClause(catalogQuery, catalogFilters, "nspname", true); } catalogQuery.append(" ORDER BY nspname"); JDBCPreparedStatement dbStat = session.prepareStatement(catalogQuery.toString()); if (catalogFilters != null) { JDBCUtils.setFilterParameters(dbStat, 1, catalogFilters); } return dbStat; } @Override protected PostgreSchema fetchObject( @NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet resultSet) throws SQLException, DBException { String name = JDBCUtils.safeGetString(resultSet, "nspname"); if (name == null) { return null; } if (PostgreSchema.isUtilitySchema(name) && !owner.getDataSource().getContainer().isShowUtilityObjects()) { return null; } return new PostgreSchema(owner, name, resultSet); } } }
/** DBeaver UI core */ public class DBeaverUI implements DBUICallback { static final Log log = Log.getLog(DBeaverUI.class); private static DBeaverUI instance; private SharedTextColors sharedTextColors; private TrayIconHandler trayItem; private final List<IDisposable> globalDisposables = new ArrayList<>(); public static DBeaverUI getInstance() { if (instance == null) { instance = new DBeaverUI(); instance.initialize(); } return instance; } static void disposeUI() { if (instance != null) { instance.dispose(); } } public static ISharedTextColors getSharedTextColors() { return getInstance().sharedTextColors; } private void dispose() { // this.trayItem.dispose(); this.sharedTextColors.dispose(); if (trayItem != null) { trayItem.hide(); } List<IDisposable> dispList = new ArrayList<>(globalDisposables); Collections.reverse(dispList); for (IDisposable disp : dispList) { try { disp.dispose(); } catch (Exception e) { log.error(e); } globalDisposables.remove(disp); } } private void initialize() { this.sharedTextColors = new SharedTextColors(); this.trayItem = new TrayIconHandler(); DBUserInterface.setInstance(this); // Register context listener WorkbenchContextListener.registerInWorkbench(); /* // Global focus lister for debug Display.getCurrent().addFilter(SWT.FocusIn, new Listener() { @Override public void handleEvent(Event event) { System.out.println("FOCUS TO: " + event.widget); } }); */ } public static AbstractUIJob runUIJob( String jobName, final DBRRunnableWithProgress runnableWithProgress) { return runUIJob(jobName, 0, runnableWithProgress); } public static AbstractUIJob runUIJob( String jobName, int timeout, final DBRRunnableWithProgress runnableWithProgress) { AbstractUIJob job = new AbstractUIJob(jobName) { @Override public IStatus runInUIThread(DBRProgressMonitor monitor) { try { runnableWithProgress.run(monitor); } catch (InvocationTargetException e) { return GeneralUtils.makeExceptionStatus(e); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } return Status.OK_STATUS; } }; job.setSystem(true); job.schedule(timeout); return job; } @NotNull public static IWorkbenchWindow getActiveWorkbenchWindow() { IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); if (window != null) { return window; } IWorkbenchWindow[] windows = workbench.getWorkbenchWindows(); if (windows.length > 0) { return windows[0]; } throw new IllegalStateException("No workbench window"); } public static Shell getActiveWorkbenchShell() { return getActiveWorkbenchWindow().getShell(); } public static Display getDisplay() { Shell shell = getActiveWorkbenchShell(); if (shell != null) return shell.getDisplay(); else return Display.getDefault(); } /* public static void runWithProgress(IWorkbenchPartSite site, final DBRRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { IActionBars actionBars = null; if (site instanceof IViewSite) { actionBars = ((IViewSite) site).getActionBars(); } else if (site instanceof IEditorSite) { actionBars = ((IEditorSite) site).getActionBars(); } IStatusLineManager statusLineManager = null; if (actionBars != null) { statusLineManager = actionBars.getStatusLineManager(); } if (statusLineManager == null) { runInProgressService(runnable); } else { IProgressMonitor progressMonitor = statusLineManager.getProgressMonitor(); runnable.run(new DefaultProgressMonitor(progressMonitor)); } } */ public static DBRRunnableContext getDefaultRunnableContext() { IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench != null && workbench.getActiveWorkbenchWindow() != null) { return new RunnableContextDelegate(workbench.getActiveWorkbenchWindow()); } else { return new DBRRunnableContext() { @Override public void run(boolean fork, boolean cancelable, DBRRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { runnable.run(VoidProgressMonitor.INSTANCE); } }; } } /** * Runs task in Eclipse progress service. NOTE: this call can't be canceled if it will block in IO */ public static void runInProgressService(final DBRRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { getDefaultRunnableContext() .run( true, true, new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { runnable.run(monitor); } }); } /** * Runs task in Eclipse progress dialog. NOTE: this call can't be canceled if it will block in IO */ public static void runInProgressDialog(final DBRRunnableWithProgress runnable) throws InvocationTargetException { try { IRunnableContext runnableContext; IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow(); if (workbenchWindow != null) { runnableContext = new ProgressMonitorDialog(workbench.getActiveWorkbenchWindow().getShell()); } else { runnableContext = workbench.getProgressService(); } runnableContext.run( true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { runnable.run(RuntimeUtils.makeMonitor(monitor)); } }); } catch (InterruptedException e) { // do nothing } } public static void runInUI(IRunnableContext context, final DBRRunnableWithProgress runnable) { try { PlatformUI.getWorkbench() .getProgressService() .runInUI( context, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { runnable.run(RuntimeUtils.makeMonitor(monitor)); } }, DBeaverActivator.getWorkspace().getRoot()); } catch (InvocationTargetException e) { UIUtils.showErrorDialog(null, null, null, e.getTargetException()); } catch (InterruptedException e) { // do nothing } } public static void notifyAgent(String message, int status) { if (!DBeaverCore.getGlobalPreferenceStore() .getBoolean(DBeaverPreferences.AGENT_LONG_OPERATION_NOTIFY)) { // Notifications disabled return; } getInstance().trayItem.notify(message, status); } @Override public void showError(@NotNull String title, @Nullable String message, @NotNull IStatus status) { UIUtils.showErrorDialog(null, title, message, status); } @Override public void showError(@NotNull String title, @Nullable String message, @NotNull Throwable e) { UIUtils.showErrorDialog(null, title, message, e); } @Override public void showError(@NotNull String title, @Nullable String message) { UIUtils.showErrorDialog(null, title, message); } @Override public DBAAuthInfo promptUserCredentials(String prompt, String userName, String userPassword) { // Ask user final Shell shell = DBeaverUI.getActiveWorkbenchShell(); final BaseAuthDialog authDialog = new BaseAuthDialog(shell, prompt); authDialog.setUserName(userName); authDialog.setUserPassword(userPassword); final RunnableWithResult<Boolean> binder = new RunnableWithResult<Boolean>() { @Override public void run() { result = (authDialog.open() == IDialogConstants.OK_ID); } }; UIUtils.runInUI(shell, binder); if (binder.getResult() != null && binder.getResult()) { return authDialog.getAuthInfo(); } else { return null; } } @Override public void executeProcess(final DBRProcessDescriptor processDescriptor) { processDescriptor.setProcessListener( new DBRProcessListener() { @Override public void onProcessStarted() { ProcessPropertyTester.firePropertyChange(ProcessPropertyTester.PROP_RUNNING); } @Override public void onProcessTerminated(int resultCode) { ProcessPropertyTester.firePropertyChange(ProcessPropertyTester.PROP_RUNNING); } }); // Direct execute try { processDescriptor.execute(); } catch (DBException e) { showError("Execute process", processDescriptor.getName(), e); } if (processDescriptor.getCommand().isShowProcessPanel()) { getActiveWorkbenchShell() .getDisplay() .asyncExec( new Runnable() { @Override public void run() { try { final ShellProcessView processView = (ShellProcessView) DBeaverUI.getActiveWorkbenchWindow() .getActivePage() .showView( ShellProcessView.VIEW_ID, ShellProcessView.getNextId(), IWorkbenchPage.VIEW_VISIBLE); processView.initProcess(processDescriptor); } catch (PartInitException e) { log.error(e); } } }); } } }
/** Table collector */ public class DiagramObjectCollector { private static final Log log = Log.getLog(DiagramObjectCollector.class); private final EntityDiagram diagram; private final List<ERDEntity> erdEntities = new ArrayList<>(); private final Map<DBSEntity, ERDEntity> tableMap = new HashMap<>(); public DiagramObjectCollector(EntityDiagram diagram) { this.diagram = diagram; this.tableMap.putAll(diagram.getTableMap()); } public static Collection<DBSEntity> collectTables( DBRProgressMonitor monitor, Collection<? extends DBSObject> roots) throws DBException { Set<DBSEntity> tables = new LinkedHashSet<>(); collectTables(monitor, roots, tables); return tables; } private static void collectTables( DBRProgressMonitor monitor, Collection<? extends DBSObject> roots, Set<DBSEntity> tables) throws DBException { for (DBSObject root : roots) { if (monitor.isCanceled()) { break; } if (root instanceof DBSFolder) { collectTables(monitor, ((DBSFolder) root).getChildrenObjects(monitor), tables); } else if (root instanceof DBSEntity) { tables.add((DBSEntity) root); } if (root instanceof DBSObjectContainer) { collectTables(monitor, (DBSObjectContainer) root, tables); } } } private static void collectTables( DBRProgressMonitor monitor, DBSObjectContainer container, Set<DBSEntity> tables) throws DBException { if (monitor.isCanceled()) { return; } container.cacheStructure(monitor, DBSObjectContainer.STRUCT_ALL); final Collection<? extends DBSObject> children = container.getChildren(monitor); if (!CommonUtils.isEmpty(children)) { Class<? extends DBSObject> childType = container.getChildType(monitor); DBSObjectFilter objectFilter = container.getDataSource().getContainer().getObjectFilter(childType, container, true); for (DBSObject entity : children) { if (monitor.isCanceled()) { break; } if (objectFilter != null && !objectFilter.matches(entity.getName())) { continue; } if (entity instanceof DBSEntity) { tables.add((DBSEntity) entity); } else if (entity instanceof DBSObjectContainer) { collectTables(monitor, (DBSObjectContainer) entity, tables); } } } } public void generateDiagramObjects( DBRProgressMonitor monitor, Collection<? extends DBSObject> roots) throws DBException { boolean showViews = ERDActivator.getDefault() .getPreferenceStore() .getBoolean(ERDConstants.PREF_DIAGRAM_SHOW_VIEWS); Collection<DBSEntity> tables = collectTables(monitor, roots); for (DBSEntity table : tables) { if (DBUtils.isHiddenObject(table)) { // Skip hidden tables continue; } if (!showViews && table instanceof DBSTable && ((DBSTable) table).isView()) { // Skip views continue; } addDiagramEntity(monitor, table); } // Add new relations for (ERDEntity erdEntity : erdEntities) { erdEntity.addRelations(monitor, tableMap, false); } } private void addDiagramEntity(DBRProgressMonitor monitor, DBSEntity table) { if (diagram.containsTable(table)) { // Avoid duplicates return; } ERDEntity erdEntity = ERDEntity.fromObject(monitor, diagram, table); if (erdEntity != null) { erdEntities.add(erdEntity); tableMap.put(table, erdEntity); } } public List<ERDEntity> getDiagramEntities() { return erdEntities; } public static List<ERDEntity> generateEntityList( final EntityDiagram diagram, Collection<DBPNamedObject> objects) { final List<DBSObject> roots = new ArrayList<>(); for (DBPNamedObject object : objects) { if (object instanceof DBSObject) { roots.add((DBSObject) object); } } final List<ERDEntity> entities = new ArrayList<>(); try { DBeaverUI.runInProgressService( new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { DiagramObjectCollector collector = new DiagramObjectCollector(diagram); try { collector.generateDiagramObjects(monitor, roots); } catch (DBException e) { throw new InvocationTargetException(e); } entities.addAll(collector.getDiagramEntities()); } }); } catch (InvocationTargetException e) { log.error(e.getTargetException()); } catch (InterruptedException e) { // interrupted } return entities; } }
/** * DB2 Index * * @author Denis Forveille */ public class DB2Index extends JDBCTableIndex<DB2Schema, DB2TableBase> { private static final Log LOG = Log.getLog(DB2Index.class); // Structure private DB2UniqueRule uniqueRule; private Integer colCount; private Integer uniqueColCount; private DB2IndexType db2IndexType; private Integer pctFree; private Integer indexId; private Integer minPctUsed; private Boolean reverseScans; private Integer tablespaceId; private DB2IndexPageSplit pageSplit; private Boolean compression; private String remarks; // Derived private Timestamp createTime; private Boolean madeUnique; // Stats private Timestamp statsTime; private Long fullKeycard; private Long firstKeycard; private Long first2Keycard; private Long first3Keycard; private Long first4Keycard; private Integer clusterRatio; // ----------------- // Constructors // ----------------- public DB2Index( DBRProgressMonitor monitor, DB2Schema schema, DB2TableBase table, ResultSet dbResult) { super(schema, table, JDBCUtils.safeGetStringTrimmed(dbResult, "INDNAME"), null, true); DB2DataSource db2DataSource = (DB2DataSource) schema.getDataSource(); this.uniqueRule = CommonUtils.valueOf(DB2UniqueRule.class, JDBCUtils.safeGetString(dbResult, "UNIQUERULE")); this.colCount = JDBCUtils.safeGetInteger(dbResult, "COLCOUNT"); this.uniqueColCount = JDBCUtils.safeGetInteger(dbResult, "UNIQUE_COLCOUNT"); this.pctFree = JDBCUtils.safeGetInteger(dbResult, "PCTFREE"); this.indexId = JDBCUtils.safeGetInteger(dbResult, "IID"); this.minPctUsed = JDBCUtils.safeGetInteger(dbResult, "MINPCTUSED"); this.reverseScans = JDBCUtils.safeGetBoolean(dbResult, "REVERSE_SCANS", DB2YesNo.Y.name()); this.tablespaceId = JDBCUtils.safeGetInteger(dbResult, "TBSPACEID"); this.pageSplit = CommonUtils.valueOf( DB2IndexPageSplit.class, JDBCUtils.safeGetStringTrimmed(dbResult, "PAGESPLIT")); this.remarks = JDBCUtils.safeGetString(dbResult, "REMARKS"); this.createTime = JDBCUtils.safeGetTimestamp(dbResult, "CREATE_TIME"); this.madeUnique = JDBCUtils.safeGetBoolean(dbResult, "MADE_UNIQUE"); this.statsTime = JDBCUtils.safeGetTimestamp(dbResult, "STATS_TIME"); this.fullKeycard = JDBCUtils.safeGetLong(dbResult, "FULLKEYCARD"); this.firstKeycard = JDBCUtils.safeGetLong(dbResult, "FIRSTKEYCARD"); this.first2Keycard = JDBCUtils.safeGetLong(dbResult, "FIRST2KEYCARD"); this.first3Keycard = JDBCUtils.safeGetLong(dbResult, "FIRST3KEYCARD"); this.first4Keycard = JDBCUtils.safeGetLong(dbResult, "FIRST4KEYCARD"); this.clusterRatio = JDBCUtils.safeGetInteger(dbResult, "CLUSTERRATIO"); if (db2DataSource.isAtLeastV9_5()) { this.compression = JDBCUtils.safeGetBoolean(dbResult, "COMPRESSION", DB2YesNo.Y.name()); } // DF: Could have been done in constructor. More "readable" to do it here this.db2IndexType = CommonUtils.valueOf( DB2IndexType.class, JDBCUtils.safeGetStringTrimmed(dbResult, "INDEXTYPE")); this.indexType = db2IndexType.getDBSIndexType(); } public DB2Index(DB2TableBase db2Table, String indexName, DBSIndexType indexType) { super(db2Table.getSchema(), db2Table, indexName, indexType, false); } // ----------------- // Business Contract // ----------------- @Override public boolean isUnique() { return (uniqueRule.isUnique()); } @NotNull @Override public DB2DataSource getDataSource() { return getTable().getDataSource(); } @Override public String getFullQualifiedName() { return getContainer().getName() + "." + getName(); } // ----------------- // Columns // ----------------- @Override public List<DB2IndexColumn> getAttributeReferences(DBRProgressMonitor monitor) { try { return getContainer().getIndexCache().getChildren(monitor, getContainer(), this); } catch (DBException e) { // DF: Don't know what to do with this exception except log it LOG.error("DBException swallowed during getAttributeReferences", e); return null; } } public void addColumn(DB2IndexColumn ixColumn) { DBSObjectCache<DB2Index, DB2IndexColumn> cols = getContainer().getIndexCache().getChildrenCache(this); cols.cacheObject(ixColumn); } // ----------------- // Properties // ----------------- @NotNull @Override @Property( viewable = true, editable = true, valueTransformer = DBObjectNameCaseTransformer.class, order = 1) public String getName() { return super.getName(); } @Property(viewable = true, editable = false, order = 2) public DB2Schema getIndSchema() { return getContainer(); } @Property(viewable = true, editable = false, order = 5) public DB2UniqueRule getUniqueRule() { return uniqueRule; } @Property(viewable = false, editable = false, order = 10) public Boolean getMadeUnique() { return madeUnique; } @Property(viewable = false, editable = false, order = 11) public Integer getColCount() { return colCount; } @Property(viewable = false, editable = false, order = 12) public Integer getUniqueColCount() { return uniqueColCount; } @Property(viewable = false, editable = false, order = 70) public Integer getIndexId() { return indexId; } @Property(viewable = false, editable = false, order = 71) public Integer getTablespaceId() { return tablespaceId; } @Property(viewable = false, order = 20, editable = false) public Integer getPctFree() { return pctFree; } @Property(viewable = false, order = 21, editable = false) public Integer getMinPctUsed() { return minPctUsed; } @Property(viewable = false, order = 22, editable = false) public Boolean getReverseScans() { return reverseScans; } @Property(viewable = false, order = 23, editable = false) public DB2IndexPageSplit getPageSplit() { return pageSplit; } @Property(viewable = false, order = 24, editable = false) public Boolean getCompression() { return compression; } @Nullable @Override @Property(viewable = false, editable = false) public String getDescription() { return remarks; } @Property(viewable = false, editable = false, category = DB2Constants.CAT_DATETIME) public Timestamp getCreateTime() { return createTime; } @Property(viewable = false, editable = false, order = 30, category = DB2Constants.CAT_STATS) public Timestamp getStatsTime() { return statsTime; } @Property(viewable = true, editable = false, order = 31, category = DB2Constants.CAT_STATS) public Long getFullKeycard() { return fullKeycard; } @Property(viewable = false, editable = false, order = 32, category = DB2Constants.CAT_STATS) public Long getFirstKeycard() { return firstKeycard; } @Property(viewable = false, editable = false, order = 33, category = DB2Constants.CAT_STATS) public Long getFirst2Keycard() { return first2Keycard; } @Property(viewable = false, editable = false, order = 34, category = DB2Constants.CAT_STATS) public Long getFirst3Keycard() { return first3Keycard; } @Property(viewable = false, editable = false, order = 35, category = DB2Constants.CAT_STATS) public Long getFirst4Keycard() { return first4Keycard; } @Property(viewable = false, editable = false, order = 36, category = DB2Constants.CAT_STATS) public Integer getClusterRatio() { return clusterRatio; } }
/** DBNProject */ public class DBNProject extends DBNResource { private static final Log log = Log.getLog(DBNProject.class); public DBNProject(DBNNode parentNode, IProject project, DBPResourceHandler handler) { super(parentNode, project, handler); getModel().getApplication().getProjectManager().addProject(project); } @Override protected void dispose(boolean reflect) { IProject project = getProject(); super.dispose(reflect); getModel().getApplication().getProjectManager().removeProject(project); } public IProject getProject() { return (IProject) getResource(); } public DBNProjectDatabases getDatabases() { try { for (DBNNode db : getChildren(VoidProgressMonitor.INSTANCE)) { if (db instanceof DBNProjectDatabases) { return (DBNProjectDatabases) db; } } } catch (DBException e) { throw new IllegalStateException("Can't read project contents", e); } throw new IllegalStateException("No databases resource in project"); } @Override public String getNodeDescription() { try { final IProject project = getProject(); return project == null ? null : project.getDescription().getComment(); } catch (CoreException e) { log.debug(e); return null; } } @Override public DBPImage getNodeIcon() { return DBIcon.PROJECT; } @Override public boolean allowsOpen() { return false; } @Override public <T> T getAdapter(Class<T> adapter) { if (adapter == DBNProject.class) { return adapter.cast(this); } return super.getAdapter(adapter); } @Override public boolean supportsRename() { // Do not rename active projects return getModel().getApplication().getProjectManager().getActiveProject() != getProject(); } @Override public void rename(DBRProgressMonitor monitor, String newName) throws DBException { try { final IProjectDescription description = getProject().getDescription(); description.setName(newName); getProject().move(description, true, monitor.getNestedMonitor()); } catch (CoreException e) { throw new DBException("Can't rename project", e); } } @Override protected DBNNode[] readChildNodes(DBRProgressMonitor monitor) throws DBException { if (!getProject().isOpen()) { try { getProject().open(monitor.getNestedMonitor()); getProject().refreshLocal(IFile.DEPTH_ONE, monitor.getNestedMonitor()); } catch (CoreException e) { throw new DBException("Can't open project '" + getProject().getName() + "'", e); } } DBPDataSourceRegistry dataSourceRegistry = getModel().getApplication().getProjectManager().getDataSourceRegistry(getProject()); DBNNode[] children = super.readChildNodes(monitor); if (dataSourceRegistry != null) { children = ArrayUtils.add( DBNNode.class, children, new DBNProjectDatabases(this, dataSourceRegistry)); } return children; } public DBNResource findResource(IResource resource) { List<IResource> path = new ArrayList<>(); for (IResource parent = resource; !(parent instanceof IProject); parent = parent.getParent()) { path.add(0, parent); } DBNResource resNode = this; for (IResource res : path) { try { resNode.getChildren(VoidProgressMonitor.INSTANCE); } catch (DBException e) { log.error(e); } resNode = resNode.getChild(res); if (resNode == null) { return null; } } return resNode; } @Override protected void handleChildResourceChange(IResourceDelta delta) { final String name = delta.getResource().getName(); if (name.startsWith(DBPDataSourceRegistry.CONFIG_FILE_PREFIX) && name.endsWith(DBPDataSourceRegistry.CONFIG_FILE_EXT)) { // DS registry configuration changed getDatabases().getDataSourceRegistry().refreshConfig(); } else { super.handleChildResourceChange(delta); } } public void openProject() { final DBNProjectDatabases databases = getDatabases(); if (databases != null) { databases.getDataSourceRegistry().refreshConfig(); } } }
/** Data pump for SQL queries */ class ResultSetDataReceiver implements DBDDataReceiver { static final Log log = Log.getLog(ResultSetDataReceiver.class); private ResultSetViewer resultSetViewer; private int columnsCount; private DBDAttributeBindingMeta[] metaColumns; private List<Object[]> rows = new ArrayList<>(); private boolean hasMoreData; private boolean nextSegmentRead; private long offset; private long maxRows; private Map<DBCAttributeMetaData, List<DBCException>> errors = new HashMap<>(); ResultSetDataReceiver(ResultSetViewer resultSetViewer) { this.resultSetViewer = resultSetViewer; } boolean isHasMoreData() { return hasMoreData; } void setHasMoreData(boolean hasMoreData) { this.hasMoreData = hasMoreData; } void setNextSegmentRead(boolean nextSegmentRead) { this.nextSegmentRead = nextSegmentRead; } @Override public void fetchStart( DBCSession session, final DBCResultSet resultSet, long offset, long maxRows) throws DBCException { this.rows.clear(); this.offset = offset; this.maxRows = maxRows; if (!nextSegmentRead) { // Get columns metadata DBCResultSetMetaData metaData = resultSet.getMeta(); List<DBCAttributeMetaData> rsAttributes = metaData.getAttributes(); columnsCount = rsAttributes.size(); // Extract column info metaColumns = new DBDAttributeBindingMeta[columnsCount]; for (int i = 0; i < columnsCount; i++) { metaColumns[i] = DBUtils.getAttributeBinding(session, rsAttributes.get(i)); } resultSetViewer.setMetaData(metaColumns); } } @Override public void fetchRow(DBCSession session, DBCResultSet resultSet) throws DBCException { Object[] row = new Object[columnsCount]; for (int i = 0; i < columnsCount; i++) { try { row[i] = metaColumns[i] .getValueHandler() .fetchValueObject( session, resultSet, metaColumns[i].getAttribute(), metaColumns[i].getOrdinalPosition()); } catch (DBCException e) { // Do not reports the same error multiple times // There are a lot of error could occur during result set fetch // We report certain error only once List<DBCException> errorList = errors.get(metaColumns[i].getMetaAttribute()); if (errorList == null) { errorList = new ArrayList<>(); errors.put(metaColumns[i].getMetaAttribute(), errorList); } if (!errorList.contains(e)) { log.warn("Can't read column '" + metaColumns[i].getName() + "' value", e); errorList.add(e); } } } rows.add(row); } @Override public void fetchEnd(DBCSession session, final DBCResultSet resultSet) throws DBCException { if (!nextSegmentRead) { // Read locators' metadata ResultSetUtils.bindAttributes(session, resultSet, metaColumns, rows); } final List<Object[]> tmpRows = rows; final boolean nextSegmentRead = this.nextSegmentRead; runInUI( new Runnable() { @Override public void run() { // Push data into viewer if (!nextSegmentRead) { resultSetViewer.updatePresentation(resultSet); resultSetViewer.setData(tmpRows); } else { resultSetViewer.appendData(tmpRows); } // Check for more data hasMoreData = maxRows > 0 && tmpRows.size() >= maxRows; } }); } @Override public void close() { nextSegmentRead = false; errors.clear(); rows = new ArrayList<>(); } private void runInUI(Runnable runnable) { Control control = resultSetViewer.getControl(); if (!control.isDisposed()) { control.getDisplay().asyncExec(runnable); } } }
public class CompileHandler extends AbstractHandler implements IElementUpdater { static final Log log = Log.getLog(CompileHandler.class); @Override public Object execute(ExecutionEvent event) throws ExecutionException { final List<OracleSourceObject> objects = getSelectedObjects(event); if (!objects.isEmpty()) { final Shell activeShell = HandlerUtil.getActiveShell(event); if (objects.size() == 1) { final OracleSourceObject unit = objects.get(0); DBCSourceHost sourceHost = null; final IWorkbenchPart activePart = HandlerUtil.getActiveEditor(event); if (activePart != null) { sourceHost = RuntimeUtils.getObjectAdapter(activePart, DBCSourceHost.class); if (sourceHost == null) { sourceHost = activePart.getAdapter(DBCSourceHost.class); } } if (sourceHost != null && sourceHost.getSourceObject() != unit) { sourceHost = null; } final DBCCompileLog compileLog = sourceHost == null ? new DBCCompileLogBase() : sourceHost.getCompileLog(); compileLog.clearLog(); Throwable error = null; try { DBeaverUI.runInProgressService( new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { compileUnit(monitor, compileLog, unit); } catch (DBCException e) { throw new InvocationTargetException(e); } } }); if (compileLog.getError() != null) { error = compileLog.getError(); } } catch (InvocationTargetException e) { error = e.getTargetException(); } catch (InterruptedException e) { return null; } if (error != null) { UIUtils.showErrorDialog(activeShell, "Unexpected compilation error", null, error); } else if (!CommonUtils.isEmpty(compileLog.getErrorStack())) { // Show compile errors int line = -1, position = -1; StringBuilder fullMessage = new StringBuilder(); for (DBCCompileError oce : compileLog.getErrorStack()) { fullMessage.append(oce.toString()).append(GeneralUtils.getDefaultLineSeparator()); if (line < 0) { line = oce.getLine(); position = oce.getPosition(); } } // If compiled object is currently open in editor - try to position on error line if (sourceHost != null && sourceHost.getSourceObject() == unit && line > 0 && position > 0) { sourceHost.positionSource(line, position); activePart.getSite().getPage().activate(activePart); } String errorTitle = unit.getName() + " compilation failed"; if (sourceHost != null) { sourceHost.setCompileInfo(errorTitle, true); sourceHost.showCompileLog(); } UIUtils.showErrorDialog(activeShell, errorTitle, fullMessage.toString()); } else { String message = unit.getName() + " compiled successfully"; if (sourceHost != null) { sourceHost.setCompileInfo(message, true); } UIUtils.showMessageBox(activeShell, "Done", message, SWT.ICON_INFORMATION); } } else { OracleCompilerDialog dialog = new OracleCompilerDialog(activeShell, objects); dialog.open(); } } return null; } private List<OracleSourceObject> getSelectedObjects(ExecutionEvent event) { List<OracleSourceObject> objects = new ArrayList<>(); final ISelection currentSelection = HandlerUtil.getCurrentSelection(event); if (currentSelection instanceof IStructuredSelection && !currentSelection.isEmpty()) { for (Iterator<?> iter = ((IStructuredSelection) currentSelection).iterator(); iter.hasNext(); ) { final Object element = iter.next(); final OracleSourceObject sourceObject = RuntimeUtils.getObjectAdapter(element, OracleSourceObject.class); if (sourceObject != null) { objects.add(sourceObject); } } } if (objects.isEmpty()) { final IWorkbenchPart activePart = HandlerUtil.getActivePart(event); final OracleSourceObject sourceObject = RuntimeUtils.getObjectAdapter(activePart, OracleSourceObject.class); if (sourceObject != null) { objects.add(sourceObject); } } return objects; } @Override public void updateElement(UIElement element, Map parameters) { List<OracleSourceObject> objects = new ArrayList<>(); IWorkbenchPartSite partSite = UIUtils.getWorkbenchPartSite(element.getServiceLocator()); if (partSite != null) { final ISelectionProvider selectionProvider = partSite.getSelectionProvider(); if (selectionProvider != null) { ISelection selection = selectionProvider.getSelection(); if (selection instanceof IStructuredSelection && !selection.isEmpty()) { for (Iterator<?> iter = ((IStructuredSelection) selection).iterator(); iter.hasNext(); ) { final Object item = iter.next(); final OracleSourceObject sourceObject = RuntimeUtils.getObjectAdapter(item, OracleSourceObject.class); if (sourceObject != null) { objects.add(sourceObject); } } } } if (objects.isEmpty()) { final IWorkbenchPart activePart = partSite.getPart(); final OracleSourceObject sourceObject = RuntimeUtils.getObjectAdapter(activePart, OracleSourceObject.class); if (sourceObject != null) { objects.add(sourceObject); } } } if (!objects.isEmpty()) { if (objects.size() > 1) { element.setText("Compile " + objects.size() + " objects"); } else { final OracleSourceObject sourceObject = objects.get(0); String objectType = TextUtils.formatWord(sourceObject.getSourceType().name()); element.setText("Compile " + objectType /* + " '" + sourceObject.getName() + "'"*/); } } } public static boolean compileUnit( DBRProgressMonitor monitor, DBCCompileLog compileLog, OracleSourceObject unit) throws DBCException { final DBEPersistAction[] compileActions = unit.getCompileActions(); if (ArrayUtils.isEmpty(compileActions)) { return true; } try (JDBCSession session = DBUtils.openUtilSession( monitor, unit.getDataSource(), "Compile '" + unit.getName() + "'")) { boolean success = true; for (DBEPersistAction action : compileActions) { final String script = action.getScript(); compileLog.trace(script); if (monitor.isCanceled()) { break; } try { try (DBCStatement dbStat = session.prepareStatement(DBCStatementType.QUERY, script, false, false, false)) { dbStat.executeStatement(); } action.handleExecute(null); } catch (DBCException e) { action.handleExecute(e); throw e; } if (action instanceof OracleObjectPersistAction) { if (!logObjectErrors( session, compileLog, unit, ((OracleObjectPersistAction) action).getObjectType())) { success = false; } } } final DBSObjectState oldState = unit.getObjectState(); unit.refreshObjectState(monitor); if (unit.getObjectState() != oldState) { unit.getDataSource() .getContainer() .fireEvent(new DBPEvent(DBPEvent.Action.OBJECT_UPDATE, unit)); } return success; } } public static boolean logObjectErrors( JDBCSession session, DBCCompileLog compileLog, OracleSourceObject unit, OracleObjectType objectType) { try { try (JDBCPreparedStatement dbStat = session.prepareStatement( "SELECT * FROM SYS.ALL_ERRORS WHERE OWNER=? AND NAME=? AND TYPE=? ORDER BY SEQUENCE")) { dbStat.setString(1, unit.getSchema().getName()); dbStat.setString(2, unit.getName()); dbStat.setString(3, objectType.getTypeName()); try (ResultSet dbResult = dbStat.executeQuery()) { boolean hasErrors = false; while (dbResult.next()) { DBCCompileError error = new DBCCompileError( "ERROR".equals(dbResult.getString("ATTRIBUTE")), dbResult.getString("TEXT"), dbResult.getInt("LINE"), dbResult.getInt("POSITION")); hasErrors = true; if (error.isError()) { compileLog.error(error); } else { compileLog.warn(error); } } return !hasErrors; } } } catch (Exception e) { log.error("Can't read user errors", e); return false; } } }
/** * SQLQueryJob * * @author Serge Rider */ public class SQLQueryJob extends DataSourceJob { static final Log log = Log.getLog(SQLQueryJob.class); public static final Object STATS_RESULTS = new Object(); private final DBSDataContainer dataContainer; private final List<SQLQuery> queries; private final SQLResultsConsumer resultsConsumer; private final SQLQueryListener listener; private final IWorkbenchPartSite partSite; private DBDDataFilter dataFilter; private boolean connectionInvalidated = false; private SQLScriptCommitType commitType; private SQLScriptErrorHandling errorHandling; private boolean fetchResultSets; private long rsOffset; private long rsMaxRows; private DBCStatement curStatement; private final List<DBCResultSet> curResultSets = new ArrayList<>(); private Throwable lastError = null; private DBCStatistics statistics; private int fetchResultSetNumber; private int resultSetNumber; private SQLQuery lastGoodQuery; public SQLQueryJob( @NotNull IWorkbenchPartSite partSite, @NotNull String name, @NotNull DBCExecutionContext executionContext, @NotNull DBSDataContainer dataContainer, @NotNull List<SQLQuery> queries, @NotNull SQLResultsConsumer resultsConsumer, @Nullable SQLQueryListener listener) { super(name, DBeaverIcons.getImageDescriptor(UIIcon.SQL_SCRIPT_EXECUTE), executionContext); this.dataContainer = dataContainer; this.partSite = partSite; this.queries = queries; this.resultsConsumer = resultsConsumer; this.listener = listener; { // Read config form preference store DBPPreferenceStore preferenceStore = getDataSourceContainer().getPreferenceStore(); this.commitType = SQLScriptCommitType.valueOf( preferenceStore.getString(DBeaverPreferences.SCRIPT_COMMIT_TYPE)); this.errorHandling = SQLScriptErrorHandling.valueOf( preferenceStore.getString(DBeaverPreferences.SCRIPT_ERROR_HANDLING)); this.fetchResultSets = queries.size() == 1 || preferenceStore.getBoolean(DBeaverPreferences.SCRIPT_FETCH_RESULT_SETS); this.rsMaxRows = preferenceStore.getInt(DBeaverPreferences.RESULT_SET_MAX_ROWS); } } public void setFetchResultSets(boolean fetchResultSets) { this.fetchResultSets = fetchResultSets; } public SQLQuery getLastQuery() { return queries.isEmpty() ? null : queries.get(0); } public SQLQuery getLastGoodQuery() { return lastGoodQuery; } public boolean hasLimits() { return rsOffset >= 0 && rsMaxRows > 0; } public void setResultSetLimit(long offset, long maxRows) { this.rsOffset = offset; this.rsMaxRows = maxRows; } @Override protected IStatus run(DBRProgressMonitor monitor) { RuntimeUtils.setThreadName("SQL script execution"); statistics = new DBCStatistics(); try { DBCExecutionContext context = getExecutionContext(); DBCTransactionManager txnManager = DBUtils.getTransactionManager(context); DBCExecutionPurpose purpose = queries.size() > 1 ? DBCExecutionPurpose.USER_SCRIPT : DBCExecutionPurpose.USER; try (DBCSession session = context.openSession(monitor, purpose, "SQL Query")) { // Set transaction settings (only if autocommit is off) QMUtils.getDefaultHandler().handleScriptBegin(session); boolean oldAutoCommit = txnManager == null || txnManager.isAutoCommit(); boolean newAutoCommit = (commitType == SQLScriptCommitType.AUTOCOMMIT); if (txnManager != null && !oldAutoCommit && newAutoCommit) { txnManager.setAutoCommit(monitor, true); } monitor.beginTask(this.getName(), queries.size()); // Notify job start if (listener != null) { listener.onStartScript(); } resultSetNumber = 0; for (int queryNum = 0; queryNum < queries.size(); ) { // Execute query SQLQuery query = queries.get(queryNum); fetchResultSetNumber = resultSetNumber; boolean runNext = executeSingleQuery(session, query, true); if (!runNext) { // Ask to continue if (lastError != null) { log.error(lastError); } boolean isQueue = queryNum < queries.size() - 1; ExecutionQueueErrorResponse response = ExecutionQueueErrorJob.showError( isQueue ? "SQL script execution" : "SQL query execution", lastError, isQueue); boolean stopScript = false; switch (response) { case STOP: // just stop execution stopScript = true; break; case RETRY: // just make it again continue; case IGNORE: // Just do nothing break; case IGNORE_ALL: errorHandling = SQLScriptErrorHandling.IGNORE; break; } if (stopScript) { break; } } // Check monitor if (monitor.isCanceled()) { break; } monitor.worked(1); queryNum++; } showExecutionResult(session); monitor.done(); // Commit data if (txnManager != null && !oldAutoCommit && commitType != SQLScriptCommitType.AUTOCOMMIT) { if (lastError == null || errorHandling == SQLScriptErrorHandling.STOP_COMMIT) { if (commitType != SQLScriptCommitType.NO_COMMIT) { monitor.beginTask("Commit data", 1); txnManager.commit(session); monitor.done(); } } else { monitor.beginTask("Rollback data", 1); txnManager.rollback(session, null); monitor.done(); } } // Restore transactions settings if (txnManager != null && !oldAutoCommit && newAutoCommit) { txnManager.setAutoCommit(monitor, false); } QMUtils.getDefaultHandler().handleScriptEnd(session); // Return success return new Status(Status.OK, DBeaverCore.getCorePluginID(), "SQL job completed"); } } catch (Throwable ex) { return new Status( Status.ERROR, DBeaverCore.getCorePluginID(), "Error during SQL job execution: " + ex.getMessage()); } finally { // Notify job end if (listener != null) { listener.onEndScript(statistics, lastError != null); } } } private boolean executeSingleQuery( @NotNull DBCSession session, @NotNull SQLQuery sqlQuery, boolean fireEvents) { lastError = null; final String originalQueryText = sqlQuery.getQuery(); DBCExecutionContext executionContext = getExecutionContext(); SQLQueryResult curResult = new SQLQueryResult(sqlQuery); if (rsOffset > 0) { curResult.setRowOffset(rsOffset); } SQLQuery originalQuery = sqlQuery; long startTime = System.currentTimeMillis(); if (fireEvents && listener != null) { // Notify query start listener.onStartQuery(sqlQuery); } try { // Prepare statement closeStatement(); // Check and invalidate connection DBPDataSource dataSource = executionContext.getDataSource(); if (!connectionInvalidated && dataSource .getContainer() .getPreferenceStore() .getBoolean(DBeaverPreferences.STATEMENT_INVALIDATE_BEFORE_EXECUTE)) { executionContext.invalidateContext(session.getProgressMonitor()); connectionInvalidated = true; } try { // Modify query (filters + parameters) if (dataFilter != null && dataFilter.hasFilters() && dataSource instanceof SQLDataSource) { String filteredQueryText = ((SQLDataSource) dataSource) .getSQLDialect() .addFiltersToQuery(dataSource, originalQueryText, dataFilter); sqlQuery = new SQLQuery(filteredQueryText, sqlQuery.getOffset(), sqlQuery.getLength()); } } catch (DBException e) { throw new DBCException("Can't apply query filter", e); } Boolean hasParameters = prepareStatementParameters(sqlQuery); if (hasParameters == null) { return false; } statistics.setQueryText(originalQueryText); startTime = System.currentTimeMillis(); DBCExecutionSource source = new AbstractExecutionSource( dataContainer, executionContext, partSite.getPart(), sqlQuery); curStatement = DBUtils.prepareStatement( source, session, hasParameters ? DBCStatementType.QUERY : DBCStatementType.SCRIPT, sqlQuery, rsOffset, rsMaxRows); if (hasParameters) { bindStatementParameters(session, sqlQuery); } // Execute statement try { boolean hasResultSet = curStatement.executeStatement(); curResult.setHasResultSet(hasResultSet); statistics.addExecuteTime(System.currentTimeMillis() - startTime); statistics.addStatementsCount(); long updateCount = -1; while (hasResultSet || resultSetNumber == 0 || updateCount >= 0) { // Fetch data only if we have to fetch all results or if it is rs requested if (fetchResultSetNumber < 0 || fetchResultSetNumber == resultSetNumber) { if (hasResultSet && fetchResultSets) { DBDDataReceiver dataReceiver = resultsConsumer.getDataReceiver(sqlQuery, resultSetNumber); if (dataReceiver != null) { hasResultSet = fetchQueryData( session, curStatement.openResultSet(), curResult, dataReceiver, true); } } } if (!hasResultSet) { try { updateCount = curStatement.getUpdateRowCount(); if (updateCount >= 0) { curResult.setUpdateCount(updateCount); statistics.addRowsUpdated(updateCount); } } catch (DBCException e) { // In some cases we can't read update count // This is bad but we can live with it // Just print a warning log.warn("Can't obtain update count", e); } } if (hasResultSet && fetchResultSets) { resultSetNumber++; fetchResultSetNumber = resultSetNumber; } if (!hasResultSet && updateCount < 0) { // Nothing else to fetch break; } if (dataSource.getInfo().supportsMultipleResults()) { hasResultSet = curStatement.nextResults(); updateCount = hasResultSet ? -1 : 0; } else { break; } } try { curResult.setWarnings(curStatement.getStatementWarnings()); } catch (Throwable e) { log.warn("Can't read execution warnings", e); } } finally { // monitor.subTask("Close query"); if (!keepStatementOpen()) { closeStatement(); } // Release parameters releaseStatementParameters(sqlQuery); } } catch (Throwable ex) { if (!(ex instanceof DBException)) { log.error("Unexpected error while processing SQL", ex); } curResult.setError(ex); lastError = ex; } finally { curResult.setQueryTime(System.currentTimeMillis() - startTime); if (fireEvents && listener != null) { // Notify query end listener.onEndQuery(curResult); } } if (curResult.getError() != null && errorHandling != SQLScriptErrorHandling.IGNORE) { return false; } // Success lastGoodQuery = originalQuery; return true; } private void showExecutionResult(DBCSession session) throws DBCException { if (statistics.getStatementsCount() > 1 || resultSetNumber == 0) { SQLQuery query = new SQLQuery("", -1, -1); if (queries.size() == 1) { query.setQuery(queries.get(0).getQuery()); } query.setData(STATS_RESULTS); // It will set tab name to "Stats" DBDDataReceiver dataReceiver = resultsConsumer.getDataReceiver(query, resultSetNumber); if (dataReceiver != null) { fetchExecutionResult(session, dataReceiver, query); } } } private void fetchExecutionResult( @NotNull DBCSession session, @NotNull DBDDataReceiver dataReceiver, @NotNull SQLQuery query) throws DBCException { // Fetch fake result set // DBCStatement statsStatement; StatResultSet fakeResultSet = new StatResultSet(session, curStatement); SQLQueryResult resultInfo = new SQLQueryResult(query); if (statistics.getStatementsCount() > 1) { // Multiple statements - show script statistics fakeResultSet.addColumn("Queries", DBPDataKind.NUMERIC); fakeResultSet.addColumn("Updated Rows", DBPDataKind.NUMERIC); fakeResultSet.addColumn("Execute time", DBPDataKind.NUMERIC); fakeResultSet.addColumn("Fetch time", DBPDataKind.NUMERIC); fakeResultSet.addColumn("Total time", DBPDataKind.NUMERIC); fakeResultSet.addRow( statistics.getStatementsCount(), statistics.getRowsUpdated(), statistics.getExecuteTime(), statistics.getFetchTime(), statistics.getTotalTime()); resultInfo.setResultSetName("Statistics"); } else { // Single statement long updateCount = statistics.getRowsUpdated(); if (updateCount >= 0) { fakeResultSet.addColumn("Query", DBPDataKind.STRING); fakeResultSet.addColumn("Updated Rows", DBPDataKind.NUMERIC); fakeResultSet.addRow(query.getQuery(), updateCount); } else { fakeResultSet.addColumn("Result", DBPDataKind.NUMERIC); } resultInfo.setResultSetName("Result"); } fetchQueryData(session, fakeResultSet, resultInfo, dataReceiver, false); } private Boolean prepareStatementParameters(SQLQuery sqlStatement) { // Bind parameters if (!CommonUtils.isEmpty(sqlStatement.getParameters())) { List<SQLQueryParameter> unresolvedParams = new ArrayList<>(); for (SQLQueryParameter param : sqlStatement.getParameters()) { if (!param.isResolved()) { unresolvedParams.add(param); } } if (!CommonUtils.isEmpty(unresolvedParams)) { // Resolve parameters if (!fillStatementParameters(unresolvedParams)) { return null; } } // Set values for all parameters return true; } return false; } private boolean fillStatementParameters(final List<SQLQueryParameter> parameters) { final RunnableWithResult<Boolean> binder = new RunnableWithResult<Boolean>() { @Override public void run() { SQLQueryParameterBindDialog dialog = new SQLQueryParameterBindDialog(partSite, getExecutionContext(), parameters); result = (dialog.open() == IDialogConstants.OK_ID); } }; UIUtils.runInUI(partSite.getShell(), binder); Boolean result = binder.getResult(); return result != null && result; } private void bindStatementParameters(DBCSession session, SQLQuery sqlStatement) throws DBCException { // Bind them for (SQLQueryParameter param : sqlStatement.getParameters()) { if (param.isResolved()) { // convert value to native form Object realValue = param.getValueHandler().getValueFromObject(session, param, param.getValue(), false); // bind param .getValueHandler() .bindValueObject(session, curStatement, param, param.getOrdinalPosition(), realValue); } } } private void releaseStatementParameters(SQLQuery sqlStatement) { if (!CommonUtils.isEmpty(sqlStatement.getParameters())) { for (SQLQueryParameter param : sqlStatement.getParameters()) { if (param.isResolved()) { param.getValueHandler().releaseValueObject(param.getValue()); } } } } private boolean fetchQueryData( DBCSession session, DBCResultSet resultSet, SQLQueryResult result, DBDDataReceiver dataReceiver, boolean updateStatistics) throws DBCException { if (dataReceiver == null) { // No data pump - skip fetching stage return false; } if (resultSet == null) { return false; } boolean keepCursor = keepStatementOpen(); if (keepCursor) { curResultSets.add(resultSet); } DBRProgressMonitor monitor = session.getProgressMonitor(); monitor.subTask("Fetch result set"); long rowCount = 0; dataReceiver.fetchStart(session, resultSet, rsOffset, rsMaxRows); try { // Retrieve source entity if (result != null) { DBCResultSetMetaData rsMeta = resultSet.getMeta(); String sourceName = null; // resultSet.getResultSetName(); for (DBCAttributeMetaData attr : rsMeta.getAttributes()) { String entityName = attr.getEntityName(); if (!CommonUtils.isEmpty(entityName)) { if (sourceName == null) { sourceName = entityName; } else if (!sourceName.equals(entityName)) { // Multiple source entities sourceName += "(+)"; break; } } } /* if (CommonUtils.isEmpty(sourceName)) { try { sourceName = resultSet.getResultSetName(); } catch (DBCException e) { log.debug(e); } } */ if (CommonUtils.isEmpty(sourceName)) { sourceName = "Result"; } result.setResultSetName(sourceName); } long fetchStartTime = System.currentTimeMillis(); // Fetch all rows while ((!hasLimits() || rowCount < rsMaxRows) && resultSet.nextRow()) { if (monitor.isCanceled()) { break; } rowCount++; if (rowCount > 0 && rowCount % 100 == 0) { monitor.subTask(rowCount + " rows fetched"); monitor.worked(100); } dataReceiver.fetchRow(session, resultSet); } if (updateStatistics) { statistics.addFetchTime(System.currentTimeMillis() - fetchStartTime); } } finally { if (!keepCursor) { try { resultSet.close(); } catch (Throwable e) { log.error("Error while closing resultset", e); } } try { dataReceiver.fetchEnd(session, resultSet); } catch (Throwable e) { log.error("Error while handling end of result set fetch", e); } dataReceiver.close(); } if (result != null) { result.setRowCount(rowCount); } if (updateStatistics) { statistics.setRowsFetched(rowCount); } monitor.subTask(rowCount + " rows fetched"); return true; } private boolean keepStatementOpen() { // Only in single query mode and if pref option set to true return queries.size() == 1 && getDataSourceContainer() .getPreferenceStore() .getBoolean(DBeaverPreferences.KEEP_STATEMENT_OPEN); } private void closeStatement() { if (curStatement != null) { for (DBCResultSet resultSet : curResultSets) { resultSet.close(); } curResultSets.clear(); try { curStatement.close(); } catch (Throwable e) { log.error("Error closing statement", e); } curStatement = null; } } /* protected void canceling() { // Cancel statement only for the second time cancel is called */ /*if (!statementCancel) { statementCancel = true; } else */ /* { if (!statementCanceled && curStatement != null) { try { curStatement.cancelBlock(); } catch (DBException e) { log.error("Can't cancel execution: " + e.getMessage()); } statementCanceled = true; } } } */ public void extractData(DBCSession session) throws DBCException { statistics = new DBCStatistics(); if (queries.size() != 1) { throw new DBCException("Invalid state of SQL Query job"); } resultSetNumber = 0; SQLQuery query = queries.get(0); session.getProgressMonitor().beginTask(query.getQuery(), 1); try { boolean result = executeSingleQuery(session, query, true); if (!result && lastError != null) { if (lastError instanceof DBCException) { throw (DBCException) lastError; } else { throw new DBCException(lastError, getExecutionContext().getDataSource()); } } else if (result) { showExecutionResult(session); } } finally { session.getProgressMonitor().done(); } } public void setDataFilter(DBDDataFilter dataFilter) { this.dataFilter = dataFilter; } public DBCStatistics getStatistics() { return statistics; } public void setFetchResultSetNumber(int fetchResultSetNumber) { this.fetchResultSetNumber = fetchResultSetNumber; } }
public abstract class AbstractSearchPage extends DialogPage implements IObjectSearchPage { protected static final Log log = Log.getLog(AbstractSearchPage.class); protected IObjectSearchContainer container; protected AbstractSearchPage(String title) { super(title); } @Override public void setSearchContainer(IObjectSearchContainer container) { this.container = container; } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { updateEnablement(); } } protected abstract void updateEnablement(); protected static List<DBNNode> loadTreeState(DBPPreferenceStore store, String propName) { final List<DBNNode> result = new ArrayList<>(); final String sources = store.getString(propName); if (!CommonUtils.isEmpty(sources)) { try { DBeaverUI.runInProgressService( new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) { // Keep broken datasources to make connect attempt only once Set<DBNDataSource> brokenDataSources = new HashSet<>(); // Find all nodes StringTokenizer st = new StringTokenizer(sources, "|"); // $NON-NLS-1$ while (st.hasMoreTokens()) { String nodePath = st.nextToken(); try { DBNDataSource dsNode = DBeaverCore.getInstance().getNavigatorModel().getDataSourceByPath(nodePath); if (brokenDataSources.contains(dsNode)) { continue; } DBNNode node = DBeaverCore.getInstance() .getNavigatorModel() .getNodeByPath(monitor, nodePath); if (node != null) { result.add(node); } else { brokenDataSources.add(dsNode); } } catch (DBException e) { log.error(e); } } } }); } catch (InvocationTargetException e) { log.error(e.getTargetException()); } catch (InterruptedException e) { // ignore } } return result; } }
/** Abstract connection wizard */ public abstract class ConnectionWizard extends Wizard implements INewWizard { private static final Log log = Log.getLog(ConnectionWizard.class); // protected final IProject project; private final Map<DriverDescriptor, DataSourceDescriptor> infoMap = new HashMap<>(); private boolean resized = false; protected ConnectionWizard() { setNeedsProgressMonitor(true); } @Override public void dispose() { // Dispose all temp data sources for (DataSourceDescriptor dataSource : infoMap.values()) { dataSource.dispose(); } super.dispose(); } public abstract DBPDataSourceRegistry getDataSourceRegistry(); abstract DriverDescriptor getSelectedDriver(); public abstract ConnectionPageSettings getPageSettings(); protected abstract void saveSettings(DataSourceDescriptor dataSource); @NotNull public DataSourceDescriptor getActiveDataSource() { DriverDescriptor driver = getSelectedDriver(); DataSourceDescriptor info = infoMap.get(driver); if (info == null) { DBPConnectionConfiguration connectionInfo = new DBPConnectionConfiguration(); info = new DataSourceDescriptor( getDataSourceRegistry(), DataSourceDescriptor.generateNewId(getSelectedDriver()), getSelectedDriver(), connectionInfo); info.getConnectionConfiguration().setClientHomeId(driver.getDefaultClientHomeId()); infoMap.put(driver, info); } return info; } public void testConnection() { DataSourceDescriptor dataSource = getPageSettings().getActiveDataSource(); DataSourceDescriptor testDataSource = new DataSourceDescriptor( getDataSourceRegistry(), dataSource.getId(), getSelectedDriver(), new DBPConnectionConfiguration(dataSource.getConnectionConfiguration())); try { saveSettings(testDataSource); final ConnectionTester op = new ConnectionTester(testDataSource); try { getContainer() .run( true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { // Wait for job to finish op.ownerMonitor = RuntimeUtils.makeMonitor(monitor); op.schedule(); while (op.getState() == Job.WAITING || op.getState() == Job.RUNNING) { if (monitor.isCanceled()) { op.cancel(); throw new InterruptedException(); } try { Thread.sleep(50); } catch (InterruptedException e) { break; } } if (op.getConnectError() != null) { throw new InvocationTargetException(op.getConnectError()); } } }); String message = ""; if (!CommonUtils.isEmpty(op.productName)) { message += "Server: " + op.productName + " " + op.productVersion + "\n"; } if (!CommonUtils.isEmpty(op.driverName)) { message += "Driver: " + op.driverName + " " + op.driverVersion + "\n"; } if (!CommonUtils.isEmpty(message)) { message += "\n"; } message += NLS.bind( CoreMessages.dialog_connection_wizard_start_connection_monitor_connected, op.connectTime); MessageDialog.openInformation( getShell(), CoreMessages.dialog_connection_wizard_start_connection_monitor_success, message); } catch (InterruptedException ex) { UIUtils.showErrorDialog( getShell(), CoreMessages.dialog_connection_wizard_start_dialog_interrupted_title, CoreMessages.dialog_connection_wizard_start_dialog_interrupted_message); } catch (InvocationTargetException ex) { UIUtils.showErrorDialog( getShell(), CoreMessages.dialog_connection_wizard_start_dialog_error_title, null, GeneralUtils.makeExceptionStatus(ex.getTargetException())); } } finally { testDataSource.dispose(); } } public boolean isNew() { return false; } public void resizeShell() { if (!resized) { Shell shell = getContainer().getShell(); Point shellSize = shell.getSize(); Point compSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT); if (shellSize.y < compSize.y) { shell.setSize(compSize); shell.layout(true); } resized = true; } } private class ConnectionTester extends ConnectJob { String productName; String productVersion; String driverName; String driverVersion; long connectTime = -1; DBRProgressMonitor ownerMonitor; public ConnectionTester(DataSourceDescriptor testDataSource) { super(testDataSource); setSystem(true); super.initialize = true; // CommonUtils.toBoolean(testDataSource.getDriver().getDriverParameter(DBConstants.PARAM_INIT_ON_TEST)); productName = null; productVersion = null; } @Override public IStatus run(DBRProgressMonitor monitor) { if (ownerMonitor != null) { monitor = ownerMonitor; } monitor.beginTask(CoreMessages.dialog_connection_wizard_start_connection_monitor_start, 4); Thread.currentThread() .setName(CoreMessages.dialog_connection_wizard_start_connection_monitor_thread); try { container.setName(container.getConnectionConfiguration().getUrl()); monitor.worked(1); long startTime = System.currentTimeMillis(); super.run(monitor); connectTime = (System.currentTimeMillis() - startTime); if (connectError != null || monitor.isCanceled()) { return Status.OK_STATUS; } monitor.worked(1); DBPDataSource dataSource = container.getDataSource(); if (dataSource == null) { throw new DBException(CoreMessages.editors_sql_status_not_connected_to_database); } // monitor.subTask("Initialize connection"); // dataSource.initialize(monitor); // monitor.worked(1); monitor.subTask( CoreMessages.dialog_connection_wizard_start_connection_monitor_subtask_test); DBPDataSourceInfo info = dataSource.getInfo(); if (info != null) { try { productName = info.getDatabaseProductName(); productVersion = info.getDatabaseProductVersion(); driverName = info.getDriverName(); driverVersion = info.getDriverVersion(); } catch (Exception e) { log.error("Can't obtain connection metadata", e); } } else { try (DBCSession session = DBUtils.openUtilSession(monitor, dataSource, "Test connection")) { if (session instanceof Connection) { try { Connection connection = (Connection) session; DatabaseMetaData metaData = connection.getMetaData(); productName = metaData.getDatabaseProductName(); productVersion = metaData.getDatabaseProductVersion(); driverName = metaData.getDriverName(); driverVersion = metaData.getDriverVersion(); } catch (Exception e) { log.error("Can't obtain connection metadata", e); } } } } new DisconnectJob(container).schedule(); monitor.subTask(CoreMessages.dialog_connection_wizard_start_connection_monitor_success); } catch (DBException ex) { connectError = ex; } monitor.done(); return Status.OK_STATUS; } } }
public class LoadingJob<RESULT> extends AbstractJob { private static final Log log = Log.getLog(LoadingJob.class); public static final Object LOADING_FAMILY = new Object(); public static <RESULT> LoadingJob<RESULT> createService( ILoadService<RESULT> loadingService, ILoadVisualizer<RESULT> visualizer) { return new LoadingJob<RESULT>(loadingService, visualizer); } private ILoadService<RESULT> loadingService; private ILoadVisualizer<RESULT> visualizer; public LoadingJob(ILoadService<RESULT> loadingService, ILoadVisualizer<RESULT> visualizer) { super(loadingService.getServiceName()); this.loadingService = loadingService; this.visualizer = visualizer; setUser(false); } public ILoadService<RESULT> getLoadingService() { return loadingService; } public ILoadVisualizer<RESULT> getVisualizer() { return visualizer; } @Override protected IStatus run(DBRProgressMonitor monitor) { return run(monitor, true); } private IStatus run(DBRProgressMonitor monitor, boolean lazy) { monitor = visualizer.overwriteMonitor(monitor); LoadingUIJob<RESULT> updateUIJob = new LoadingUIJob<>(this, monitor); updateUIJob.schedule(); this.loadingService.setProgressMonitor(monitor); Throwable error = null; RESULT result = null; try { result = this.loadingService.evaluate(); } catch (InvocationTargetException e) { // log.error(e.getTargetException()); error = e.getTargetException(); } catch (InterruptedException e) { return new Status(Status.CANCEL, DBeaverCore.PLUGIN_ID, "Loading interrupted"); } finally { UIUtils.runInUI(null, new LoadFinisher(result, error)); } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return family == loadingService.getFamily(); } public void syncRun() { run(VoidProgressMonitor.INSTANCE, false); } private class LoadFinisher implements Runnable { private final RESULT innerResult; private final Throwable innerError; public LoadFinisher(RESULT innerResult, Throwable innerError) { this.innerResult = innerResult; this.innerError = innerError; } @Override public void run() { visualizer.completeLoading(innerResult); if (innerError != null) { log.debug(innerError); UIUtils.showErrorDialog(null, getName(), null, innerError); } } } static class LoadingUIJob<RESULT> extends AbstractUIJob { private static final Log log = Log.getLog(LoadingUIJob.class); private static final long DELAY = 200; private ILoadService<RESULT> loadService; private ILoadVisualizer<RESULT> visualizer; private DBRProgressMonitor mainMonitor; LoadingUIJob(LoadingJob<RESULT> loadingJob, DBRProgressMonitor mainMonitor) { super(loadingJob.getName()); this.loadService = loadingJob.getLoadingService(); this.visualizer = loadingJob.getVisualizer(); this.mainMonitor = mainMonitor; setSystem(true); } @Override public IStatus runInUIThread(DBRProgressMonitor monitor) { /* if (mainMonitor.isCanceled()) { // Try to cancel current load service try { loadService.cancel(); } catch (InvocationTargetException e) { log.warn("Error while canceling service", e.getTargetException()); } return Status.CANCEL_STATUS; } else { */ if (!visualizer.isCompleted()) { visualizer.visualizeLoading(); schedule(DELAY); } // } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return family == LOADING_FAMILY; } @Override protected void canceling() { super.canceling(); } } }
public class CompareObjectsWizard extends Wizard implements IExportWizard { static final Log log = Log.getLog(CompareObjectsWizard.class); private static final String RS_COMPARE_WIZARD_DIALOG_SETTINGS = "CompareWizard"; // $NON-NLS-1$ private CompareObjectsSettings settings; public CompareObjectsWizard(List<DBNDatabaseNode> nodes) { this.settings = new CompareObjectsSettings(nodes); IDialogSettings section = UIUtils.getDialogSettings(RS_COMPARE_WIZARD_DIALOG_SETTINGS); setDialogSettings(section); settings.loadFrom(section); } @Override public void dispose() { super.dispose(); } public CompareObjectsSettings getSettings() { return settings; } @Override public void addPages() { super.addPages(); addPage(new CompareObjectsPageSettings()); addPage(new CompareObjectsPageOutput()); } @Override public void init(IWorkbench workbench, IStructuredSelection currentSelection) { setWindowTitle("Compare objects"); setNeedsProgressMonitor(true); } private void showError(String error) { ((WizardPage) getContainer().getCurrentPage()).setErrorMessage(error); } @Override public boolean performFinish() { // Save settings getSettings().saveTo(getDialogSettings()); showError(null); // Compare final CompareObjectsExecutor executor = new CompareObjectsExecutor(settings); try { DBeaverUI.run( getContainer(), true, true, new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { CompareReport report = generateReport(monitor, executor); renderReport(monitor, report); } catch (DBException e) { throw new InvocationTargetException(e); } } }); UIUtils.showMessageBox( getShell(), "Objects compare", "Objects compare finished", SWT.ICON_INFORMATION); } catch (InvocationTargetException e) { if (executor.getInitializeError() != null) { showError(executor.getInitializeError().getMessage()); } else { log.error(e.getTargetException()); showError(e.getTargetException().getMessage()); } return false; } catch (InterruptedException e) { showError("Compare interrupted"); return false; } finally { executor.dispose(); } // Done return true; } private CompareReport generateReport(DBRProgressMonitor monitor, CompareObjectsExecutor executor) throws DBException, InterruptedException { monitor.beginTask("Compare objects", 1000); CompareReport report = executor.compareObjects(monitor, getSettings().getNodes()); monitor.done(); return report; } private void renderReport(DBRProgressMonitor monitor, CompareReport report) { try { File reportFile; switch (settings.getOutputType()) { case BROWSER: reportFile = File.createTempFile("compare-report", ".html"); break; default: { StringBuilder fileName = new StringBuilder("compare"); // "compare-report.html"; for (DBNDatabaseNode node : report.getNodes()) { fileName.append("-").append(CommonUtils.escapeIdentifier(node.getName())); } fileName.append("-report.html"); reportFile = new File(settings.getOutputFolder(), fileName.toString()); break; } } reportFile.deleteOnExit(); OutputStream outputStream = new FileOutputStream(reportFile); try { monitor.beginTask("Render report", report.getReportLines().size()); CompareReportRenderer reportRenderer = new CompareReportRenderer(); reportRenderer.renderReport(monitor, report, getSettings(), outputStream); monitor.done(); } finally { ContentUtils.close(outputStream); } UIUtils.launchProgram(reportFile.getAbsolutePath()); } catch (IOException e) { showError(e.getMessage()); log.error(e); } } }
/** UI Utils */ public class UIUtils { static final Log log = Log.getLog(UIUtils.class); public static final String DEFAULT_TIMESTAMP_PATTERN = "yyyy.MM.dd HH:mm"; public static final String INLINE_WIDGET_EDITOR_ID = "org.jkiss.dbeaver.ui.InlineWidgetEditor"; public static VerifyListener getIntegerVerifyListener(Locale locale) { final DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); return new VerifyListener() { @Override public void verifyText(VerifyEvent e) { for (int i = 0; i < e.text.length(); i++) { char ch = e.text.charAt(i); if (!Character.isDigit(ch) && ch != symbols.getMinusSign() && ch != symbols.getGroupingSeparator()) { e.doit = false; return; } } e.doit = true; } }; } public static VerifyListener getNumberVerifyListener(Locale locale) { DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); final char[] allowedChars = new char[] { symbols.getDecimalSeparator(), symbols.getGroupingSeparator(), symbols.getMinusSign(), symbols.getZeroDigit(), symbols.getMonetaryDecimalSeparator(), '+' }; final String exponentSeparator = symbols.getExponentSeparator(); return new VerifyListener() { @Override public void verifyText(VerifyEvent e) { for (int i = 0; i < e.text.length(); i++) { char ch = e.text.charAt(i); if (!Character.isDigit(ch) && !ArrayUtils.contains(allowedChars, ch) && exponentSeparator.indexOf(ch) == -1) { e.doit = false; return; } } e.doit = true; } }; } public static ToolItem createToolItem( ToolBar toolBar, String text, Image icon, final IAction action) { ToolItem item = new ToolItem(toolBar, SWT.PUSH); item.setToolTipText(text); if (icon != null) { item.setImage(icon); } item.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { action.run(); } }); return item; } public static TableColumn createTableColumn(Table table, int style, String text) { TableColumn column = new TableColumn(table, style); column.setText(text); return column; } public static TreeColumn createTreeColumn(Tree tree, int style, String text) { TreeColumn column = new TreeColumn(tree, style); column.setText(text); return column; } public static void packColumns(Table table) { packColumns(table, false); } public static void packColumns(Table table, boolean fit) { table.setRedraw(false); try { int totalWidth = 0; final TableColumn[] columns = table.getColumns(); for (TableColumn column : columns) { column.pack(); totalWidth += column.getWidth(); } final Rectangle clientArea = table.getClientArea(); if (clientArea.width > 0 && totalWidth > clientArea.width) { for (TableColumn column : columns) { int colWidth = column.getWidth(); if (colWidth > totalWidth / 3) { // If some columns is too big (more than 33% of total width) // Then shrink it to 30% column.setWidth(totalWidth / 3); totalWidth -= colWidth; totalWidth += column.getWidth(); } } int extraSpace = totalWidth - clientArea.width; for (TableColumn tc : columns) { double ratio = (double) tc.getWidth() / totalWidth; int newWidth = (int) (tc.getWidth() - extraSpace * ratio); tc.setWidth(newWidth); } } if (fit && totalWidth < clientArea.width) { int sbWidth = 0; if (table.getVerticalBar() != null) { sbWidth = table.getVerticalBar().getSize().x; } if (columns.length > 0) { float extraSpace = (clientArea.width - totalWidth - sbWidth) / columns.length; for (TableColumn tc : columns) { tc.setWidth((int) (tc.getWidth() + extraSpace)); } } } } finally { table.setRedraw(true); } } public static void packColumns(@NotNull Tree tree) { packColumns(tree, false, null); } public static void packColumns(@NotNull Tree tree, boolean fit, @Nullable float[] ratios) { tree.setRedraw(false); try { // Check for disposed items // TODO: it looks like SWT error. Sometimes tree items are disposed and NPE is thrown from // column.pack for (TreeItem item : tree.getItems()) { if (item.isDisposed()) { return; } } int totalWidth = 0; final TreeColumn[] columns = tree.getColumns(); for (TreeColumn column : columns) { column.pack(); totalWidth += column.getWidth(); } Rectangle clientArea = tree.getClientArea(); if (clientArea.isEmpty()) { return; } if (fit) { int areaWidth = clientArea.width; if (tree.getVerticalBar() != null) { areaWidth -= tree.getVerticalBar().getSize().x; } if (totalWidth > areaWidth) { int extraSpace = totalWidth - areaWidth; for (TreeColumn tc : columns) { double ratio = (double) tc.getWidth() / totalWidth; tc.setWidth((int) (tc.getWidth() - extraSpace * ratio)); } } else if (totalWidth < areaWidth) { float extraSpace = areaWidth - totalWidth; if (columns.length > 0) { if (ratios == null || ratios.length < columns.length) { extraSpace /= columns.length; extraSpace--; for (TreeColumn tc : columns) { tc.setWidth((int) (tc.getWidth() + extraSpace)); } } else { for (int i = 0; i < columns.length; i++) { TreeColumn tc = columns[i]; tc.setWidth((int) (tc.getWidth() + extraSpace * ratios[i])); } } } } } } finally { tree.setRedraw(true); } } public static void maxTableColumnsWidth(Table table) { table.setRedraw(false); try { int columnCount = table.getColumnCount(); if (columnCount > 0) { int totalWidth = 0; final TableColumn[] columns = table.getColumns(); for (TableColumn tc : columns) { tc.pack(); totalWidth += tc.getWidth(); } final Rectangle clientArea = table.getClientArea(); if (totalWidth < clientArea.width) { int extraSpace = clientArea.width - totalWidth; extraSpace /= columnCount; for (TableColumn tc : columns) { tc.setWidth(tc.getWidth() + extraSpace); } } } } finally { table.setRedraw(true); } } public static int getColumnAtPos(TableItem item, int x, int y) { int columnCount = item.getParent().getColumnCount(); for (int i = 0; i < columnCount; i++) { Rectangle rect = item.getBounds(i); if (rect.contains(x, y)) { return i; } } return -1; } public static int getColumnAtPos(TreeItem item, int x, int y) { int columnCount = item.getParent().getColumnCount(); for (int i = 0; i < columnCount; i++) { Rectangle rect = item.getBounds(i); if (rect.contains(x, y)) { return i; } } return -1; } public static void sortTable(Table table, Comparator<TableItem> comparator) { int columnCount = table.getColumnCount(); String[] values = new String[columnCount]; TableItem[] items = table.getItems(); for (int i = 1; i < items.length; i++) { for (int j = 0; j < i; j++) { TableItem item = items[i]; if (comparator.compare(item, items[j]) < 0) { for (int k = 0; k < columnCount; k++) { values[k] = item.getText(k); } Object data = item.getData(); boolean checked = item.getChecked(); item.dispose(); item = new TableItem(table, SWT.NONE, j); item.setText(values); item.setData(data); item.setChecked(checked); items = table.getItems(); break; } } } } public static TableItem getNextTableItem(Table table, TableItem item) { TableItem[] items = table.getItems(); for (int i = 0; i < items.length - 1; i++) { if (items[i] == item) { return items[i + 1]; } } return null; } public static void dispose(Widget widget) { if (widget != null && !widget.isDisposed()) { try { widget.dispose(); } catch (Exception e) { log.debug("widget dispose error", e); } } } public static void dispose(Resource resource) { if (resource != null && !resource.isDisposed()) { try { resource.dispose(); } catch (Exception e) { log.debug("Resource dispose error", e); } } } public static void showMessageBox( final Shell shell, final String title, final String info, final int messageType) { Runnable runnable = new Runnable() { @Override public void run() { MessageBox messageBox = new MessageBox(shell, messageType | SWT.OK); messageBox.setMessage(info); messageBox.setText(title); messageBox.open(); } }; runInUI(shell, runnable); } public static boolean confirmAction( final Shell shell, final String title, final String question) { RunnableWithResult<Boolean> confirmer = new RunnableWithResult<Boolean>() { @Override public void run() { MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.YES | SWT.NO); messageBox.setMessage(question); messageBox.setText(title); int response = messageBox.open(); result = (response == SWT.YES); } }; runInUI(shell, confirmer); return confirmer.getResult(); } public static Font makeBoldFont(Font normalFont) { return modifyFont(normalFont, SWT.BOLD); } public static Font modifyFont(Font normalFont, int style) { FontData[] fontData = normalFont.getFontData(); fontData[0].setStyle(fontData[0].getStyle() | style); return new Font(normalFont.getDevice(), fontData[0]); } public static Group createControlGroup( Composite parent, String label, int columns, int layoutStyle, int widthHint) { Group group = new Group(parent, SWT.NONE); group.setText(label); GridData gd = new GridData(layoutStyle); if (widthHint > 0) { gd.widthHint = widthHint; } group.setLayoutData(gd); GridLayout gl = new GridLayout(columns, false); group.setLayout(gl); return group; } public static Label createControlLabel(Composite parent, String label) { Label textLabel = new Label(parent, SWT.NONE); textLabel.setText(label + ": "); // $NON-NLS-1$ return textLabel; } public static Label createTextLabel(Composite parent, String label) { Label textLabel = new Label(parent, SWT.NONE); textLabel.setText(label); return textLabel; } public static Label createImageLabel(Composite parent, DBPImage image) { Label imageLabel = new Label(parent, SWT.NONE); imageLabel.setImage(DBeaverIcons.getImage(image)); return imageLabel; } public static Text createLabelText(Composite parent, String label, String value) { return createLabelText(parent, label, value, SWT.BORDER); } public static Text createLabelText(Composite parent, String label, String value, int style) { return createLabelText(parent, label, value, style, new GridData(GridData.FILL_HORIZONTAL)); } @NotNull public static Text createLabelText( @NotNull Composite parent, @NotNull String label, @Nullable String value, int style, @Nullable Object layoutData) { createControlLabel(parent, label); Text text = new Text(parent, style); if (value != null) { text.setText(value); } if (layoutData != null) { text.setLayoutData(layoutData); } return text; } @NotNull public static Spinner createLabelSpinner( @NotNull Composite parent, @NotNull String label, int value, int minimum, int maximum) { createControlLabel(parent, label); Spinner spinner = new Spinner(parent, SWT.BORDER); spinner.setMinimum(minimum); spinner.setMaximum(maximum); spinner.setSelection(value); return spinner; } @NotNull public static Button createLabelCheckbox(Composite parent, String label, boolean checked) { return createLabelCheckbox(parent, label, null, checked, SWT.NONE); } @NotNull public static Button createLabelCheckbox( Composite parent, String label, String tooltip, boolean checked) { return createLabelCheckbox(parent, label, tooltip, checked, SWT.NONE); } @NotNull public static Button createLabelCheckbox( @NotNull Composite parent, @NotNull String label, @Nullable String tooltip, boolean checked, int style) { Label labelControl = createControlLabel(parent, label); // labelControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); final Button button = new Button(parent, SWT.CHECK | style); if (checked) { button.setSelection(true); } labelControl.addMouseListener( new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { if (!button.isDisposed() && button.isVisible() && button.isEnabled()) { button.setSelection(!button.getSelection()); button.notifyListeners(SWT.Selection, new Event()); } } }); if (tooltip != null) { labelControl.setToolTipText(tooltip); button.setToolTipText(tooltip); } return button; } public static Button createCheckbox(Composite parent, String label, boolean checked) { final Button button = new Button(parent, SWT.CHECK); button.setText(label); if (checked) { button.setSelection(true); } return button; } public static Combo createLabelCombo(Composite parent, String label, int style) { Label labelControl = createControlLabel(parent, label); // labelControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); final Combo combo = new Combo(parent, style); combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return combo; } public static Button createToolButton( Composite parent, String text, SelectionListener selectionListener) { Button button = new Button(parent, SWT.PUSH); button.setText(text); button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if (selectionListener != null) { button.addSelectionListener(selectionListener); } return button; } @Nullable public static Shell getActiveShell() { IWorkbench workbench = PlatformUI.getWorkbench(); return workbench == null ? null : getShell(workbench.getActiveWorkbenchWindow()); } @Nullable public static Shell getShell(IShellProvider provider) { return provider == null ? null : provider.getShell(); } @Nullable public static Shell getShell(IWorkbenchPart part) { return part == null ? null : getShell(part.getSite()); } @Nullable public static Integer getTextInteger(Text text) { String str = text.getText(); str = str.trim(); if (str.length() == 0) { return null; } try { return Integer.valueOf(str); } catch (NumberFormatException e) { log.debug(e); return null; } } @Nullable public static IHandlerActivation registerKeyBinding( IServiceLocator serviceLocator, IAction action) { IHandlerService handlerService = serviceLocator.getService(IHandlerService.class); if (handlerService != null) { return handlerService.activateHandler( action.getActionDefinitionId(), new ActionHandler(action)); } else { return null; } } public static Composite createPlaceholder(Composite parent, int columns) { return createPlaceholder(parent, columns, 0); } public static Composite createPlaceholder(Composite parent, int columns, int spacing) { Composite ph = new Composite(parent, SWT.NONE); GridLayout gl = new GridLayout(columns, false); gl.verticalSpacing = spacing; gl.horizontalSpacing = spacing; gl.marginHeight = 0; gl.marginWidth = 0; ph.setLayout(gl); return ph; } public static Label createHorizontalLine(Composite parent) { Label horizontalLine = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); horizontalLine.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1)); return horizontalLine; } @Nullable public static String getComboSelection(Combo combo) { int selectionIndex = combo.getSelectionIndex(); if (selectionIndex < 0) { return null; } return combo.getItem(selectionIndex); } public static boolean setComboSelection(Combo combo, String value) { if (value == null) { return false; } int count = combo.getItemCount(); for (int i = 0; i < count; i++) { if (value.equals(combo.getItem(i))) { combo.select(i); return true; } } return false; } public static Combo createEncodingCombo(Composite parent, String curCharset) { if (curCharset == null) { curCharset = GeneralUtils.getDefaultFileEncoding(); } Combo encodingCombo = new Combo(parent, SWT.DROP_DOWN); encodingCombo.setVisibleItemCount(30); SortedMap<String, Charset> charsetMap = Charset.availableCharsets(); int index = 0; int defIndex = -1; for (String csName : charsetMap.keySet()) { Charset charset = charsetMap.get(csName); encodingCombo.add(charset.displayName()); if (charset.displayName().equalsIgnoreCase(curCharset)) { defIndex = index; } if (defIndex < 0) { for (String alias : charset.aliases()) { if (alias.equalsIgnoreCase(curCharset)) { defIndex = index; } } } index++; } if (defIndex >= 0) { encodingCombo.select(defIndex); } else { log.warn("Charset '" + curCharset + "' is not recognized"); // $NON-NLS-1$ //$NON-NLS-2$ } return encodingCombo; } @NotNull public static SashForm createPartDivider( final IWorkbenchPart workbenchPart, Composite parent, int style) { final SashForm sash = new SashForm(parent, style); /* * //sash.setSashWidth(10); final IWorkbenchWindow workbenchWindow = workbenchPart.getSite().getWorkbenchWindow(); * //sash.setBackground(sashActiveBackground); * * final IPartListener partListener = new IPartListener() { * * @Override public void partBroughtToTop(IWorkbenchPart part) { } * * @Override public void partOpened(IWorkbenchPart part) { } * * @Override public void partClosed(IWorkbenchPart part) { } * * @Override * * @SuppressWarnings("restriction") public void partActivated(IWorkbenchPart part) { if (part == workbenchPart) { Color * sashActiveBackground = workbenchWindow.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get( * IWorkbenchThemeConstants.ACTIVE_TAB_BG_END); if (sashActiveBackground == null) { sashActiveBackground = * Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); } sash.setBackground(sashActiveBackground); } } * * @Override public void partDeactivated(IWorkbenchPart part) { if (part == workbenchPart) { * sash.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); } } }; * * final IPageListener pageListener = workbenchWindow.getActivePage() != null ? null : new IPageListener() { * * @Override public void pageActivated(IWorkbenchPage page) { } * * @Override public void pageOpened(IWorkbenchPage page) { page.addPartListener(partListener); } * * @Override public void pageClosed(IWorkbenchPage page) { page.removePartListener(partListener); } }; if (pageListener != * null) { // No active page yet, wait for it in listener workbenchWindow.addPageListener(pageListener); } else { // Add * listener to active page workbenchWindow.getActivePage().addPartListener(partListener); } * * sash.addDisposeListener(new DisposeListener() { * * @Override public void widgetDisposed(DisposeEvent e) { if (pageListener != null) { * workbenchWindow.removePageListener(pageListener); } if (workbenchWindow.getActivePage() != null) { * workbenchWindow.getActivePage().removePartListener(partListener); } } }); */ return sash; } public static void showErrorDialog( @Nullable Shell shell, @NotNull String title, @Nullable String message, @Nullable Throwable error) { if (error != null) { log.error(error); } showErrorDialog( shell, title, error == null ? null : message, error == null ? new Status(IStatus.ERROR, DBeaverCore.PLUGIN_ID, message) : GeneralUtils.makeExceptionStatus(error)); } public static void showErrorDialog( @Nullable Shell shell, @NotNull String title, @Nullable String message) { showErrorDialog(shell, title, message, (Throwable) null); } public static void showErrorDialog( @Nullable final Shell shell, @NotNull final String title, @Nullable final String message, @NotNull final IStatus status) { for (IStatus s = status; s != null; ) { if (s.getException() instanceof DBException) { if (showDatabaseError(shell, title, message, (DBException) s.getException())) { // If this DB error was handled by some DB-specific way then just don't care about it return; } break; } if (s.getChildren() != null && s.getChildren().length > 0) { s = s.getChildren()[0]; } else { break; } } // log.debug(message); Runnable runnable = new Runnable() { @Override public void run() { // Display the dialog StandardErrorDialog dialog = new StandardErrorDialog( shell == null ? DBeaverUI.getActiveWorkbenchShell() : shell, title, message, RuntimeUtils.stripStack(status), IStatus.ERROR); dialog.open(); } }; runInUI(shell, runnable); } public static void runInUI(@Nullable Shell shell, @NotNull Runnable runnable) { final Display display = shell == null || shell.isDisposed() ? Display.getDefault() : shell.getDisplay(); if (display.getThread() != Thread.currentThread()) { display.syncExec(runnable); } else { runnable.run(); } } public static void runInDetachedUI(@Nullable Shell shell, @NotNull Runnable runnable) { if (shell == null) { Display.getDefault().asyncExec(runnable); } else { try { shell.getDisplay().asyncExec(runnable); } catch (SWTException e) { // DF: Widget has been disposed, too late for some processing then.. } } } @NotNull public static String formatMessage(@Nullable String message, @Nullable Object... args) { if (message == null) { return ""; //$NON-NLS-1$ } else { return MessageFormat.format(message, args); } } @NotNull public static Button createPushButton( @NotNull Composite parent, @Nullable String label, @Nullable Image image) { Button button = new Button(parent, SWT.PUSH); if (label != null) { button.setText(label); } if (image != null) { button.setImage(image); } return button; } public static void setHelp(Control control, String pluginId, String helpContextID) { PlatformUI.getWorkbench() .getHelpSystem() .setHelp(control, pluginId + "." + helpContextID); // $NON-NLS-1$ } public static void setHelp(Control control, String helpContextID) { setHelp(control, DBeaverCore.PLUGIN_ID, helpContextID); } @NotNull public static Text createOutputFolderChooser( final Composite parent, @Nullable String label, @Nullable ModifyListener changeListener) { UIUtils.createControlLabel( parent, label != null ? label : CoreMessages.data_transfer_wizard_output_label_directory); Composite chooserPlaceholder = UIUtils.createPlaceholder(parent, 2); chooserPlaceholder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); final Text directoryText = new Text(chooserPlaceholder, SWT.BORDER); directoryText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if (changeListener != null) { directoryText.addModifyListener(changeListener); } final Runnable folderChooser = new Runnable() { @Override public void run() { DirectoryDialog dialog = new DirectoryDialog(parent.getShell(), SWT.NONE); dialog.setMessage(CoreMessages.data_transfer_wizard_output_dialog_directory_message); dialog.setText(CoreMessages.data_transfer_wizard_output_dialog_directory_text); String directory = directoryText.getText(); if (!CommonUtils.isEmpty(directory)) { dialog.setFilterPath(directory); } directory = dialog.open(); if (directory != null) { directoryText.setText(directory); } } }; directoryText.addMouseListener( new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { folderChooser.run(); } }); Button openFolder = new Button(chooserPlaceholder, SWT.PUSH | SWT.FLAT); openFolder.setImage(DBeaverIcons.getImage(DBIcon.TREE_FOLDER)); openFolder.setLayoutData( new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_CENTER)); openFolder.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { folderChooser.run(); } }); return directoryText; } public static String makeAnchor(String text) { return "<a>" + text + "</a>"; // $NON-NLS-1$ //$NON-NLS-2$ } @Nullable public static <T> T findView(IWorkbenchWindow workbenchWindow, Class<T> viewClass) { IViewReference[] references = workbenchWindow.getActivePage().getViewReferences(); for (IViewReference ref : references) { IViewPart view = ref.getView(false); if (view != null && viewClass.isAssignableFrom(view.getClass())) { return viewClass.cast(view); } } return null; } @Nullable public static IViewPart findView(IWorkbenchWindow workbenchWindow, String viewId) { IViewReference[] references = workbenchWindow.getActivePage().getViewReferences(); for (IViewReference ref : references) { if (ref.getId().equals(viewId)) { return ref.getView(false); } } return null; } public static void setClipboardContents(Display display, Transfer transfer, Object contents) { Clipboard clipboard = new Clipboard(display); clipboard.setContents(new Object[] {contents}, new Transfer[] {transfer}); clipboard.dispose(); } public static void updateMainWindowTitle(IWorkbenchWindow window) { IProject activeProject = DBeaverCore.getInstance().getProjectRegistry().getActiveProject(); IProduct product = Platform.getProduct(); String title = product == null ? "Unknown" : product.getName(); // $NON-NLS-1$ if (activeProject != null) { title += " - " + activeProject.getName(); // $NON-NLS-1$ } IWorkbenchPage activePage = window.getActivePage(); if (activePage != null) { IEditorPart activeEditor = activePage.getActiveEditor(); if (activeEditor != null) { title += " - [ " + activeEditor.getTitle() + " ]"; } } window.getShell().setText(title); } public static void showPreferencesFor(Shell shell, Object element, String defPageID) { PreferenceDialog propDialog; if (element == null) { propDialog = PreferencesUtil.createPreferenceDialogOn( shell, defPageID, new String[] {defPageID}, null, PreferencesUtil.OPTION_NONE); } else { propDialog = PreferencesUtil.createPropertyDialogOn( shell, element, defPageID, null, null, PreferencesUtil.OPTION_NONE); } if (propDialog != null) { propDialog.open(); } } public static void addFocusTracker( IServiceLocator serviceLocator, String controlID, Control control) { final IFocusService focusService = serviceLocator.getService(IFocusService.class); if (focusService != null) { focusService.addFocusTracker(control, controlID); } else { log.debug("Focus service not found in " + serviceLocator); } } public static void removeFocusTracker(IServiceLocator serviceLocator, Control control) { if (PlatformUI.getWorkbench().isClosing()) { // TODO: it is a bug in eclipse. During workbench shutdown disposed service returned. return; } final IFocusService focusService = serviceLocator.getService(IFocusService.class); if (focusService != null) { focusService.removeFocusTracker(control); } else { log.debug("Focus service not found in " + serviceLocator); } } public static IDialogSettings getDialogSettings(String dialogId) { IDialogSettings workbenchSettings = DBeaverActivator.getInstance().getDialogSettings(); IDialogSettings section = workbenchSettings.getSection(dialogId); if (section == null) { section = workbenchSettings.addNewSection(dialogId); } return section; } @Nullable public static IWorkbenchPartSite getWorkbenchPartSite(IServiceLocator serviceLocator) { IWorkbenchPartSite partSite = serviceLocator.getService(IWorkbenchPartSite.class); if (partSite == null) { IWorkbenchPart activePart = serviceLocator.getService(IWorkbenchPart.class); if (activePart == null) { IWorkbenchWindow workbenchWindow = DBeaverUI.getActiveWorkbenchWindow(); if (workbenchWindow != null) { IWorkbenchPage activePage = workbenchWindow.getActivePage(); if (activePage != null) { activePart = activePage.getActivePart(); } } } if (activePart != null) { partSite = activePart.getSite(); } } return partSite; } public static boolean isContextActive(String contextId) { Collection<?> contextIds = PlatformUI.getWorkbench() .getActiveWorkbenchWindow() .getService(IContextService.class) .getActiveContextIds(); for (Object id : contextIds) { if (contextId.equals(id)) { return true; } } return false; } @Nullable public static ISelectionProvider getSelectionProvider(IServiceLocator serviceLocator) { ISelectionProvider selectionProvider = serviceLocator.getService(ISelectionProvider.class); if (selectionProvider != null) { return selectionProvider; } IWorkbenchPartSite partSite = getWorkbenchPartSite(serviceLocator); if (partSite == null) { IWorkbenchPart activePart = serviceLocator.getService(IWorkbenchPart.class); if (activePart == null) { IWorkbenchWindow activeWindow = DBeaverUI.getActiveWorkbenchWindow(); if (activeWindow != null) { activePart = activeWindow.getActivePage().getActivePart(); } } if (activePart != null) { partSite = activePart.getSite(); } } if (partSite != null) { return partSite.getSelectionProvider(); } else { return null; } } public static void enableWithChildren(Composite composite, boolean enable) { composite.setEnabled(enable); for (Control child : composite.getChildren()) { if (child instanceof Composite) { enableWithChildren((Composite) child, enable); } else { child.setEnabled(enable); } } } /** * Determine whether this control or any of it's child has focus * * @param control control to check * @return true if it has focus */ public static boolean hasFocus(Control control) { Control focusControl = control.getDisplay().getFocusControl(); if (focusControl == null) { return false; } for (Control fc = focusControl; fc != null; fc = fc.getParent()) { if (fc == control) { return true; } } return false; } /** * Eclipse hack. Disables/enabled all key bindings in specified site's part. Works only if host * editor is extender of AbstractTextEditor Uses reflection because setActionActivation is private * method TODO: find better way to disable key bindings or prioritize event handling to widgets * * @param partSite workbench part site * @param enable enable or disable */ @Deprecated public static void enableHostEditorKeyBindings(IWorkbenchPartSite partSite, boolean enable) { IWorkbenchPart part = partSite.getPart(); if (part instanceof AbstractTextEditor) { AbstractTextEditor hostEditor = (AbstractTextEditor) part; if (hostEditor instanceof BaseTextEditor) { StyledText textWidget = ((BaseTextEditor) hostEditor).getTextViewer().getTextWidget(); if (textWidget == null || textWidget.isDisposed()) { return; } } try { Method activatorMethod = AbstractTextEditor.class.getDeclaredMethod("setActionActivation", Boolean.TYPE); activatorMethod.setAccessible(true); activatorMethod.invoke(hostEditor, enable); } catch (Throwable e) { if (e instanceof InvocationTargetException) { e = ((InvocationTargetException) e).getTargetException(); } log.warn("Can't disable text editor action activations", e); } // hostEditor.getEditorSite().getActionBarContributor().setActiveEditor(hostEditor); } } public static void enableHostEditorKeyBindingsSupport( final IWorkbenchPartSite partSite, Control control) { if (!(partSite.getPart() instanceof AbstractTextEditor)) { return; } final boolean[] activated = new boolean[] {false}; control.addFocusListener( new FocusListener() { @Override public void focusGained(FocusEvent e) { if (!activated[0]) { UIUtils.enableHostEditorKeyBindings(partSite, false); activated[0] = true; } } @Override public void focusLost(FocusEvent e) { if (activated[0]) { UIUtils.enableHostEditorKeyBindings(partSite, true); activated[0] = false; } } }); control.addDisposeListener( new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { if (activated[0]) { UIUtils.enableHostEditorKeyBindings(partSite, true); activated[0] = false; } } }); } public static CTabItem getTabItem(CTabFolder tabFolder, Object data) { for (CTabItem item : tabFolder.getItems()) { if (item.getData() == data) { return item; } } return null; } public static TreeItem getTreeItem(Tree tree, Object data) { for (TreeItem item : tree.getItems()) { if (item.getData() == data) { return item; } } return null; } public static int blend(int v1, int v2, int ratio) { return (ratio * v1 + (100 - ratio) * v2) / 100; } public static RGB blend(RGB c1, RGB c2, int ratio) { int r = blend(c1.red, c2.red, ratio); int g = blend(c1.green, c2.green, ratio); int b = blend(c1.blue, c2.blue, ratio); return new RGB(r, g, b); } public static boolean isParent(Control parent, Control child) { for (Control c = child; c != null; c = c.getParent()) { if (c == parent) { return true; } } return false; } public static boolean isInDialog(Control control) { return control.getShell().getData() instanceof org.eclipse.jface.dialogs.Dialog; } public static boolean validateAndSave(DBRProgressMonitor monitor, ISaveablePart saveable) { if (!saveable.isDirty()) { return true; } SaveRunner saveRunner = new SaveRunner(monitor, saveable); runInUI(null, saveRunner); return saveRunner.getResult(); } public static Link createLink(Composite parent, String text, SelectionListener listener) { Link link = new Link(parent, SWT.NONE); link.setText(text); link.addSelectionListener(listener); return link; } public static CellEditor createPropertyEditor( final IServiceLocator serviceLocator, Composite parent, DBPPropertySource source, DBPPropertyDescriptor property) { if (source == null) { return null; } final Object object = source.getEditableValue(); if (!property.isEditable(object)) { return null; } CellEditor cellEditor = UIUtils.createCellEditor(parent, object, property); if (cellEditor != null) { final Control editorControl = cellEditor.getControl(); UIUtils.addFocusTracker(serviceLocator, UIUtils.INLINE_WIDGET_EDITOR_ID, editorControl); editorControl.addDisposeListener( new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { UIUtils.removeFocusTracker(serviceLocator, editorControl); } }); } return cellEditor; } public static CellEditor createCellEditor( Composite parent, Object object, DBPPropertyDescriptor property) { // List if (property instanceof IPropertyValueListProvider) { final IPropertyValueListProvider listProvider = (IPropertyValueListProvider) property; final Object[] items = listProvider.getPossibleValues(object); if (!ArrayUtils.isEmpty(items)) { final String[] strings = new String[items.length]; for (int i = 0, itemsLength = items.length; i < itemsLength; i++) { strings[i] = items[i] instanceof DBPNamedObject ? ((DBPNamedObject) items[i]).getName() : CommonUtils.toString(items[i]); } final CustomComboBoxCellEditor editor = new CustomComboBoxCellEditor( parent, strings, SWT.DROP_DOWN | (listProvider.allowCustomValue() ? SWT.NONE : SWT.READ_ONLY)); return editor; } } Class<?> propertyType = property.getDataType(); if (propertyType == null || CharSequence.class.isAssignableFrom(propertyType)) { return new CustomTextCellEditor(parent); } else if (BeanUtils.isNumericType(propertyType)) { return new CustomNumberCellEditor(parent, propertyType); } else if (BeanUtils.isBooleanType(propertyType)) { return new CustomCheckboxCellEditor(parent); // return new CheckboxCellEditor(parent); } else if (propertyType.isEnum()) { final Object[] enumConstants = propertyType.getEnumConstants(); final String[] strings = new String[enumConstants.length]; for (int i = 0, itemsLength = enumConstants.length; i < itemsLength; i++) { strings[i] = ((Enum) enumConstants[i]).name(); } return new CustomComboBoxCellEditor(parent, strings, SWT.DROP_DOWN | SWT.READ_ONLY); } else { log.warn("Unsupported property type: " + propertyType.getName()); return null; } } public static boolean showDatabaseError( Shell shell, String title, String message, DBException error) { DBPDataSource dataSource = error.getDataSource(); DBPErrorAssistant errorAssistant = DBUtils.getAdapter(DBPErrorAssistant.class, dataSource); if (errorAssistant != null) { DBPErrorAssistant.ErrorType errorType = ((DBPErrorAssistant) dataSource).discoverErrorType(error); switch (errorType) { case CONNECTION_LOST: DataSourceInvalidateHandler.showConnectionLostDialog(shell, message, error); return true; case DRIVER_CLASS_MISSING: DriverEditDialog.showBadConfigDialog(shell, message, error); return true; } } return false; } public static void postEvent(Control ownerControl, final Event event) { final Display display = ownerControl.getDisplay(); display.asyncExec( new Runnable() { @Override public void run() { display.post(event); } }); } public static void drawMessageOverControl( Control control, PaintEvent e, String message, int offset) { Rectangle bounds = control.getBounds(); Point ext = e.gc.textExtent(message); e.gc.drawText(message, (bounds.width - ext.x) / 2, bounds.height / 3 + offset); } private static class SaveRunner implements Runnable { private final DBRProgressMonitor monitor; private final ISaveablePart saveable; private boolean result; private SaveRunner(DBRProgressMonitor monitor, ISaveablePart saveable) { this.monitor = monitor; this.saveable = saveable; } public boolean getResult() { return result; } @Override public void run() { int choice = -1; if (saveable instanceof ISaveablePart2) { choice = ((ISaveablePart2) saveable).promptToSaveOnClose(); } if (choice == -1 || choice == ISaveablePart2.DEFAULT) { Shell shell; String saveableName; if (saveable instanceof IWorkbenchPart) { shell = ((IWorkbenchPart) saveable).getSite().getShell(); saveableName = ((IWorkbenchPart) saveable).getTitle(); } else { shell = DBeaverUI.getActiveWorkbenchShell(); saveableName = CommonUtils.toString(saveable); } int confirmResult = ConfirmationDialog.showConfirmDialog( shell, DBeaverPreferences.CONFIRM_EDITOR_CLOSE, ConfirmationDialog.QUESTION_WITH_CANCEL, saveableName); switch (confirmResult) { case IDialogConstants.YES_ID: choice = ISaveablePart2.YES; break; case IDialogConstants.NO_ID: choice = ISaveablePart2.NO; break; default: choice = ISaveablePart2.CANCEL; break; } } switch (choice) { case ISaveablePart2.YES: // yes saveable.doSave(monitor.getNestedMonitor()); result = !saveable.isDirty(); break; case ISaveablePart2.NO: // no result = true; break; case ISaveablePart2.CANCEL: // cancel default: result = false; break; } } } public static Color getConnectionColor(DBPConnectionConfiguration connectionInfo) { String rgbString = connectionInfo.getConnectionColor(); if (CommonUtils.isEmpty(rgbString)) { rgbString = connectionInfo.getConnectionType().getColor(); } if (CommonUtils.isEmpty(rgbString)) { return null; } Color connectionColor = DBeaverUI.getSharedTextColors().getColor(StringConverter.asRGB(rgbString)); if (connectionColor.getBlue() == 255 && connectionColor.getRed() == 255 && connectionColor.getGreen() == 255) { // For white color return just null to avoid explicit color set. // It is important for dark themes return null; } return connectionColor; } public static Color getConnectionTypeColor(DBPConnectionType connectionType) { String rgbString = connectionType.getColor(); if (CommonUtils.isEmpty(rgbString)) { return null; } return DBeaverUI.getSharedTextColors().getColor(StringConverter.asRGB(rgbString)); } }
/** CONTENT text editor */ public class ImageEditorPart extends EditorPart implements IResourceChangeListener { private static final Log log = Log.getLog(ImageEditorPart.class); private ImageEditor imageViewer; private boolean contentValid; @Override public void doSave(IProgressMonitor monitor) {} @Override public void doSaveAs() {} @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); ResourcesPlugin.getWorkspace().addResourceChangeListener(this); } @Override public void dispose() { ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); super.dispose(); } @Override public boolean isDirty() { return false; } @Override public boolean isSaveAsAllowed() { return false; } @Override public void createPartControl(Composite parent) { imageViewer = new ImageEditor(parent, SWT.NONE); loadImage(); } private void loadImage() { if (imageViewer == null || imageViewer.isDisposed()) { return; } if (getEditorInput() instanceof IPathEditorInput) { try { final IPath absolutePath = ((IPathEditorInput) getEditorInput()).getPath(); File localFile = absolutePath.toFile(); if (localFile.exists()) { try (InputStream inputStream = new FileInputStream(localFile)) { contentValid = imageViewer.loadImage(inputStream); imageViewer.update(); } } } catch (Exception e) { log.error("Can't load image contents", e); } } } @Override public void setFocus() { imageViewer.setFocus(); } @Override public String getTitle() { return "Image"; } @Override public Image getTitleImage() { return DBeaverIcons.getImage(DBIcon.TYPE_IMAGE); } @Override public void resourceChanged(IResourceChangeEvent event) { IResourceDelta delta = event.getDelta(); if (delta == null) { return; } IEditorInput input = getEditorInput(); IPath localPath = null; if (input instanceof IPathEditorInput) { localPath = ((IPathEditorInput) input).getPath(); } if (localPath == null) { return; } localPath = ContentUtils.convertPathToWorkspacePath(localPath); delta = delta.findMember(localPath); if (delta == null) { return; } if (delta.getKind() == IResourceDelta.CHANGED) { // Refresh editor DBeaverUI.asyncExec( new Runnable() { @Override public void run() { loadImage(); } }); } } }
/** ResultSetPresentationDescriptor */ public class ResultSetPresentationDescriptor extends AbstractContextDescriptor { private static final Log log = Log.getLog(ResultSetPresentationDescriptor.class); public static final String EXTENSION_ID = "org.jkiss.dbeaver.resultset.presentation"; // NON-NLS-1 //$NON-NLS-1$ private static final String CONTENT_TYPE = "contentType"; private final String id; private final String label; private final String description; private final ObjectType presentationType; private final DBPImage icon; private final int order; private final List<MimeType> contentTypes = new ArrayList<>(); protected ResultSetPresentationDescriptor(IConfigurationElement config) { super(config); this.id = config.getAttribute(RegistryConstants.ATTR_ID); this.label = config.getAttribute(RegistryConstants.ATTR_LABEL); this.description = config.getAttribute(RegistryConstants.ATTR_DESCRIPTION); this.presentationType = new ObjectType(config.getAttribute(RegistryConstants.ATTR_CLASS)); this.icon = iconToImage(config.getAttribute(RegistryConstants.ATTR_ICON)); this.order = CommonUtils.toInt(config.getAttribute(RegistryConstants.ATTR_ORDER)); for (IConfigurationElement typeCfg : config.getChildren(CONTENT_TYPE)) { String type = typeCfg.getAttribute(RegistryConstants.ATTR_TYPE); try { MimeType contentType = new MimeType(type); contentTypes.add(contentType); } catch (MimeTypeParseException e) { log.warn("Invalid content type: " + type, e); } } } public String getId() { return id; } public String getLabel() { return label; } public String getDescription() { return description; } public DBPImage getIcon() { return icon; } public int getOrder() { return order; } public boolean supportedBy(DBCResultSet resultSet, IResultSetContext context) { return appliesTo(resultSet, context) || matchesContentType(context); } public IResultSetPresentation createInstance() throws DBException { return presentationType.createInstance(IResultSetPresentation.class); } public boolean matches(Class<? extends IResultSetPresentation> type) { return presentationType.matchesType(type); } private boolean matchesContentType(IResultSetContext context) { String documentType = context.getDocumentContentType(); if (contentTypes.isEmpty() || CommonUtils.isEmpty(documentType)) { return false; } for (MimeType mimeType : contentTypes) { try { if (mimeType.match(documentType)) { return true; } } catch (MimeTypeParseException e) { log.warn("Bad document content type: " + documentType, e); } } return false; } }
/** * JDBC Content value handler. Handle LOBs, LONGs and BINARY types. * * @author Serge Rider */ public class ContentValueManager extends BaseValueManager { static final Log log = Log.getLog(ContentValueManager.class); public static final String PROP_CATEGORY_CONTENT = "CONTENT"; public static void contributeContentActions( @NotNull IContributionManager manager, @NotNull final IValueController controller) throws DBCException { if (controller.getValue() instanceof DBDContent && !((DBDContent) controller.getValue()).isNull()) { manager.add( new Action( CoreMessages.model_jdbc_save_to_file_, DBeaverIcons.getImageDescriptor(UIIcon.SAVE_AS)) { @Override public void run() { DialogUtils.saveToFile(controller); } }); } manager.add( new Action( CoreMessages.model_jdbc_load_from_file_, DBeaverIcons.getImageDescriptor(UIIcon.LOAD)) { @Override public void run() { DialogUtils.loadFromFile(controller); } }); } public static IValueEditor openContentEditor(@NotNull IValueController controller) { Object value = controller.getValue(); IValueController.EditType binaryEditType = IValueController.EditType.valueOf( controller .getExecutionContext() .getDataSource() .getContainer() .getPreferenceStore() .getString(DBeaverPreferences.RESULT_SET_BINARY_EDITOR_TYPE)); if (binaryEditType != IValueController.EditType.EDITOR && value instanceof DBDContentCached) { // Use string editor for cached content return new TextViewDialog(controller); } else if (value instanceof DBDContent) { DBDContent content = (DBDContent) value; boolean isText = ContentUtils.isTextContent(content); List<ContentEditorPart> parts = new ArrayList<>(); if (isText) { parts.add(new ContentTextEditorPart()); if (ContentUtils.isXML(content)) { parts.add(new ContentXMLEditorPart()); } } else { parts.add(new ContentBinaryEditorPart()); parts.add(new ContentTextEditorPart()); parts.add(new ContentImageEditorPart()); } return ContentEditor.openEditor( controller, parts.toArray(new ContentEditorPart[parts.size()])); } else { controller.showMessage(CoreMessages.model_jdbc_unsupported_content_value_type_, true); return null; } } @Override public void contributeActions( @NotNull IContributionManager manager, @NotNull final IValueController controller) throws DBCException { contributeContentActions(manager, controller); } @Override public void contributeProperties( @NotNull DBPPropertyManager propertySource, @NotNull IValueController controller) { super.contributeProperties(propertySource, controller); try { Object value = controller.getValue(); if (value instanceof DBDContent) { propertySource.addProperty( PROP_CATEGORY_CONTENT, "content_type", //$NON-NLS-1$ CoreMessages.model_jdbc_content_type, ((DBDContent) value).getContentType()); final long contentLength = ((DBDContent) value).getContentLength(); if (contentLength >= 0) { propertySource.addProperty( PROP_CATEGORY_CONTENT, "content_length", //$NON-NLS-1$ CoreMessages.model_jdbc_content_length, contentLength); } } } catch (Exception e) { log.warn("Can't extract CONTENT value information", e); // $NON-NLS-1$ } } @NotNull @Override public IValueController.EditType[] getSupportedEditTypes() { return new IValueController.EditType[] { IValueController.EditType.PANEL, IValueController.EditType.EDITOR }; } @Override public IValueEditor createEditor(@NotNull final IValueController controller) throws DBException { switch (controller.getEditType()) { case INLINE: // Open inline/panel editor if (controller.getValue() instanceof DBDContentCached) { return new ContentInlineEditor(controller); } else { return null; } case EDITOR: return openContentEditor(controller); case PANEL: Object value = controller.getValue(); if (value instanceof DBDContent && ContentUtils.isXML((DBDContent) value)) { return new XMLPanelEditor(controller); } else { return new ContentPanelEditor(controller); } default: return null; } } }
/** FileRefDocumentProvider */ public class FileRefDocumentProvider extends BaseTextDocumentProvider { private static final Log log = Log.getLog(FileRefDocumentProvider.class); private static final int DEFAULT_BUFFER_SIZE = 10000; public FileRefDocumentProvider() {} protected IEditorInput createNewEditorInput(IFile newFile) { return new ProjectFileEditorInput(newFile); } @Override protected Document createDocument(Object element) throws CoreException { Document document = createEmptyDocument(); IStorage storage = EditorUtils.getStorageFromInput(element); if (storage != null) { if (setDocumentContent(document, storage)) { setupDocument(document); return document; } } File file = EditorUtils.getLocalFileFromInput(element); if (file != null) { try (InputStream stream = new FileInputStream(file)) { setDocumentContent(document, stream, null); setupDocument(document); return document; } catch (IOException e) { throw new CoreException(GeneralUtils.makeExceptionStatus(e)); } } throw new IllegalArgumentException( "Project document provider supports only editor inputs which provides IStorage facility"); } protected void setupDocument(IDocument document) {} @Override public boolean isReadOnly(Object element) { IStorage storage = EditorUtils.getStorageFromInput(element); if (storage != null) { return storage.isReadOnly(); } File file = EditorUtils.getLocalFileFromInput(element); if (file != null) { return !file.isFile(); } return super.isReadOnly(element); } @Override public boolean isModifiable(Object element) { return !isReadOnly(element); } @Override public boolean isDeleted(Object element) { IStorage storage = EditorUtils.getStorageFromInput(element); if (storage instanceof IResource) { return !((IResource) storage).exists(); } File file = EditorUtils.getLocalFileFromInput(element); if (file != null) { return !file.exists(); } return super.isDeleted(element); } @Override protected void doSaveDocument( IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException { try { IStorage storage = EditorUtils.getStorageFromInput(element); File localFile = null; if (storage == null) { localFile = EditorUtils.getLocalFileFromInput(element); if (localFile == null) { throw new DBException("Can't obtain file from editor input"); } } String encoding = (storage instanceof IEncodedStorage ? ((IEncodedStorage) storage).getCharset() : GeneralUtils.DEFAULT_FILE_CHARSET_NAME); Charset charset = Charset.forName(encoding); CharsetEncoder encoder = charset.newEncoder(); encoder.onMalformedInput(CodingErrorAction.REPLACE); encoder.onUnmappableCharacter(CodingErrorAction.REPORT); byte[] bytes; ByteBuffer byteBuffer = encoder.encode(CharBuffer.wrap(document.get())); if (byteBuffer.hasArray()) { bytes = byteBuffer.array(); } else { bytes = new byte[byteBuffer.limit()]; byteBuffer.get(bytes); } InputStream stream = new ByteArrayInputStream(bytes, 0, byteBuffer.limit()); if (storage instanceof IFile) { IFile file = (IFile) storage; if (file.exists()) { // inform about the upcoming content change fireElementStateChanging(element); try { file.setContents(stream, true, true, monitor); } catch (CoreException x) { // inform about failure fireElementStateChangeFailed(element); throw x; } catch (RuntimeException x) { // inform about failure fireElementStateChangeFailed(element); throw x; } } else { try { monitor.beginTask("Save file '" + file.getName() + "'", 2000); // ContainerCreator creator = new ContainerCreator(file.getWorkspace(), // file.getParent().getFullPath()); // creator.createContainer(new SubProgressMonitor(monitor, 1000)); file.create(stream, false, monitor); } finally { monitor.done(); } } } else if (storage instanceof IPersistentStorage) { monitor.beginTask("Save document", 1); ((IPersistentStorage) storage).setContents(monitor, stream); } else if (localFile != null) { try (OutputStream os = new FileOutputStream(localFile)) { IOUtils.copyStream(stream, os); } } else { throw new DBException("Storage [" + storage + "] doesn't support save"); } } catch (Exception e) { if (e instanceof CoreException) { throw (CoreException) e; } else { throw new CoreException(GeneralUtils.makeExceptionStatus(e)); } } } protected boolean setDocumentContent(IDocument document, IStorage storage) throws CoreException { try { InputStream contentStream = storage.getContents(); try { String encoding = (storage instanceof IEncodedStorage ? ((IEncodedStorage) storage).getCharset() : GeneralUtils.getDefaultFileEncoding()); setDocumentContent(document, contentStream, encoding); } finally { ContentUtils.close(contentStream); } } catch (IOException e) { throw new CoreException(GeneralUtils.makeExceptionStatus(e)); } return true; } protected void setDocumentContent(IDocument document, InputStream contentStream, String encoding) throws IOException { Reader in = null; try { if (encoding == null) { encoding = GeneralUtils.DEFAULT_FILE_CHARSET_NAME; } in = new BufferedReader(new InputStreamReader(contentStream, encoding), DEFAULT_BUFFER_SIZE); StringBuilder buffer = new StringBuilder(DEFAULT_BUFFER_SIZE); char[] readBuffer = new char[2048]; int n = in.read(readBuffer); while (n > 0) { buffer.append(readBuffer, 0, n); n = in.read(readBuffer); } document.set(buffer.toString()); } finally { if (in != null) { ContentUtils.close(in); } else { ContentUtils.close(contentStream); } } } protected long computeModificationStamp(IResource resource) { long modificationStamp = resource.getModificationStamp(); IPath path = resource.getLocation(); if (path == null) { return modificationStamp; } modificationStamp = path.toFile().lastModified(); return modificationStamp; } protected void refreshFile(IFile file) throws CoreException { refreshFile(file, getProgressMonitor()); } @Override protected ElementInfo createElementInfo(Object element) throws CoreException { if (element instanceof IEditorInput) { IEditorInput input = (IEditorInput) element; IStorage storage = EditorUtils.getStorageFromInput(input); if (storage instanceof IFile) { IFile file = (IFile) storage; try { refreshFile(file); } catch (CoreException x) { log.warn("Can't refresh file", x); } IDocument d; IStatus s = null; try { d = createDocument(element); } catch (CoreException x) { log.warn("Can't create document", x); s = x.getStatus(); d = createEmptyDocument(); } // Set the initial line delimiter String initialLineDelimiter = GeneralUtils.getDefaultLineSeparator(); if (initialLineDelimiter != null) { ((IDocumentExtension4) d).setInitialLineDelimiter(initialLineDelimiter); } IAnnotationModel m = createAnnotationModel(element); FileSynchronizer f = new FileSynchronizer(input); f.install(); FileInfo info = new FileInfo(d, m, f); info.modificationStamp = computeModificationStamp(file); info.fStatus = s; return info; } } return super.createElementInfo(element); } @Override protected void disposeElementInfo(Object element, ElementInfo info) { if (info instanceof FileInfo) { FileInfo fileInfo = (FileInfo) info; if (fileInfo.fileSynchronizer != null) { fileInfo.fileSynchronizer.uninstall(); } } super.disposeElementInfo(element, info); } protected void refreshFile(IFile file, IProgressMonitor monitor) throws CoreException { if (file != null) { try { file.refreshLocal(IResource.DEPTH_INFINITE, monitor); } catch (OperationCanceledException x) { // do nothing } } } /** * Updates the element info to a change of the file content and sends out appropriate * notifications. * * @param fileEditorInput the input of an text editor */ protected void handleElementContentChanged(IEditorInput fileEditorInput) { FileInfo info = (FileInfo) getElementInfo(fileEditorInput); if (info == null) { return; } IStorage storage = EditorUtils.getStorageFromInput(fileEditorInput); if (storage instanceof IFile) { IFile file = (IFile) storage; IDocument document = createEmptyDocument(); IStatus status = null; try { try { refreshFile(file); } catch (CoreException x) { log.error("handleElementContentChanged", x); } setDocumentContent(document, file); } catch (CoreException x) { status = x.getStatus(); } String newContent = document.get(); if (!newContent.equals(info.fDocument.get())) { // set the new content and fire content related events fireElementContentAboutToBeReplaced(fileEditorInput); removeUnchangedElementListeners(fileEditorInput, info); info.fDocument.removeDocumentListener(info); info.fDocument.set(newContent); info.fCanBeSaved = false; info.modificationStamp = computeModificationStamp(file); info.fStatus = status; addUnchangedElementListeners(fileEditorInput, info); fireElementContentReplaced(fileEditorInput); } else { removeUnchangedElementListeners(fileEditorInput, info); // fires only the dirty state related event info.fCanBeSaved = false; info.modificationStamp = computeModificationStamp(file); info.fStatus = status; addUnchangedElementListeners(fileEditorInput, info); fireElementDirtyStateChanged(fileEditorInput, false); } } } /** * Sends out the notification that the file serving as document input has been moved. * * @param fileEditorInput the input of an text editor * @param path the path of the new location of the file */ protected void handleElementMoved(IEditorInput fileEditorInput, IPath path) { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IFile newFile = workspace.getRoot().getFile(path); fireElementMoved(fileEditorInput, createNewEditorInput(newFile)); } /** * Sends out the notification that the file serving as document input has been deleted. * * @param fileEditorInput the input of an text editor */ protected void handleElementDeleted(IEditorInput fileEditorInput) { fireElementDeleted(fileEditorInput); } protected abstract class SafeChange implements Runnable { private IEditorInput editorInput; public SafeChange(IEditorInput input) { editorInput = input; } protected abstract void execute(IEditorInput input) throws Exception; @Override public void run() { if (getElementInfo(editorInput) == null) { fireElementStateChangeFailed(editorInput); return; } try { execute(editorInput); } catch (Exception e) { fireElementStateChangeFailed(editorInput); } } } /** Synchronizes the document with external resource changes. */ protected class FileSynchronizer implements IResourceChangeListener, IResourceDeltaVisitor { protected IEditorInput fileEditorInput; protected boolean isInstalled = false; /** * Creates a new file synchronizer. Is not yet installed on a resource. * * @param fileEditorInput the editor input to be synchronized */ public FileSynchronizer(IEditorInput fileEditorInput) { this.fileEditorInput = fileEditorInput; } /** * Returns the file wrapped by the file editor input. * * @return the file wrapped by the editor input associated with that synchronizer */ protected IFile getFile() { IStorage storage = EditorUtils.getStorageFromInput(fileEditorInput); return storage instanceof IFile ? (IFile) storage : null; } /** Installs the synchronizer on the input's file. */ public void install() { getFile().getWorkspace().addResourceChangeListener(this); isInstalled = true; } /** Uninstalls the synchronizer from the input's file. */ public void uninstall() { getFile().getWorkspace().removeResourceChangeListener(this); isInstalled = false; } @Override public void resourceChanged(IResourceChangeEvent e) { IResourceDelta delta = e.getDelta(); try { if (delta != null && isInstalled) { delta.accept(this); } } catch (CoreException x) { log.warn("Error handling resourceChanged", x); } } @Override public boolean visit(IResourceDelta delta) throws CoreException { if (delta == null) { return false; } IFile file = getFile(); if (file == null) { return false; } delta = delta.findMember(file.getFullPath()); if (delta == null) { return false; } Runnable runnable = null; switch (delta.getKind()) { case IResourceDelta.CHANGED: FileInfo info = (FileInfo) getElementInfo(fileEditorInput); if (info == null || !canRefreshFromFile(info)) { break; } boolean isSynchronized = computeModificationStamp(file) == info.modificationStamp; if ((IResourceDelta.ENCODING & delta.getFlags()) != 0 && isSynchronized) { runnable = new SafeChange(fileEditorInput) { @Override protected void execute(IEditorInput input) throws Exception { handleElementContentChanged(input); } }; } if (runnable == null && (IResourceDelta.CONTENT & delta.getFlags()) != 0 && !isSynchronized) { runnable = new SafeChange(fileEditorInput) { @Override protected void execute(IEditorInput input) throws Exception { handleElementContentChanged(input); } }; } break; case IResourceDelta.REMOVED: if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) { final IPath path = delta.getMovedToPath(); runnable = new SafeChange(fileEditorInput) { @Override protected void execute(IEditorInput input) throws Exception { handleElementMoved(input, path); } }; } else { info = (FileInfo) getElementInfo(fileEditorInput); if (info != null && canRefreshFromFile(info)) { runnable = new SafeChange(fileEditorInput) { @Override protected void execute(IEditorInput input) throws Exception { handleElementDeleted(input); } }; } } break; } if (runnable != null) { update(runnable); } return false; } private boolean canRefreshFromFile(FileInfo info) { // return !info.fCanBeSaved; return true; } /** * Posts the update code "behind" the running operation. * * @param runnable the update code */ protected void update(Runnable runnable) { if (runnable instanceof SafeChange) { fireElementStateChanging(fileEditorInput); } IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow[] windows = workbench.getWorkbenchWindows(); if (windows != null && windows.length > 0) { Display display = windows[0].getShell().getDisplay(); display.asyncExec(runnable); } else { runnable.run(); } } } /** Bundle of all required information to allow files as underlying document resources. */ protected class FileInfo extends ElementInfo { /** The file synchronizer. */ public FileSynchronizer fileSynchronizer; /** The time stamp at which this provider changed the file. */ public long modificationStamp = IResource.NULL_STAMP; public FileInfo(IDocument document, IAnnotationModel model, FileSynchronizer fileSynchronizer) { super(document, model); this.fileSynchronizer = fileSynchronizer; } } }
/** * Holds and cache current user privileges and authorities * * @author Denis Forveille */ public class DB2CurrentUserPrivileges { private static final Log LOG = Log.getLog(DB2CurrentUserPrivileges.class); private static final String SYSMON = "SYSMON"; private static final String SYSMAINT = "SYSMAINT"; private static final String SYSADM = "SYSADM"; private static final String SYSCTRL = "SYSCTRL"; private static final String DATAACCESS = "DATAACCESS"; private static final String DBADM = "DBADM"; private static final String SQLADM = "SQLADM"; private static final String AUTH_APP = "T:SYSIBMADM.APPLICATIONS"; private static final String AUTH_DBCFG = "T:SYSIBMADM.DBCFG"; private static final String AUTH_CONTAINER = "R:SYSPROC.SNAP_GET_CONTAINER"; private static final String SEL_AUTHORITIES; static { StringBuilder sb = new StringBuilder(256); sb.append("SELECT AUTHORITY"); sb.append(" FROM TABLE (SYSPROC.AUTH_LIST_AUTHORITIES_FOR_AUTHID (?, 'U')) AS T "); sb.append(" WHERE 'Y' IN (D_USER,D_GROUP,D_PUBLIC,ROLE_USER,ROLE_GROUP,ROLE_PUBLIC,D_ROLE)"); sb.append(" WITH UR"); SEL_AUTHORITIES = sb.toString(); } private static final String SEL_OBJECTS; static { StringBuilder sb = new StringBuilder(512); sb.append("SELECT 'R:' || TRIM(SCHEMA) || '.' || SPECIFICNAME"); sb.append(" FROM SYSCAT.ROUTINEAUTH"); sb.append( " WHERE ((GRANTEETYPE = 'G' AND GRANTEE = 'PUBLIC') OR (GRANTEETYPE = 'U' AND GRANTEE = ?)) "); sb.append( " AND (SCHEMA = 'SYSPROC' AND SPECIFICNAME = 'SNAP_GET_CONTAINER' AND EXECUTEAUTH IN ('Y','G'))"); sb.append(" UNION ALL "); sb.append("SELECT DISTINCT 'T:' || TRIM(TABSCHEMA) || '.' ||TABNAME"); sb.append(" FROM SYSCAT.TABAUTH"); sb.append( " WHERE ((GRANTEETYPE = 'G' AND GRANTEE = 'PUBLIC') OR (GRANTEETYPE = 'U' AND GRANTEE = ?))"); sb.append(" AND ("); sb.append( " (TABSCHEMA = 'SYSIBMADM' AND TABNAME = 'APPLICATIONS' AND 'Y' IN (CONTROLAUTH,SELECTAUTH))"); sb.append( " OR (TABSCHEMA = 'SYSIBMADM' AND TABNAME = 'DBCFG' AND 'Y' IN (CONTROLAUTH,SELECTAUTH))"); sb.append(" )"); sb.append(" WITH UR"); SEL_OBJECTS = sb.toString(); } private final List<String> listAuthorities; private final List<String> listObjectPrivileges; private final Boolean userIsAuthorisedForApplications; private final Boolean userIsAuthorisedForContainers; private final Boolean userIsAuthorisedForDBCFG; private final Boolean userIsAuthorisedForAdminister; // ------------------------ // Constructors // ------------------------ public DB2CurrentUserPrivileges( DBRProgressMonitor monitor, JDBCSession session, String currentAuthId, DB2DataSource db2DataSource) throws SQLException { // DF: There is no easy way to get this information from DB2 v9.1 // WE consider the user has no system authorities listAuthorities = new ArrayList<>(); if (db2DataSource.isAtLeastV9_5()) { try (JDBCPreparedStatement dbStat = session.prepareStatement(SEL_AUTHORITIES)) { dbStat.setString(1, currentAuthId); try (JDBCResultSet dbResult = dbStat.executeQuery()) { while (dbResult.next()) { listAuthorities.add(dbResult.getString(1)); } } } } listObjectPrivileges = new ArrayList<>(); try (JDBCPreparedStatement dbStat = session.prepareStatement(SEL_OBJECTS)) { dbStat.setString(1, currentAuthId); dbStat.setString(2, currentAuthId); try (JDBCResultSet dbResult = dbStat.executeQuery()) { while (dbResult.next()) { listObjectPrivileges.add(dbResult.getString(1)); } } } // Cache Authorities userIsAuthorisedForApplications = computeUserIsAuthorisedForApplications(); userIsAuthorisedForDBCFG = computeUserIsAuthorisedForDBCFG(); userIsAuthorisedForAdminister = userIsAuthorisedForApplications || userIsAuthorisedForDBCFG; userIsAuthorisedForContainers = computeUserIsAuthorisedForContainers(); } // ------------------------ // Standard Getters // ------------------------ public Boolean userIsAuthorisedForApplications() { return userIsAuthorisedForApplications; } public Boolean userIsAuthorisedForContainers() { return userIsAuthorisedForContainers; } public Boolean userIsAuthorisedForDBCFG() { return userIsAuthorisedForDBCFG; } public Boolean userIsAuthorisedForAdminister() { return userIsAuthorisedForAdminister; } // ------- // Helpers // ------- private Boolean computeUserIsAuthorisedForApplications() { // Must have one of SYSMON, SYSMAINT, SYSADM or SYSCTRL if ((listAuthorities.contains(SYSMON)) || (listAuthorities.contains(SYSMAINT)) || (listAuthorities.contains(SYSADM)) || (listAuthorities.contains(SYSCTRL))) { // Plus one of DATAACCESS or DBADM or SQLADM or SELECT on SYSIBMADM.APPLICATIONS or CONTROL on // SYSIBMADM.APPLICATIONS if ((listAuthorities.contains(DATAACCESS)) || (listAuthorities.contains(DBADM)) || (listAuthorities.contains(SQLADM))) { return true; } if (listObjectPrivileges.contains(AUTH_APP)) { return true; } } LOG.debug("Current User is not authorized to see Applications"); return false; } private Boolean computeUserIsAuthorisedForContainers() { // Must have one of SYSMON, SYSMAINT, SYSADM or SYSCTRL if ((listAuthorities.contains(SYSMON)) || (listAuthorities.contains(SYSMAINT)) || (listAuthorities.contains(SYSADM)) || (listAuthorities.contains(SYSCTRL))) { // Plus one of DATAACCESS or EXECUTE on SYSPROC.SNAP_GET_CONTAINER if (listAuthorities.contains(DATAACCESS)) { return true; } if (listObjectPrivileges.contains(AUTH_CONTAINER)) { return true; } } LOG.debug("Current User is not authorized to see Tablespaces Containers"); return false; } private Boolean computeUserIsAuthorisedForDBCFG() { // Must have one of DATAACCESS, DBADM, SQLADM or or SELECT on SYSIBMADM.APPLICATIONS or CONTROL // on SYSIBMADM.APPLICATIONS if ((listAuthorities.contains(DATAACCESS)) || (listAuthorities.contains(DBADM)) || (listAuthorities.contains(SQLADM))) { return true; } if (listObjectPrivileges.contains(AUTH_DBCFG)) { return true; } LOG.debug("Current User is not authorized to see DB/DBM Configuration Parameters"); return false; } }
/** * The SQL content assist processor. This content assist processor proposes text completions and * computes context information for a SQL content type. */ public class SQLCompletionProcessor implements IContentAssistProcessor { static final Log log = Log.getLog(SQLCompletionProcessor.class); private enum QueryType { TABLE, COLUMN } private SQLEditorBase editor; private IContextInformationValidator validator = new Validator(); private int documentOffset; private String activeQuery = null; private SQLWordPartDetector wordDetector; private static boolean lookupTemplates = false; public SQLCompletionProcessor(SQLEditorBase editor) { this.editor = editor; } public static boolean isLookupTemplates() { return lookupTemplates; } public static void setLookupTemplates(boolean lookupTemplates) { SQLCompletionProcessor.lookupTemplates = lookupTemplates; } /** * This method returns a list of completion proposals as ICompletionProposal objects. The * proposals are based on the word at the offset in the document where the cursor is positioned. * In this implementation, we find the word at the document offset and compare it to our list of * SQL reserved words. The list is a subset, of those words that match what the user has entered. * For example, the text or proposes the SQL keywords OR and ORDER. The list is returned as an * array of completion proposals. * * @see * org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(ITextViewer, * int) */ @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { this.documentOffset = documentOffset; this.activeQuery = null; this.wordDetector = new SQLWordPartDetector(viewer.getDocument(), editor.getSyntaxManager(), documentOffset); final String wordPart = wordDetector.getWordPart(); if (lookupTemplates) { return makeTemplateProposals(viewer, documentOffset, wordPart); } final List<SQLCompletionProposal> proposals = new ArrayList<>(); QueryType queryType = null; { final String prevKeyWord = wordDetector.getPrevKeyWord(); if (!CommonUtils.isEmpty(prevKeyWord)) { if (editor.getSyntaxManager().getDialect().isEntityQueryWord(prevKeyWord)) { queryType = QueryType.TABLE; } else if (editor.getSyntaxManager().getDialect().isAttributeQueryWord(prevKeyWord)) { queryType = QueryType.COLUMN; } } } if (queryType != null) { if (editor.getDataSource() != null) { try { final QueryType qt = queryType; DBeaverUI.runInProgressService( new DBRRunnableWithProgress() { @Override public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Seeking for completion proposals", 1); try { monitor.subTask("Make structure proposals"); makeStructureProposals(monitor, proposals, wordPart, qt); } finally { monitor.done(); } } }); } catch (InvocationTargetException e) { log.warn("Error while seeking for structure proposals", e.getTargetException()); } catch (InterruptedException e) { // interrupted - do nothing } } } if (proposals.isEmpty() || !wordPart.isEmpty()) { // Keyword assist List<String> matchedKeywords = editor.getSyntaxManager().getDialect().getMatchedKeywords(wordPart); for (String keyWord : matchedKeywords) { DBPKeywordType keywordType = editor.getSyntaxManager().getDialect().getKeywordType(keyWord); if (keywordType != null) { proposals.add( createCompletionProposal( keyWord, keyWord, keyWord + " (" + keywordType.name() + ")", null, false, null)); } } } // Remove duplications for (int i = 0; i < proposals.size(); i++) { SQLCompletionProposal proposal = proposals.get(i); for (int j = i + 1; j < proposals.size(); ) { SQLCompletionProposal proposal2 = proposals.get(j); if (proposal.getDisplayString().equals(proposal2.getDisplayString())) { proposals.remove(j); } else { j++; } } } DBSObject selectedObject = getSelectedObject(editor.getDataSource()); boolean hideDups = getPreferences().getBoolean(SQLPreferenceConstants.HIDE_DUPLICATE_PROPOSALS) && selectedObject != null; if (hideDups) { for (int i = 0; i < proposals.size(); i++) { SQLCompletionProposal proposal = proposals.get(i); for (int j = 0; j < proposals.size(); ) { SQLCompletionProposal proposal2 = proposals.get(j); if (i != j && proposal.hasStructObject() && proposal2.hasStructObject() && CommonUtils.equalObjects( proposal.getObject().getName(), proposal2.getObject().getName()) && proposal.getObjectContainer() == selectedObject) { proposals.remove(j); } else { j++; } } } } if (hideDups) { // Remove duplicates from non-active schema if (selectedObject instanceof DBSObjectContainer) { // List<ICompletionProposal> } } return proposals.toArray(new ICompletionProposal[proposals.size()]); } @NotNull private ICompletionProposal[] makeTemplateProposals( ITextViewer viewer, int documentOffset, String wordPart) { wordPart = wordPart.toLowerCase(); final List<SQLTemplateCompletionProposal> templateProposals = new ArrayList<>(); // Templates for (Template template : editor.getTemplatesPage().getTemplateStore().getTemplates()) { if (template.getName().toLowerCase().startsWith(wordPart)) { templateProposals.add( new SQLTemplateCompletionProposal( template, new SQLContext( SQLTemplatesRegistry.getInstance() .getTemplateContextRegistry() .getContextType(template.getContextTypeId()), viewer.getDocument(), new Position(wordDetector.getStartOffset(), wordDetector.getLength()), editor), new Region(documentOffset, 0), null)); } } return templateProposals.toArray(new ICompletionProposal[templateProposals.size()]); } private void makeStructureProposals( final DBRProgressMonitor monitor, final List<SQLCompletionProposal> proposals, final String wordPart, final QueryType queryType) { DBPDataSource dataSource = editor.getDataSource(); if (dataSource == null) { return; } if (queryType != null) { // Try to determine which object is queried (if wordPart is not empty) // or get list of root database objects if (wordPart.length() == 0) { // Get root objects DBSObject rootObject = null; if (queryType == QueryType.COLUMN && dataSource instanceof DBSObjectContainer) { // Try to detect current table rootObject = getTableFromAlias(monitor, (DBSObjectContainer) dataSource, null); } else if (dataSource instanceof DBSObjectContainer) { // Try to get from active object DBSObject selectedObject = getSelectedObject(dataSource); if (selectedObject != null) { makeProposalsFromChildren(monitor, selectedObject, null, proposals); } rootObject = (DBSObjectContainer) dataSource; } if (rootObject != null) { makeProposalsFromChildren(monitor, rootObject, null, proposals); } } else { DBSObject rootObject = null; if (queryType == QueryType.COLUMN && dataSource instanceof DBSObjectContainer) { // Part of column name // Try to get from active object DBSObjectContainer sc = (DBSObjectContainer) dataSource; DBSObject selectedObject = getSelectedObject(dataSource); if (selectedObject instanceof DBSObjectContainer) { sc = (DBSObjectContainer) selectedObject; } int divPos = wordPart.indexOf(editor.getSyntaxManager().getStructSeparator()); String tableAlias = divPos == -1 ? null : wordPart.substring(0, divPos); rootObject = getTableFromAlias(monitor, sc, tableAlias); } if (rootObject != null) { makeProposalsFromChildren(monitor, rootObject, wordPart, proposals); } else { // Get root object or objects from active database (if any) makeStructureProposals(monitor, dataSource, proposals); } } } else { // Get list of sub-objects (filtered by wordPart) makeStructureProposals(monitor, dataSource, proposals); } } private void makeStructureProposals( DBRProgressMonitor monitor, DBPDataSource dataSource, List<SQLCompletionProposal> proposals) { final DBSObjectContainer rootContainer = DBUtils.getAdapter(DBSObjectContainer.class, dataSource); if (rootContainer == null) { return; } DBSObjectContainer selectedContainer = null; { DBSObject selectedObject = getSelectedObject(dataSource); if (selectedObject != null) { selectedContainer = DBUtils.getAdapter(DBSObjectContainer.class, selectedObject); } } DBSObjectContainer sc = rootContainer; DBSObject childObject = sc; List<String> tokens = wordDetector.splitWordPart(); String lastToken = null; for (int i = 0; i < tokens.size(); i++) { String token = tokens.get(i); if (i == tokens.size() - 1 && !wordDetector.getWordPart().endsWith(".")) { lastToken = token; break; } if (sc == null) { break; } // Get next structure container try { String objectName = DBObjectNameCaseTransformer.transformName(dataSource, token); childObject = sc.getChild(monitor, objectName); if (childObject == null && i == 0 && selectedContainer != null) { // Probably it is from selected object, let's try it childObject = selectedContainer.getChild(monitor, objectName); if (childObject != null) { sc = selectedContainer; } } if (childObject == null) { if (i == 0) { // Assume it's a table alias ? childObject = this.getTableFromAlias(monitor, sc, token); if (childObject == null) { DBSStructureAssistant structureAssistant = DBUtils.getAdapter(DBSStructureAssistant.class, sc); if (structureAssistant != null) { Collection<DBSObjectReference> references = structureAssistant.findObjectsByMask( monitor, null, structureAssistant.getAutoCompleteObjectTypes(), wordDetector.removeQuotes(token), wordDetector.isQuoted(token), 2); if (!references.isEmpty()) { childObject = references.iterator().next().resolveObject(monitor); } } } } else { // Path element not found. Damn - can't do anything. return; } } if (childObject instanceof DBSObjectContainer) { sc = (DBSObjectContainer) childObject; } else { sc = null; } } catch (DBException e) { log.error(e); return; } } if (childObject == null) { return; } if (lastToken == null) { // Get all children objects as proposals makeProposalsFromChildren(monitor, childObject, null, proposals); } else { // Get matched children makeProposalsFromChildren(monitor, childObject, lastToken, proposals); if (proposals.isEmpty() || tokens.size() == 1) { // At last - try to find child tables by pattern DBSStructureAssistant structureAssistant = null; for (DBSObject object = childObject; object != null; object = object.getParentObject()) { structureAssistant = DBUtils.getAdapter(DBSStructureAssistant.class, object); if (structureAssistant != null) { break; } } if (structureAssistant != null) { makeProposalsFromAssistant(monitor, structureAssistant, sc, lastToken, proposals); } } } } @Nullable private DBSObject getTableFromAlias( DBRProgressMonitor monitor, DBSObjectContainer sc, @Nullable String token) { final DBPDataSource dataSource = editor.getDataSource(); if (!(dataSource instanceof SQLDataSource)) { return null; } if (activeQuery == null) { activeQuery = editor.extractQueryAtPos(documentOffset).getQuery() + " "; } final List<String> nameList = new ArrayList<>(); if (token == null) { token = ""; } { Matcher matcher; Pattern aliasPattern; SQLDialect sqlDialect = ((SQLDataSource) dataSource).getSQLDialect(); String quoteString = sqlDialect.getIdentifierQuoteString(); String quote = quoteString == null ? SQLConstants.STR_QUOTE_DOUBLE : SQLConstants.STR_QUOTE_DOUBLE.equals(quoteString) ? quoteString : Pattern.quote(quoteString); String catalogSeparator = sqlDialect.getCatalogSeparator(); while (token.endsWith(catalogSeparator)) token = token.substring(0, token.length() - 1); String tableNamePattern = "((?:" + quote + "(?:[.[^" + quote + "]]+)" + quote + ")|(?:[\\w" + Pattern.quote(catalogSeparator) + "]+))"; String structNamePattern; if (CommonUtils.isEmpty(token)) { structNamePattern = "(?:from|update|join|into)\\s*" + tableNamePattern; } else { structNamePattern = tableNamePattern + "(?:\\s*\\.\\s*" + tableNamePattern + ")?" + "\\s+(?:(?:AS)\\s)?" + token + "[\\s,]+"; } try { aliasPattern = Pattern.compile(structNamePattern, Pattern.CASE_INSENSITIVE); } catch (PatternSyntaxException e) { // Bad pattern - seems to be a bad token return null; } matcher = aliasPattern.matcher(activeQuery); if (!matcher.find()) { return null; } int groupCount = matcher.groupCount(); for (int i = 1; i <= groupCount; i++) { String group = matcher.group(i); if (!CommonUtils.isEmpty(group)) { String[] allNames = group.split(Pattern.quote(catalogSeparator)); for (String name : allNames) { if (quoteString != null && name.startsWith(quoteString) && name.endsWith(quoteString)) { name = name.substring(1, name.length() - 1); } nameList.add(name); } } } } if (nameList.isEmpty()) { return null; } for (int i = 0; i < nameList.size(); i++) { nameList.set( i, DBObjectNameCaseTransformer.transformName(sc.getDataSource(), nameList.get(i))); } try { DBSObject childObject = null; while (childObject == null) { childObject = DBUtils.findNestedObject(monitor, sc, nameList); if (childObject == null) { DBSObjectContainer parentSc = DBUtils.getParentAdapter(DBSObjectContainer.class, sc); if (parentSc == null) { break; } sc = parentSc; } } if (childObject == null && nameList.size() <= 1) { // No such object found - may be it's start of table name DBSStructureAssistant structureAssistant = DBUtils.getAdapter(DBSStructureAssistant.class, sc); if (structureAssistant != null) { String objectNameMask = nameList.get(0); Collection<DBSObjectReference> tables = structureAssistant.findObjectsByMask( monitor, sc, structureAssistant.getAutoCompleteObjectTypes(), wordDetector.removeQuotes(objectNameMask), wordDetector.isQuoted(objectNameMask), 2); if (!tables.isEmpty()) { return tables.iterator().next().resolveObject(monitor); } } return null; } else { return childObject; } } catch (DBException e) { log.error(e); return null; } } private void makeProposalsFromChildren( DBRProgressMonitor monitor, DBSObject parent, @Nullable String startPart, List<SQLCompletionProposal> proposals) { if (startPart != null) { startPart = wordDetector.removeQuotes(startPart).toUpperCase(); int divPos = startPart.lastIndexOf(editor.getSyntaxManager().getStructSeparator()); if (divPos != -1) { startPart = startPart.substring(divPos + 1); } } try { Collection<? extends DBSObject> children = null; if (parent instanceof DBSObjectContainer) { children = ((DBSObjectContainer) parent).getChildren(monitor); } else if (parent instanceof DBSEntity) { children = ((DBSEntity) parent).getAttributes(monitor); } if (children != null && !children.isEmpty()) { for (DBSObject child : children) { if (startPart != null && !child.getName().toUpperCase().startsWith(startPart)) { continue; } proposals.add(makeProposalsFromObject(monitor, child)); } } } catch (DBException e) { log.error(e); } } private void makeProposalsFromAssistant( DBRProgressMonitor monitor, DBSStructureAssistant assistant, @Nullable DBSObjectContainer rootSC, String objectName, List<SQLCompletionProposal> proposals) { try { Collection<DBSObjectReference> references = assistant.findObjectsByMask( monitor, rootSC, assistant.getAutoCompleteObjectTypes(), wordDetector.removeQuotes(objectName) + "%", wordDetector.isQuoted(objectName), 100); for (DBSObjectReference reference : references) { proposals.add(makeProposalsFromObject(reference, reference.getObjectType().getImage())); } } catch (DBException e) { log.error(e); } } private SQLCompletionProposal makeProposalsFromObject( DBRProgressMonitor monitor, DBSObject object) { DBNNode node = DBeaverCore.getInstance().getNavigatorModel().getNodeByObject(monitor, object, false); return makeProposalsFromObject(object, node == null ? null : node.getNodeIconDefault()); } private SQLCompletionProposal makeProposalsFromObject( DBPNamedObject object, @Nullable DBPImage objectIcon) { String objectName = DBUtils.getObjectFullName(object); StringBuilder info = new StringBuilder(); PropertyCollector collector = new PropertyCollector(object, false); collector.collectProperties(); for (DBPPropertyDescriptor descriptor : collector.getPropertyDescriptors2()) { Object propValue = collector.getPropertyValue(descriptor.getId()); if (propValue == null) { continue; } String propString = propValue.toString(); info.append("<b>").append(descriptor.getDisplayName()).append(": </b>"); info.append(propString); info.append("<br>"); } boolean isSingleObject = true; String replaceString = null; DBPDataSource dataSource = editor.getDataSource(); if (dataSource != null) { // If we replace short name with referenced object // and current active schema (catalog) is not this object's container then // replace with full qualified name if (!getPreferences().getBoolean(SQLPreferenceConstants.PROPOSAL_SHORT_NAME) && object instanceof DBSObjectReference) { if (wordDetector.getFullWord().indexOf(editor.getSyntaxManager().getStructSeparator()) == -1) { DBSObjectReference structObject = (DBSObjectReference) object; if (structObject.getContainer() != null) { DBSObject selectedObject = getSelectedObject(dataSource); if (selectedObject != structObject.getContainer()) { replaceString = DBUtils.getFullQualifiedName(dataSource, structObject.getContainer(), object); isSingleObject = false; } } } } if (replaceString == null) { replaceString = DBUtils.getQuotedIdentifier(dataSource, object.getName()); } } else { replaceString = DBUtils.getObjectShortName(object); } return createCompletionProposal( replaceString, objectName, info.toString(), objectIcon, isSingleObject, object); } private DBPPreferenceStore getPreferences() { DBPPreferenceStore store = null; DBPDataSource dataSource = editor.getDataSource(); if (dataSource != null) { store = dataSource.getContainer().getPreferenceStore(); } if (store == null) { store = DBeaverCore.getGlobalPreferenceStore(); } return store; } /* * Turns the vector into an Array of ICompletionProposal objects */ protected SQLCompletionProposal createCompletionProposal( String replaceString, String displayString, String description, @Nullable DBPImage image, boolean isObject, @Nullable DBPNamedObject object) { DBPPreferenceStore store = getPreferences(); DBPDataSource dataSource = editor.getDataSource(); if (dataSource != null) { if (isObject) { // Escape replace string if required replaceString = DBUtils.getQuotedIdentifier(dataSource, replaceString); } } // If we have quoted string then ignore pref settings boolean quotedString = wordDetector.isQuoted(replaceString); final int proposalCase = quotedString ? SQLPreferenceConstants.PROPOSAL_CASE_DEFAULT : store.getInt(SQLPreferenceConstants.PROPOSAL_INSERT_CASE); switch (proposalCase) { case SQLPreferenceConstants.PROPOSAL_CASE_UPPER: replaceString = replaceString.toUpperCase(); break; case SQLPreferenceConstants.PROPOSAL_CASE_LOWER: replaceString = replaceString.toLowerCase(); break; default: DBPIdentifierCase convertCase = quotedString && dataSource instanceof SQLDataSource ? ((SQLDataSource) dataSource).getSQLDialect().storesQuotedCase() : DBPIdentifierCase.MIXED; replaceString = convertCase.transform(replaceString); break; } Image img = image == null ? null : DBeaverIcons.getImage(image); return new SQLCompletionProposal( editor.getSyntaxManager(), displayString, replaceString, // replacementString wordDetector, // wordDetector replaceString.length(), // cursorPosition the position of the cursor following the insert // relative to replacementOffset img, // image to display new ContextInformation( img, displayString, displayString), // the context information associated with this proposal description, object); } /** * This method is incomplete in that it does not implement logic to produce some context help * relevant to SQL. It just hard codes two strings to demonstrate the action * * @see * org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(ITextViewer, * int) */ @Nullable @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { SQLQuery statementInfo = editor.extractQueryAtPos(documentOffset); if (statementInfo == null || CommonUtils.isEmpty(statementInfo.getQuery())) { return null; } IContextInformation[] result = new IContextInformation[1]; result[0] = new ContextInformation(statementInfo.getQuery(), statementInfo.getQuery()); return result; } @Override public char[] getCompletionProposalAutoActivationCharacters() { return new char[] {'.'}; } @Nullable @Override public char[] getContextInformationAutoActivationCharacters() { return null; } @Nullable @Override public String getErrorMessage() { return null; } @Override public IContextInformationValidator getContextInformationValidator() { return validator; } @Nullable private static DBSObject getSelectedObject(DBPDataSource dataSource) { DBSObjectSelector objectSelector = DBUtils.getAdapter(DBSObjectSelector.class, dataSource); if (objectSelector != null) { return objectSelector.getSelectedObject(); } return null; } /** * Simple content assist tip closer. The tip is valid in a range of 5 characters around its popup * location. */ protected static class Validator implements IContextInformationValidator, IContextInformationPresenter { protected int fInstallOffset; @Override public boolean isContextInformationValid(int offset) { return Math.abs(fInstallOffset - offset) < 5; } @Override public void install(IContextInformation info, ITextViewer viewer, int offset) { fInstallOffset = offset; } @Override public boolean updatePresentation(int documentPosition, TextPresentation presentation) { return false; } } }
/** DataTransferSettings */ public class DataTransferSettings { private static final Log log = Log.getLog(DataTransferSettings.class); private static final int DEFAULT_THREADS_NUM = 1; public static class NodeSettings { DataTransferNodeDescriptor sourceNode; IDataTransferSettings settings; IWizardPage[] pages; private NodeSettings(DataTransferNodeDescriptor sourceNode) throws DBException { this.sourceNode = sourceNode; this.settings = sourceNode.createSettings(); this.pages = sourceNode.createWizardPages(); } } private List<DataTransferPipe> dataPipes; private DataTransferNodeDescriptor producer; private DataTransferNodeDescriptor consumer; private DataTransferProcessorDescriptor processor; private Map<DataTransferProcessorDescriptor, Map<Object, Object>> processorPropsHistory = new HashMap<>(); private Map<Class, NodeSettings> nodeSettings = new LinkedHashMap<>(); private boolean consumerOptional; private int maxJobCount = DEFAULT_THREADS_NUM; private transient int curPipeNum = 0; public DataTransferSettings( @Nullable IDataTransferProducer[] producers, @Nullable IDataTransferConsumer[] consumers) { dataPipes = new ArrayList<>(); if (!ArrayUtils.isEmpty(producers) && !ArrayUtils.isEmpty(consumers)) { if (producers.length != consumers.length) { throw new IllegalArgumentException("Producers number must match consumers number"); } // Make pipes for (int i = 0; i < producers.length; i++) { dataPipes.add(new DataTransferPipe(producers[i], consumers[i])); } consumerOptional = false; } else if (!ArrayUtils.isEmpty(producers)) { // Make pipes for (IDataTransferProducer source : producers) { dataPipes.add(new DataTransferPipe(source, null)); } // Set default producer Class<? extends IDataTransferProducer> producerType = dataPipes.get(0).getProducer().getClass(); DataTransferNodeDescriptor producerDesc = DataTransferRegistry.getInstance().getNodeByType(producerType); if (producerDesc != null) { selectProducer(producerDesc); consumerOptional = true; } else { UIUtils.showErrorDialog( null, "Can't find producer", "Can't find data propducer descriptor in registry"); } } else if (!ArrayUtils.isEmpty(consumers)) { // Make pipes for (IDataTransferConsumer target : consumers) { dataPipes.add(new DataTransferPipe(null, target)); } // Set default consumer Class<? extends IDataTransferConsumer> consumerType = dataPipes.get(0).getConsumer().getClass(); DataTransferNodeDescriptor consumerDesc = DataTransferRegistry.getInstance().getNodeByType(consumerType); if (consumerDesc != null) { selectConsumer(consumerDesc, null); consumerOptional = false; } else { UIUtils.showErrorDialog( null, "Can't find producer", "Can't find data propducer descriptor in registry"); } } else { throw new IllegalArgumentException("Producers or consumers must be specified"); } Collection<Class<?>> objectTypes = getObjectTypes(); List<DataTransferNodeDescriptor> nodes = new ArrayList<>(); DataTransferRegistry registry = DataTransferRegistry.getInstance(); if (ArrayUtils.isEmpty(producers)) { nodes.addAll(registry.getAvailableProducers(objectTypes)); } else { for (IDataTransferProducer source : producers) { DataTransferNodeDescriptor node = registry.getNodeByType(source.getClass()); if (node != null && !nodes.contains(node)) { nodes.add(node); } } } if (ArrayUtils.isEmpty(consumers)) { nodes.addAll(registry.getAvailableConsumers(objectTypes)); } else { for (IDataTransferConsumer target : consumers) { DataTransferNodeDescriptor node = registry.getNodeByType(target.getClass()); if (node != null && !nodes.contains(node)) { nodes.add(node); this.consumer = node; } } } for (DataTransferNodeDescriptor node : nodes) { addNodeSettings(node); } } private void addNodeSettings(DataTransferNodeDescriptor node) { if (node == null) { return; } Class<? extends IDataTransferNode> nodeClass = node.getNodeClass(); if (nodeSettings.containsKey(nodeClass)) { return; } try { nodeSettings.put(nodeClass, new NodeSettings(node)); } catch (DBException e) { log.error("Can't add node '" + node.getId() + "'", e); } } void addWizardPages(DataTransferWizard wizard) { for (NodeSettings nodeSettings : this.nodeSettings.values()) { if (nodeSettings.pages != null) { for (IWizardPage page : nodeSettings.pages) { wizard.addPage(page); } } } } public boolean isConsumerOptional() { return consumerOptional; } public boolean isPageValid(IWizardPage page) { return isPageValid(page, producer) || isPageValid(page, consumer); } private boolean isPageValid(IWizardPage page, DataTransferNodeDescriptor node) { NodeSettings nodeSettings = node == null ? null : this.nodeSettings.get(node.getNodeClass()); return nodeSettings != null && ArrayUtils.contains(nodeSettings.pages, page); } public Collection<Class<?>> getObjectTypes() { List<DataTransferPipe> dataPipes = getDataPipes(); Set<Class<?>> objectTypes = new HashSet<>(); for (DataTransferPipe transferPipe : dataPipes) { if (transferPipe.getProducer() != null) { objectTypes.add(transferPipe.getProducer().getSourceObject().getClass()); } } return objectTypes; } public IDataTransferSettings getNodeSettings(IWizardPage page) { for (NodeSettings nodeSettings : this.nodeSettings.values()) { if (nodeSettings.pages != null) { for (IWizardPage nodePage : nodeSettings.pages) { if (nodePage == page) { return nodeSettings.settings; } } } } return null; } public IDataTransferSettings getNodeSettings(IDataTransferNode node) { NodeSettings nodeSettings = this.nodeSettings.get(node.getClass()); return nodeSettings == null ? null : nodeSettings.settings; } public Map<Object, Object> getProcessorProperties() { if (processor == null) { throw new IllegalStateException("No processor selected"); } return processorPropsHistory.get(processor); } public void setProcessorProperties(Map<Object, Object> properties) { if (processor == null) { throw new IllegalStateException("No processor selected"); } processorPropsHistory.put(processor, properties); } public List<DataTransferPipe> getDataPipes() { return dataPipes; } public synchronized DataTransferPipe acquireDataPipe(DBRProgressMonitor monitor) { if (curPipeNum >= dataPipes.size()) { // End of transfer // Signal last pipe about it if (!dataPipes.isEmpty()) { dataPipes.get(dataPipes.size() - 1).getConsumer().finishTransfer(monitor, true); } return null; } DataTransferPipe result = dataPipes.get(curPipeNum); curPipeNum++; return result; } public DataTransferNodeDescriptor getProducer() { return producer; } public DataTransferNodeDescriptor getConsumer() { return consumer; } public DataTransferProcessorDescriptor getProcessor() { return processor; } private void selectProducer(DataTransferNodeDescriptor producer) { this.producer = producer; } void selectConsumer( DataTransferNodeDescriptor consumer, DataTransferProcessorDescriptor processor) { this.consumer = consumer; this.processor = processor; if (consumer != null && processor != null) { if (!processorPropsHistory.containsKey(processor)) { processorPropsHistory.put(processor, new HashMap<>()); } } // Configure pipes for (DataTransferPipe pipe : dataPipes) { if (consumer != null) { try { pipe.setConsumer((IDataTransferConsumer) consumer.createNode()); } catch (DBException e) { log.error(e); pipe.setConsumer(null); } } else { pipe.setConsumer(null); } } } public int getMaxJobCount() { return maxJobCount; } public void setMaxJobCount(int maxJobCount) { if (maxJobCount > 0) { this.maxJobCount = maxJobCount; } } void loadFrom(IRunnableContext runnableContext, IDialogSettings dialogSettings) { try { maxJobCount = dialogSettings.getInt("maxJobCount"); } catch (NumberFormatException e) { maxJobCount = DEFAULT_THREADS_NUM; } String producerId = dialogSettings.get("producer"); if (!CommonUtils.isEmpty(producerId)) { DataTransferNodeDescriptor producerNode = DataTransferRegistry.getInstance().getNodeById(producerId); if (producerNode != null) { this.producer = producerNode; } } if (consumerOptional) { DataTransferNodeDescriptor savedConsumer = null; String consumerId = dialogSettings.get("consumer"); if (!CommonUtils.isEmpty(consumerId)) { DataTransferNodeDescriptor consumerNode = DataTransferRegistry.getInstance().getNodeById(consumerId); if (consumerNode != null) { savedConsumer = consumerNode; } } DataTransferProcessorDescriptor savedProcessor = null; if (savedConsumer != null) { String processorId = dialogSettings.get("processor"); if (!CommonUtils.isEmpty(processorId)) { savedProcessor = savedConsumer.getProcessor(processorId); } } if (savedConsumer != null) { selectConsumer(savedConsumer, savedProcessor); } } // Load nodes' settings for (Map.Entry<Class, NodeSettings> entry : nodeSettings.entrySet()) { IDialogSettings nodeSection = DialogSettings.getOrCreateSection(dialogSettings, entry.getKey().getSimpleName()); entry.getValue().settings.loadSettings(runnableContext, this, nodeSection); } IDialogSettings processorsSection = dialogSettings.getSection("processors"); if (processorsSection != null) { for (IDialogSettings procSection : ArrayUtils.safeArray(processorsSection.getSections())) { String processorId = procSection.getName(); String nodeId = procSection.get("@node"); String propNamesId = procSection.get("@propNames"); DataTransferNodeDescriptor node = DataTransferRegistry.getInstance().getNodeById(nodeId); if (node != null) { Map<Object, Object> props = new HashMap<>(); DataTransferProcessorDescriptor nodeProcessor = node.getProcessor(processorId); if (nodeProcessor != null) { for (String prop : CommonUtils.splitString(propNamesId, ',')) { props.put(prop, procSection.get(prop)); } processorPropsHistory.put(nodeProcessor, props); NodeSettings nodeSettings = this.nodeSettings.get(node.getNodeClass()); if (nodeSettings != null) {} } } } } } void saveTo(IDialogSettings dialogSettings) { dialogSettings.put("maxJobCount", maxJobCount); // Save nodes' settings for (Map.Entry<Class, NodeSettings> entry : nodeSettings.entrySet()) { IDialogSettings nodeSection = DialogSettings.getOrCreateSection(dialogSettings, entry.getKey().getSimpleName()); entry.getValue().settings.saveSettings(nodeSection); } if (producer != null) { dialogSettings.put("producer", producer.getId()); } if (consumer != null) { dialogSettings.put("consumer", consumer.getId()); } if (processor != null) { dialogSettings.put("processor", processor.getId()); } // Save processors' properties IDialogSettings processorsSection = DialogSettings.getOrCreateSection(dialogSettings, "processors"); for (DataTransferProcessorDescriptor procDescriptor : processorPropsHistory.keySet()) { IDialogSettings procSettings = DialogSettings.getOrCreateSection(processorsSection, procDescriptor.getId()); procSettings.put("@node", procDescriptor.getNode().getId()); Map<Object, Object> props = processorPropsHistory.get(procDescriptor); if (props != null) { StringBuilder propNames = new StringBuilder(); for (Map.Entry<Object, Object> prop : props.entrySet()) { propNames.append(prop.getKey()).append(','); } procSettings.put("@propNames", propNames.toString()); for (Map.Entry<Object, Object> prop : props.entrySet()) { procSettings.put( CommonUtils.toString(prop.getKey()), CommonUtils.toString(prop.getValue())); } } } } }