/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.server.headlessclient;
import java.rmi.RemoteException;
import javax.servlet.ServletRequest;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import com.servoy.j2db.ISessionClient;
import com.servoy.j2db.LocalActiveSolutionHandler;
import com.servoy.j2db.persistence.IActiveSolutionHandler;
import com.servoy.j2db.persistence.IDeveloperRepository;
import com.servoy.j2db.persistence.RepositoryException;
import com.servoy.j2db.persistence.RootObjectMetaData;
import com.servoy.j2db.persistence.Solution;
import com.servoy.j2db.scripting.IExecutingEnviroment;
import com.servoy.j2db.scripting.ScriptEngine;
import com.servoy.j2db.server.shared.ApplicationServerRegistry;
import com.servoy.j2db.server.shared.IApplicationServer;
import com.servoy.j2db.server.shared.IApplicationServerSingleton;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.Utils;
import com.servoy.j2db.util.xmlxport.IXMLImportUserChannel;
/**
* Factory for headless clients
* @author rgansevles
*/
@SuppressWarnings("nls")
public class HeadlessClientFactoryInternal
{
public static ISessionClient createHeadlessClient(String solutionname, String username, String password, Object[] solutionOpenMethodArgs) throws Exception
{
return createSessionBean(null, solutionname, username, password, solutionOpenMethodArgs);
}
public static ISessionClient createSessionBean(final ServletRequest req, final String solutionname, final String username, final String password,
final Object[] solutionOpenMethodArgs) throws Exception
{
final ISessionClient[] sc = { null };
final Exception[] exception = { null };
Runnable createSessionBeanRunner = new Runnable()
{
public void run()
{
try
{
IApplicationServerSingleton as = ApplicationServerRegistry.get();
boolean nodebug = false;
Object[] openArgs = solutionOpenMethodArgs;
if (solutionOpenMethodArgs != null && solutionOpenMethodArgs.length != 0 &&
"nodebug".equals(solutionOpenMethodArgs[solutionOpenMethodArgs.length - 1]))
{
nodebug = true;
openArgs = Utils.arraySub(solutionOpenMethodArgs, 0, solutionOpenMethodArgs.length - 1);
}
// When last entry in solutionOpenMethodArgs in "nodebug" a non-debugging client is created.
if (as.isDeveloperStartup() && !nodebug)
{
sc[0] = as.getDebugClientHandler().createDebugHeadlessClient(req, username, password, null, openArgs, solutionname);
}
else
{
sc[0] = new SessionClient(req, username, password, null, openArgs, solutionname);
}
sc[0].setUseLoginSolution(false);
sc[0].loadSolution(solutionname);
}
catch (Exception e)
{
exception[0] = e;
if (sc[0] != null)
{
try
{
sc[0].shutDown(true);
}
catch (Exception ex)
{
Debug.error(ex);
}
}
}
}
};
if (Context.getCurrentContext() == null)
{
createSessionBeanRunner.run();
}
else
{
// we are running from a javascript thread, probably developer or webclient, create the bean in a
// separate thread so that a new context will be created
Thread createSessionBeanThread = new Thread(createSessionBeanRunner, "createSessionBean"); //$NON-NLS-1$
createSessionBeanThread.start();
createSessionBeanThread.join();
}
if (exception[0] != null)
{
throw exception[0];
}
return sc[0];
}
public static ISessionClient createImportHookClient(final Solution importHookModule, final IXMLImportUserChannel channel) throws Exception
{
final String[] loadException = new String[1];
// assuming no login and no method args for import hooks
SessionClient sc = new SessionClient(null, null, null, null, null, importHookModule.getName())
{
@Override
protected IActiveSolutionHandler createActiveSolutionHandler()
{
IApplicationServer as = ApplicationServerRegistry.getService(IApplicationServer.class);
return new LocalActiveSolutionHandler(as, this)
{
@Override
protected Solution loadSolution(RootObjectMetaData solutionDef) throws RemoteException, RepositoryException
{
// grab the latest version (-1) not the active one, because the hook was not yet activated.
return (Solution)((IDeveloperRepository)getRepository()).getRootObject(solutionDef.getRootObjectId(), -1);
}
};
}
@Override
protected IExecutingEnviroment createScriptEngine()
{
return new ScriptEngine(this)
{
@Override
public Object executeFunction(Function f, Scriptable scope, Scriptable thisObject, Object[] args, boolean focusEvent, boolean throwException)
throws Exception
{
// always throw exception
return super.executeFunction(f, scope, thisObject, args, focusEvent, true);
}
};
}
@Override
public void reportError(String msg, Object detail)
{
super.reportError(msg, detail);
loadException[0] = msg;
if (detail instanceof Exception)
{
loadException[0] += " " + ((Exception)detail).getMessage();
}
}
};
sc.setUseLoginSolution(false);
String userName = channel.getImporterUsername();
if (userName != null)
{
// let the import hook client run with credentials from the logged in user from the admin page.
sc.getClientInfo().setUserUid(ApplicationServerRegistry.get().getUserManager().getUserUID(sc.getClientID(), userName));
sc.getClientInfo().setUserName(userName);
}
sc.setOutputChannel(channel);
sc.loadSolution(importHookModule.getName());
if (loadException[0] != null)
{
sc.shutDown(true);
throw new RepositoryException(loadException[0]);
}
return sc;
}
}