/*
* 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.login.dialog;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.databinding.observable.Realm;
import org.openscada.core.ui.connection.login.LoginContext;
import org.openscada.core.ui.connection.login.LoginFactory;
import org.openscada.core.ui.connection.login.LoginHandler;
import org.openscada.core.ui.connection.login.StateListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ContextCreator
{
private final static Logger logger = LoggerFactory.getLogger ( ContextCreator.class );
private final LoginContext context;
private final ContextCreatorListener listener;
private final Realm realm;
private final Set<LoginHandler> handlers = new HashSet<LoginHandler> ();
private final ContextCreatorResultListener resultListener;
private boolean complete = false;
public ContextCreator ( final Realm realm, final LoginContext loginContext, final ContextCreatorListener listener, final ContextCreatorResultListener resultListener )
{
this.realm = realm;
this.context = loginContext;
this.listener = listener;
this.resultListener = resultListener;
}
public void start ( final String username, final String password )
{
for ( final LoginFactory factory : this.context.getFactories () )
{
try
{
final LoginHandler handler = factory.createHandler ( this.context, username, password );
if ( handler == null )
{
notifyStateChange ( factory.getClass ().getName (), "MISSING", null );
}
else
{
handler.setStateListener ( new StateListener () {
public void stateChanged ( final String connectionName, final String state, final Throwable error )
{
handleStateChange ( handler, connectionName, state, error );
}
} );
this.handlers.add ( handler );
}
}
catch ( final Throwable e )
{
for ( final LoginHandler handler : this.handlers )
{
handler.dispose ();
}
this.handlers.clear ();
notifyStateChange ( factory.getClass ().getName (), "FAILED", e );
}
}
if ( this.handlers.size () != this.context.getFactories ().size () )
{
// some handlers could not be created ... abort
for ( final LoginHandler handler : this.handlers )
{
handler.dispose ();
}
this.handlers.clear ();
notifyResult ( null );
}
else
{
// all got created now start the login process
for ( final LoginHandler handler : this.handlers )
{
handler.startLogin ();
}
}
}
protected synchronized void handleStateChange ( final LoginHandler handler, final String connectionName, final String state, final Throwable error )
{
notifyStateChange ( connectionName, state, error );
if ( isComplete () )
{
notifyResult ( allOk () ? new ArrayList<LoginHandler> ( this.handlers ) : null );
}
}
private boolean isComplete ()
{
logger.debug ( "Check complete" ); //$NON-NLS-1$
logger.debug ( "Handlers: {}", this.handlers ); //$NON-NLS-1$
for ( final LoginHandler handler : this.handlers )
{
if ( !handler.isComplete () )
{
return false;
}
}
return true;
}
private boolean allOk ()
{
for ( final LoginHandler handler : this.handlers )
{
if ( !handler.isOk () )
{
return false;
}
}
return true;
}
public void dispose ()
{
if ( !this.complete )
{
notifyResult ( null );
}
for ( final LoginHandler handler : this.handlers )
{
handler.dispose ();
}
this.handlers.clear ();
}
private void notifyStateChange ( final String handlerName, final String state, final Throwable error )
{
if ( this.listener != null && handlerName != null )
{
logger.info ( "Fire state change - connection: {}, state: {}, error: {}", new Object[] { handlerName, state, error } ); //$NON-NLS-1$
this.realm.asyncExec ( new Runnable () {
public void run ()
{
ContextCreator.this.listener.stateChanged ( handlerName, state, error );
}
} );
}
}
private void notifyResult ( final Collection<LoginHandler> result )
{
synchronized ( this )
{
if ( this.complete )
{
logger.warn ( "Somehow we wanted to send the result twice. Skipping!" ); //$NON-NLS-1$
return;
}
this.complete = true;
}
// remove all our connection state listeners
for ( final LoginHandler handler : this.handlers )
{
handler.setStateListener ( null );
}
if ( this.resultListener == null )
{
return;
}
// if we have a valid result the receive takes over control
if ( result != null )
{
this.handlers.clear ();
}
this.realm.asyncExec ( new Runnable () {
public void run ()
{
ContextCreator.this.resultListener.complete ( result );
}
} );
}
}