/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.runtime.ui.views; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.jcip.annotations.GuardedBy; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.navigator.IDescriptionProvider; import org.teiid.designer.runtime.DqpPlugin; import org.teiid.designer.runtime.spi.ITeiidServer; import org.teiid.designer.runtime.spi.ITeiidServerManager; import org.teiid.designer.runtime.ui.DqpUiConstants; import org.teiid.designer.runtime.ui.DqpUiPlugin; import org.teiid.designer.runtime.ui.views.content.AbstractTeiidFolder; import org.teiid.designer.runtime.ui.views.content.ITeiidContentNode; import org.teiid.designer.runtime.ui.views.content.ITeiidResourceNode; import org.teiid.designer.runtime.ui.views.content.TeiidDataNode; import org.teiid.designer.runtime.ui.views.content.TeiidErrorNode; import org.teiid.designer.runtime.ui.views.content.TeiidServerContainerNode; /** * Class provides content and label information for ConnectorBindings and ModelInfos in ConnectorsView * * @since 8.0 */ public class TeiidServerLabelProvider extends ColumnLabelProvider implements ILightweightLabelDecorator, IDescriptionProvider { /** * If a server connection cannot be established, wait this amount of time before trying again. */ private static final long RETRY_DURATION = 2000; /** * Pattern for use with modifying text for the description */ private static Pattern pattern = Pattern.compile("[\\\n\\\t]+"); //$NON-NLS-1$ private ITeiidServerManager serverMgr; /** * Servers that a connection can't be established. Value is the last time establishing a connection was tried. */ @GuardedBy( "offlineServersLock" ) private final Map<ITeiidServer, Long> offlineServerMap = new HashMap<ITeiidServer, Long>(); /** * Lock used for when accessing the offline server map. The map will be accessed in different threads as the decorator runs in * its own thread (not the UI thread). */ private final ReadWriteLock offlineServersLock = new ReentrantReadWriteLock(); /** * @param teiidServer the server that is offline */ private void addOfflineServer(ITeiidServer teiidServer) { try { this.offlineServersLock.writeLock().lock(); this.offlineServerMap.put(teiidServer, System.currentTimeMillis()); } finally { this.offlineServersLock.writeLock().unlock(); } } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration) */ @Override public void decorate(Object element, IDecoration decoration) { final Display display = Display.getDefault(); if (display.isDisposed()) { return; } // the decorator framework actually constructs another instance of this provider and the server manager will not be set by // the getElements method if (getServerManager() != null && element instanceof TeiidServerContainerNode) { TeiidServerContainerNode node = (TeiidServerContainerNode) element; ITeiidServer teiidServer = node.getTeiidServer(); if (isOkToConnect(teiidServer)) { // decorate server if can't connect if (!teiidServer.isConnected()) { addOfflineServer(teiidServer); } } } } /** * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) * @since 4.2 */ @Override public Image getImage(Object element) { if (element instanceof ITeiidResourceNode) { return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); } if (element instanceof TeiidServerContainerNode) { return DqpUiPlugin.getDefault().getAnImage(DqpUiConstants.Images.SERVER_ICON); } if (element instanceof AbstractTeiidFolder) { return DqpUiPlugin.getDefault().getAnImage(DqpUiConstants.Images.FOLDER_OBJ); } if (element instanceof TeiidDataNode) { return ((TeiidDataNode) element).getImage(); } if (element instanceof TeiidErrorNode) { ITeiidServer teiidServer = ((TeiidErrorNode) element).getTeiidServer(); if (getServerManager() != null && teiidServer != null && this.serverMgr.isDefaultServer(teiidServer)) return DqpUiPlugin.getDefault().getAnImage(DqpUiConstants.Images.SET_DEFAULT_SERVER_ERROR_ICON); else return DqpUiPlugin.getDefault().getAnImage(DqpUiConstants.Images.SERVER_ERROR_ICON); } return null; } /** * @return the server manager (never <code>null</code>) */ private ITeiidServerManager getServerManager() { if (this.serverMgr == null) { this.serverMgr = DqpPlugin.getInstance().getServerManager(); } return this.serverMgr; } /** * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) * @since 4.2 */ @Override public String getText(Object element) { if (element instanceof ITeiidContentNode) { ITeiidContentNode node = (ITeiidContentNode) element; return node.getName(); } if (element instanceof String) { return (String)element; } if (element == TeiidServerContentProvider.getPending()) { return DqpUiConstants.UTIL.getString(getClass().getSimpleName() + ".loading.label"); //$NON-NLS-1$ } return super.getText(element); } /** * Determines if a try to connect to a server should be done based on the last time a try was done and failed. * * @param teiidServer the server being checked * @return <code>true</code> if it is OK to try and connect */ private synchronized boolean isOkToConnect(ITeiidServer teiidServer) { boolean check = false; // check map for time try { this.offlineServersLock.readLock().lock(); check = this.offlineServerMap.containsKey(teiidServer); } finally { this.offlineServersLock.readLock().unlock(); } if (check) { try { this.offlineServersLock.writeLock().lock(); if (this.offlineServerMap.containsKey(teiidServer)) { long checkTime = this.offlineServerMap.get(teiidServer); // OK to try and connect if last failed attempt was too long ago if ((System.currentTimeMillis() - checkTime) > RETRY_DURATION) { this.offlineServerMap.remove(teiidServer); return true; } // don't try and connect because we just tried and failed return false; } } finally { this.offlineServersLock.writeLock().unlock(); } } // OK to try and connect return true; } @Override public String getDescription(Object element) { String text = element.toString(); Matcher matcher = pattern.matcher(text); return matcher.replaceAll(" "); //$NON-NLS-1$ } }