/* * This file is part of the OpenSCADA project * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) * * OpenSCADA is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenSCADA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenSCADA. If not, see * <http://opensource.org/licenses/lgpl-3.0.html> for a copy of the LGPLv3 License. */ package org.openscada.core.ui.connection.data; import java.util.Dictionary; import java.util.Hashtable; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.views.properties.IPropertySource; import org.openscada.core.client.Connection; import org.openscada.core.client.ConnectionState; import org.openscada.core.client.ConnectionStateListener; import org.openscada.core.connection.provider.ConnectionService; import org.openscada.core.ui.connection.Activator; import org.openscada.core.ui.connection.ConnectionDescriptor; import org.openscada.core.ui.connection.creator.ConnectionCreatorHelper; import org.openscada.utils.beans.AbstractPropertyChange; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ConnectionHolder extends AbstractPropertyChange implements ConnectionStateListener, IAdaptable { private final static Logger logger = LoggerFactory.getLogger ( ConnectionHolder.class ); public static final String PROP_CONNECTION_SERVICE = "connectionService"; public static final String PROP_CONNECTION_STATE = "connectionState"; public static final String PROP_CONNECTION_ERROR = "connectionError"; private final ConnectionDescriptor info; private final ConnectionDiscovererBean discoverer; private volatile ConnectionService connectionService; private volatile ConnectionState connectionState; private Throwable connectionError; private final BundleContext context; private ServiceRegistration<?> serviceRegistration; public ConnectionHolder ( final ConnectionDiscovererBean discoverer, final ConnectionDescriptor info ) throws InvalidSyntaxException { this.info = info; this.discoverer = discoverer; this.context = Activator.getDefault ().getBundle ().getBundleContext (); createConnection (); } private synchronized void createConnection () { final ConnectionService connectionService = ConnectionCreatorHelper.createConnection ( this.info.getConnectionInformation (), null ); if ( connectionService != null ) { connectionService.getConnection ().addConnectionStateListener ( this ); setConnectionService ( connectionService ); setConnectionState ( ConnectionState.CLOSED ); setConnectionError ( null ); registerConnection (); } } /** * Register the current connection as an OSGi service */ private void registerConnection () { final Class<?>[] interfaces = this.connectionService.getSupportedInterfaces (); final String[] clazzes = new String[interfaces.length]; int i = 0; for ( final Class<?> iface : interfaces ) { clazzes[i] = iface.getName (); i++; } final Dictionary<String, String> properties = new Hashtable<String, String> (); properties.put ( ConnectionService.CONNECTION_URI, this.info.getConnectionInformation ().toString () ); if ( this.info.getServiceId () != null ) { properties.put ( Constants.SERVICE_PID, this.info.getServiceId () ); } this.serviceRegistration = this.context.registerService ( clazzes, this.connectionService, properties ); } private synchronized void destroyConnection () { if ( this.serviceRegistration != null ) { this.serviceRegistration.unregister (); this.serviceRegistration = null; } if ( this.connectionService != null ) { this.connectionService.getConnection ().removeConnectionStateListener ( this ); this.connectionService.disconnect (); this.connectionService = null; setConnectionService ( null ); setConnectionState ( null ); setConnectionError ( null ); } } public synchronized void connect () { if ( this.connectionService != null ) { this.connectionService.connect (); } } public synchronized void disconnect () { if ( this.connectionService != null ) { this.connectionService.disconnect (); } } public ConnectionDiscovererBean getDiscoverer () { return this.discoverer; } @Override public String toString () { return this.info.toString (); } public void dispose () { destroyConnection (); } public ConnectionService getConnectionService () { return this.connectionService; } public ConnectionDescriptor getConnectionInformation () { return this.info; } public ConnectionState getConnectionState () { return this.connectionState; } protected void setConnectionState ( final ConnectionState connectionState ) { final ConnectionState oldConnectionState = this.connectionState; this.connectionState = connectionState; firePropertyChange ( PROP_CONNECTION_STATE, oldConnectionState, connectionState ); } public Throwable getConnectionError () { return this.connectionError; } protected void setConnectionService ( final ConnectionService connectionService ) { final ConnectionService olcConnectionService = connectionService; this.connectionService = connectionService; firePropertyChange ( PROP_CONNECTION_SERVICE, olcConnectionService, connectionService ); } protected void setConnectionError ( final Throwable connectionError ) { final Throwable olcConnectionError = connectionError; this.connectionError = connectionError; firePropertyChange ( PROP_CONNECTION_ERROR, olcConnectionError, connectionError ); } @Override public void stateChange ( final Connection connection, final ConnectionState state, final Throwable error ) { logger.debug ( "Connection state changed: {}", state ); final IStatus status = makeStatus ( connection, state, error ); Activator.getDefault ().getLog ().log ( status ); setConnectionState ( state ); setConnectionError ( error ); showError ( status ); } private void showError ( final IStatus status ) { if ( !status.matches ( IStatus.ERROR ) ) { return; } final Display display = PlatformUI.getWorkbench ().getDisplay (); if ( !display.isDisposed () ) { display.asyncExec ( new Runnable () { @Override public void run () { if ( !display.isDisposed () ) { ErrorDialog.openError ( PlatformUI.getWorkbench ().getActiveWorkbenchWindow ().getShell (), "Connection error", "Connection failed", status, IStatus.ERROR ); } } } ); } } private IStatus makeStatus ( final Connection connection, final ConnectionState state, final Throwable error ) { int severity; String message; if ( error != null ) { message = error.getMessage (); severity = IStatus.ERROR; } else if ( state == ConnectionState.CLOSED ) { message = "Connection closed"; severity = IStatus.WARNING; } else { message = String.format ( "State changed: %s", state ); severity = IStatus.INFO; } return new Status ( severity, Activator.PLUGIN_ID, message, error ); } @Override @SuppressWarnings ( "rawtypes" ) public Object getAdapter ( final Class adapter ) { logger.debug ( "Adapting: {}", adapter ); if ( adapter == ConnectionService.class ) { return this.connectionService; } else if ( adapter == IPropertySource.class ) { return new PropertySourceWrapper ( this ); } return null; } }