/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jkiss.dbeaver.ext.oracle.actions; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.commands.IElementUpdater; import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.menus.UIElement; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.core.DBeaverUI; import org.jkiss.dbeaver.ext.oracle.model.OracleObjectPersistAction; import org.jkiss.dbeaver.ext.oracle.model.OracleObjectType; import org.jkiss.dbeaver.ext.oracle.model.source.OracleSourceObject; import org.jkiss.dbeaver.ext.oracle.views.OracleCompilerDialog; import org.jkiss.dbeaver.model.DBPEvent; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.edit.DBEPersistAction; import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.exec.DBCStatement; import org.jkiss.dbeaver.model.exec.DBCStatementType; import org.jkiss.dbeaver.model.exec.compile.DBCCompileError; import org.jkiss.dbeaver.model.exec.compile.DBCCompileLog; import org.jkiss.dbeaver.model.exec.compile.DBCCompileLogBase; import org.jkiss.dbeaver.model.exec.compile.DBCSourceHost; import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement; import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress; import org.jkiss.dbeaver.model.struct.DBSObjectState; import org.jkiss.dbeaver.utils.RuntimeUtils; import org.jkiss.dbeaver.ui.TextUtils; import org.jkiss.dbeaver.ui.UIUtils; import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.CommonUtils; import java.lang.reflect.InvocationTargetException; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; public class CompileHandler extends AbstractHandler implements IElementUpdater { private 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(session, null); } catch (DBCException e) { action.handleExecute(session, 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; } } }