/* * 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; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.eclipse.wst.server.core.IServer; import org.eclipse.wst.server.core.IServerLifecycleListener; import org.eclipse.wst.server.core.IServerListener; import org.eclipse.wst.server.core.ServerCore; import org.eclipse.wst.server.core.internal.ResourceManager; import org.teiid.designer.core.ModelerCore; /** * Default implementation of {@link IServersProvider} that utilises * the {@link ServerCore}. * * This implementation is designed to check for and wait on the initialisation of {@link ServerCore}'s * server collection. This is actually initialised by its internal ResoourceManager, which * fails to identify when its in the process of initialisation itself. * * Should a call be made to {@link ServerCore#getServers()} while the ResourceManager * is initialisation then an incorrect empty collection is returned. To mitigate this scenario, * a wait thread is provided that will notify all interested listeners once the ResourceManager * has been correctly initialised and the servers can be fetched correctly. * * @since 8.0 * */ public class DefaultServersProvider implements IServersProvider { private static final String ERROR_MSG = "Programming Error: The DefaultServersProvider is dependent upon " + //$NON-NLS-1$ "the org.eclipse.wst.server.core.ServerCore for providing the parent " + //$NON-NLS-1$ "servers configured in the Server View. The ServerCore needs to be" + //$NON-NLS-1$ "initialised through a Job and as such is not available until the IDE has " + //$NON-NLS-1$ "been fully loaded. See the DefaultServersProvider class for ways of " + //$NON-NLS-1$ "avoiding this error."; //$NON-NLS-1$ private class ObserverThread extends Thread { public ObserverThread() { super(DefaultServersProvider.this + "." + ObserverThread.class.getSimpleName()); //$NON-NLS-1$ setDaemon(true); } @Override public void run() { while(! isServerCoreInitialised()) { try { Thread.sleep(3000); } catch (InterruptedException ex) { ModelerCore.Util.log(ex); } } synchronized(listenerLock) { Iterator<IServersInitialiseListener> iterator = listeners.iterator(); while(iterator.hasNext()) { IServersInitialiseListener listener = iterator.next(); listener.serversInitialised(); iterator.remove(); } } } } private static final String INIT_FIELD_NAME = "initialized"; //$NON-NLS-1$ private static Field resourceManagerInitField; private Object listenerLock = new Object(); private Collection<IServersInitialiseListener> listeners = new ArrayList<IServersInitialiseListener>(); /** * Create a new instance */ public DefaultServersProvider() { try { resourceManagerInitField = ResourceManager.class.getDeclaredField(INIT_FIELD_NAME); resourceManagerInitField.setAccessible(true); ObserverThread thread = new ObserverThread(); thread.start(); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * Check if ServerCore is properly initialised */ private boolean isServerCoreInitialised() { try { return (Boolean) resourceManagerInitField.get(ResourceManager.class); } catch (Exception ex) { throw new RuntimeException(ex); } } private void checkServerCoreInitialised() { if (! isServerCoreInitialised()) throw new RuntimeException(ERROR_MSG); } @Override public boolean isInitialised() { return isServerCoreInitialised(); } @Override public void addServerInitialisedListener(IServersInitialiseListener listener) { if (isInitialised()) { // No need to listen since everything is initialised listener.serversInitialised(); return; } synchronized(listenerLock) { listeners.add(listener); } } @Override public void removeServerInitialisedListener(IServersInitialiseListener listener) { synchronized(listenerLock) { listeners.remove(listener); } } @Override public void addServerLifecycleListener(IServerLifecycleListener listener) { checkServerCoreInitialised(); ServerCore.addServerLifecycleListener(listener); } @Override public void removeServerLifecycleListener(IServerLifecycleListener listener) { checkServerCoreInitialised(); ServerCore.removeServerLifecycleListener(listener); } @Override public IServer[] getServers() { checkServerCoreInitialised(); return ServerCore.getServers(); } @Override public void addServerStateListener(IServerListener serverStateListener) { checkServerCoreInitialised(); for (IServer server : getServers()) { server.addServerListener(serverStateListener); } } @Override public void removeServerStateListener(IServerListener serverStateListener) { checkServerCoreInitialised(); for (IServer server : getServers()) { server.removeServerListener(serverStateListener); } } }