/******************************************************************************* * Copyright (c) 2012, 2015 Wind River Systems, Inc. and others. All rights reserved. * This program and the accompanying materials are made available under the terms * of the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.tcf.processes.core.model.runtime; import java.util.Timer; import java.util.TimerTask; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IStatus; import org.eclipse.tcf.protocol.Protocol; import org.eclipse.tcf.te.core.interfaces.IConnectable; import org.eclipse.tcf.te.core.interfaces.IFilterable; import org.eclipse.tcf.te.runtime.callback.Callback; import org.eclipse.tcf.te.runtime.model.ContainerModelNode; import org.eclipse.tcf.te.runtime.model.contexts.AsyncRefreshableCtxAdapter; import org.eclipse.tcf.te.runtime.model.factory.Factory; import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx; import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryState; import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryType; import org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory; import org.eclipse.tcf.te.runtime.preferences.ScopedEclipsePreferences; import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelChannelService; import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelLookupService; import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService; import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelService; import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelUpdateService; import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; import org.eclipse.tcf.te.tcf.processes.core.activator.CoreBundleActivator; import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel; import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelLookupService; import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelRefreshService; import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelUpdateService; import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelChannelService; import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelLookupService; import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelRefreshService; import org.eclipse.tcf.te.tcf.processes.core.model.runtime.services.RuntimeModelUpdateService; /** * ModelManager implementation dealing with Processes at runtime. */ public final class RuntimeModel extends ContainerModelNode implements IRuntimeModel, IFilterable { // Flag to mark the model disposed private boolean disposed; // Reference to the model node factory private IFactory factory = null; // Reference to the associated peer model private final IPeerNode peerNode; // Reference to the refresh service private final IRuntimeModelRefreshService refreshService = new RuntimeModelRefreshService(this); // Reference to the lookup service private final IRuntimeModelLookupService lookupService = new RuntimeModelLookupService(this); // Reference to the update service private final IRuntimeModelUpdateService updateService = new RuntimeModelUpdateService(this); // Reference to the channel service private final IModelChannelService channelService = new RuntimeModelChannelService(this); // The runtime model needs asynchronous refreshes private final IAsyncRefreshableCtx refreshableCtxAdapter = new AsyncRefreshableCtxAdapter(); // The auto-refresh interval in seconds /* default */ int interval = 0; // The auto-refresh timer /* default */ Timer timer = null; /** * Constructor. * * @param peerNode The peerNode to associated. Must not be <code>null</code>. */ public RuntimeModel(IPeerNode peerNode) { super(); disposed = false; setChangeEventsEnabled(true); suppressEventsOnNullParent = false; Assert.isNotNull(peerNode); this.peerNode = peerNode; // No initial context query required refreshableCtxAdapter.setQueryState(QueryType.CONTEXT, QueryState.DONE); // Restore the auto refresh interval ScopedEclipsePreferences prefs = CoreBundleActivator.getScopedPreferences(); if (prefs.containsKey(peerNode.getPeerId() + ".autoRefreshInterval")) { //$NON-NLS-1$ setAutoRefreshInterval(prefs.getInt(peerNode.getPeerId() + ".autoRefreshInterval")); //$NON-NLS-1$ } } /* (non-Javadoc) * @see org.eclipse.tcf.te.runtime.nodes.PropertiesContainer#checkThreadAccess() */ @Override protected boolean checkThreadAccess() { return Protocol.isDispatchThread(); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#dispose() */ @Override public void dispose() { Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$ disposed = true; // Close the active channel (if any) channelService.closeChannel(); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#isDisposed() */ @Override public boolean isDisposed() { Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$ return disposed; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#getService(java.lang.Class) */ @Override @SuppressWarnings("unchecked") public <V extends IModelService> V getService(Class<V> serviceInterface) { Assert.isNotNull(serviceInterface); return (V)getAdapter(serviceInterface); } /* (non-Javadoc) * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) */ @Override public Object getAdapter(Class adapter) { if (IRuntimeModelRefreshService.class.equals(adapter)) { return refreshService; } if (IModelRefreshService.class.equals(adapter)) { return refreshService; } if (IRuntimeModelLookupService.class.equals(adapter)) { return lookupService; } if (IModelLookupService.class.equals(adapter)) { return lookupService; } if (IRuntimeModelUpdateService.class.equals(adapter)) { return updateService; } if (IModelUpdateService.class.equals(adapter)) { return updateService; } if (IModelChannelService.class.equals(adapter)) { return channelService; } if (IAsyncRefreshableCtx.class.equals(adapter)) { return refreshableCtxAdapter; } if (IPeerNode.class.isAssignableFrom(adapter) || IConnectable.class.isAssignableFrom(adapter)) { return getPeerNode(); } return super.getAdapter(adapter); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#setFactory(org.eclipse.tcf.te.runtime.model.interfaces.factory.IFactory) */ @Override public void setFactory(IFactory factory) { Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$ this.factory = factory; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.core.model.interfaces.IModel#getFactory() */ @Override public IFactory getFactory() { Assert.isTrue(checkThreadAccess(), "Illegal Thread Access"); //$NON-NLS-1$ return factory != null ? factory : Factory.getInstance(); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider#getPeerModel() */ @Override public final IPeerNode getPeerNode() { return peerNode; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel#setAutoRefreshInterval(int) */ @Override public final void setAutoRefreshInterval(int interval) { // Normalize the interval if (interval < 0) interval = 0; // Remember the old value (for the change event) final int oldInterval = this.interval; // Apply the new interval this.interval = interval; // If the interval has changed, start/stop the auto-refresh and send a change notification if (oldInterval != interval) { // Save the current auto refresh interval to the plugin preferences ScopedEclipsePreferences prefs = CoreBundleActivator.getScopedPreferences(); prefs.putInt(peerNode.getPeerId() + ".autoRefreshInterval", interval); //$NON-NLS-1$ // Get the auto-refresh started if not yet scheduled if (interval != 0 && timer == null) { // Create the timer task to schedule TimerTask task = new TimerTask() { @Override public void run() { // Drop out of the interval has been set to 0 in the meanwhile if (RuntimeModel.this.interval == 0) return; // Do the auto refresh doAutoRefresh(); } }; // Create the timer timer = new Timer(); timer.schedule(task, this.interval * 1000); } else if (interval == 0 && timer != null) { timer.cancel(); timer = null; } // Signal the change to the auto-refresh interval fireChangeEvent("autoRefreshInterval", Integer.valueOf(oldInterval), Integer.valueOf(interval)); //$NON-NLS-1$ } } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel#getAutoRefreshInterval() */ @Override public final int getAutoRefreshInterval() { return interval; } /** * Execute the auto refresh of the model and reschedule until stopped. */ /* default */ void doAutoRefresh() { Protocol.invokeLater(new Runnable() { @Override public void run() { // Refresh the model RuntimeModel.this.getService(IRuntimeModelRefreshService.class).refresh(new Callback() { @Override protected void internalDone(Object caller, IStatus status) { // Re-schedule ourself if the interval is still > 0 if (RuntimeModel.this.interval > 0 && timer != null) { // Create the timer task to schedule TimerTask task = new TimerTask() { @Override public void run() { // Drop out of the interval has been set to 0 in the meanwhile if (RuntimeModel.this.interval == 0) return; // Do the auto refresh doAutoRefresh(); } }; timer.schedule(task, RuntimeModel.this.interval * 1000); } } }); } }); } /* (non-Javadoc) * @see org.eclipse.tcf.te.runtime.model.ModelNode#toString() */ @Override public String toString() { if (disposed) { return "*DISPOSED* : " + super.toString(); //$NON-NLS-1$ } return super.toString(); } }