/* * Copyright 2000-2020 JetBrains s.r.o. * * 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 jetbrains.teamcity; import jetbrains.buildServer.*; import jetbrains.buildServer.activation.HttpActivationServer; import jetbrains.buildServer.delayedCommit.RemoteRunSessionData; import jetbrains.buildServer.notification.NotificationMessage; import jetbrains.buildServer.serverMessages.NotificationListener; import jetbrains.buildServer.serverMessages.PersonalChangeProcessor; import jetbrains.buildServer.serverProxy.ApplicationFacade; import jetbrains.buildServer.serverProxy.RemoteBuildServerFacade; import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.xmlrpc.XmlRpcTarget.Cancelable; import jetbrains.teamcity.core.*; import jetbrains.teamcity.core.Messages; import jetbrains.teamcity.core.remote.RemoteRunManager2; import jetbrains.teamcity.ui.LoginDialog; import jetbrains.teamcity.ui.Navigator; import org.apache.xmlrpc.XmlRpcClientException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProduct; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.osgi.framework.Bundle; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; public class EclipseIDE implements Ide { private final IdeAlarm myQueue = new EclipseIDEAlarm(); private final Collection myListeners = new CopyOnWriteArraySet(); private TeamCitySnapshot4Eclipse mySnapshot; private final ArrayList myStateChangedListeners = new ArrayList(); private Navigator myActivator; private ArrayList myActiveTeamcityResources = new ArrayList(); private final PersonalChangeProcessor myPersonalChangeListener; private final NotificationListener myNotificationListener; static class TCCommunicationException extends CoreException { private static final long serialVersionUID = 1L; public TCCommunicationException(IStatus status) { super(status); } } public EclipseIDE() { //listen personal changes myPersonalChangeListener = new PersonalChangeProcessor() { public void processChangeSucceeded(@NotNull final RemoteRunSessionData data, @NotNull final UserChangeInfo changeInfo) { for (final ITeamCityIDEListener listener : getListeners()) { listener.processChangeSucceeded(data, changeInfo); } } public void processChangeFailed(@NotNull final RemoteRunSessionData data, @NotNull final UserChangeInfo changeInfo) { for (final ITeamCityIDEListener listener : getListeners()) { listener.processChangeFailed(data, changeInfo); } } }; //listen notifications? myNotificationListener = new NotificationListener() { public void onMessageReceived(final NotificationMessage event, final boolean silent) { if (!event.isPersonalBuild()) { for (ITeamCityIDEListener listener : getListeners()) { listener.onMessageReceived(event, silent); } } } public void onSystemMessage(final String messageText) { for (ITeamCityIDEListener listener : getListeners()) { listener.onSystemMessage(messageText); } } }; addDelayedCommitListener(); } //TODO: move to appropriate place private void addDelayedCommitListener() { addListener(new TeamCityIDEAdapter() { @Override public void processChangeSucceeded(@NotNull RemoteRunSessionData data, @NotNull UserChangeInfo changeInfo) { RemoteRunManager2.doDelayedCommit(data, changeInfo); } }); } void dispose() { disposeSnapshot(); } private void disposeSnapshot() { if (mySnapshot != null) { flushPersonalChanges(mySnapshot); mySnapshot.getNotificationDispatcher().removeListener(myNotificationListener); mySnapshot.getPersonalBuildEventDispatcher().removeListener(myPersonalChangeListener); mySnapshot.dispose(); for (StateChangedListener listener : new ArrayList(myStateChangedListeners)) { mySnapshot.removeStateChangedListener(listener); } } try { HttpActivationServer.getInstance().shutdown(); } catch (Throwable t) { // no op } } public void flushPersonalChanges(TeamCitySnapshot snapshot) { final List sessions = snapshot.getPersonalSnapshot().getSessions(); snapshot.getPersonalSnapshot().shouldBeSaved(); RemoteRunManager2.saveData(getServerURL(), sessions); } void setSnapshot(final @NotNull TeamCitySnapshot4Eclipse snapshot) throws TCCommunicationException { if (mySnapshot != null) { disposeSnapshot(); } mySnapshot = snapshot; mySnapshot.getNotificationDispatcher().addListener(myNotificationListener); mySnapshot.getPersonalBuildEventDispatcher().addListener(myPersonalChangeListener); try { myActivator = new Navigator(/*this*/); HttpActivationServer.getInstance().start(myActivator); } catch (Exception t) { final XmlRpcClientException adapted = new XmlRpcClientException(String.format(Messages.getString("TeamCityIDE.http_activation_failed_error_message"), t.toString()), t); //$NON-NLS-1$ Activator.getDefault().getLog().log(Util.createStatus(IStatus.ERROR, adapted)); } // transfer listeners for (StateChangedListener listener : new ArrayList(myStateChangedListeners)) { mySnapshot.addStateChangedListener(listener); } } public synchronized void addListener(final @NotNull StateChangedListener listener) { myStateChangedListeners.add(listener); if (mySnapshot != null) { mySnapshot.addStateChangedListener(listener); } } public synchronized void removeListener(final @Nullable StateChangedListener listener) { if (listener != null) { myStateChangedListeners.remove(listener); if (mySnapshot != null) { mySnapshot.removeStateChangedListener(listener); } } } public void addToQueue(final TeamCityCommand command) { myQueue.addRequest(command, 0, Constants.EMPTY_STRING); } public IdeAlarm createAlarm() { return new EclipseIDEAlarm(); } public ApplicationFacade createApplicationFacade() { return new ApplicationFacade() { public Cancelable createCancelable() { return new Cancelable() { public boolean isCanceled() { return false; } public long sleepingPeriod() { return 0; } }; } public void onProcessCanceled() { // noop } }; } void addListener(ITeamCityIDEListener listener) { myListeners.add(listener); } void removeListener(ITeamCityIDEListener listener) { myListeners.remove(listener); } public void invokeManualLogin(@Nullable final String message) { // check thread. if (!isDispatchThread()) { getDisplay().asyncExec(new Runnable() { public void run() { doLogin(message); } }); } else { doLogin(message); } } public boolean isDispatchThread() { Display currentDisplay = getDisplay(); return !currentDisplay.isDisposed() && currentDisplay.getThread() == Thread.currentThread(); } private Display getDisplay() { Display currentDisplay = Display.getCurrent(); if (currentDisplay == null || currentDisplay.isDisposed()) { currentDisplay = Display.getDefault(); } return currentDisplay; } public boolean isDisposed() { return false; } public void showIncompatibleVersionProblemMessage(final RemoteBuildServerFacade facade, final IncompatiblePluginError error) { Activator.getDefault().getSnapshot().logout(); } public void showInfoMessage(final String message, final String caption) { getDisplay().asyncExec(new Runnable() { public void run() { MessageDialog.openInformation(getDisplay().getActiveShell(), caption, message); } }); } public void updateStatus() { for (ITeamCityIDEListener listener : getListeners()) { listener.updateStatus(); } } public void updateSummary(TeamServerSummaryProvider summaryProvider) { for (ITeamCityIDEListener listener : getListeners()) { listener.updateSummary(summaryProvider); } } private Collection getListeners() { return myListeners; } private void doLogin(String message) { // cancel all delayed login jobs. Job.getJobManager().cancel(LoginDialog.class); Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); LoginDialog dialog = new LoginDialog(shell); dialog.setInitialErrorMessage(message); dialog.open(); } public String getServerURL() { return mySnapshot.getServerURL(); } public boolean isFilterSummaryByCurrentProject() { return Activator.getDefault().getPreferenceStore().getBoolean(Constants.Preferences.TEAMCITY_DATE_RESTRICT_SCOPE); } public void setFilterSummaryByCurrentProject(final boolean filterIt) { Activator.getDefault().getPreferenceStore().setValue(Constants.Preferences.TEAMCITY_DATE_RESTRICT_SCOPE, filterIt); } public IdeAlarm getQueue() { return myQueue; } @NotNull public String getUserAgent() { try { return String.format("%s (%s; %s; %s)", getProductNameAndVersion(), Platform.getOS(), Platform.getWS(), Util.getBundleVersion(Activator.getDefault().getBundle())); } catch (Exception e) { Debug.getInstance().log(Debug.DEBUG_PLATFORM, e); return "Eclipse SDK"; //$NON-NLS-1$ } } @NotNull public static String getProductNameAndVersion() { try { StringBuilder sb = new StringBuilder(); final IProduct product = Platform.getProduct(); if (product != null && product.getName() != null && product.getDefiningBundle() != null) { final Bundle bundle = product.getDefiningBundle(); sb.append("Eclipse based "); sb.append(StringUtil.notNullize(Util.getBundleNameOrSymbolicName(bundle), "")); sb.append(' '); //$NON-NLS-1$ sb.append(Util.getVersionWithoutQualifier(Util.getBundleVersion(bundle))); } else { for (String name : Arrays.asList("org.eclipse.platform", "org.eclipse.sdk", "org.eclipse.core.runtime")) { //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ final Bundle bundle = Platform.getBundle(name); if (bundle == null) { continue; } sb.append(StringUtil.notNullize(Util.getBundleNameOrSymbolicName(bundle), name)); sb.append(' '); //$NON-NLS-1$ sb.append(Util.getVersionWithoutQualifier(Util.getBundleVersion(bundle))); break; } } if (sb.length() == 0) { sb.append("Eclipse SDK"); //$NON-NLS-1$ } return sb.toString(); } catch (Exception e) { Debug.getInstance().log(Debug.DEBUG_PLATFORM, e); return "Eclipse SDK"; //$NON-NLS-1$ } } @NotNull public Collection getSamplePaths() { return myActiveTeamcityResources; } public void setSamplePaths(final @NotNull Collection activeResources) { myActiveTeamcityResources = new ArrayList(activeResources); Activator.getDefault().getSnapshot().scheduleUpdate(); } public boolean isUIVisible() { for (ITeamCityIDEListener listener : getListeners()) { if (listener.isActive()) { return true; } } return false; } }