/*********************************************************************
* EJExecutor.java
* created on 09.07.2006 by netseeker
* $Source$
* $Date$
* $Revision$
*
* ====================================================================
*
* Copyright 2006 netseeker aka Michael Manske
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This file is part of the de.netseeker.ejoe.ext.crispy framework.
* For more information on the author, please see
* <http://www.manskes.de/>.
*
*********************************************************************/
package de.netseeker.ejoe.ext.crispy;
import java.lang.reflect.Method;
import java.util.Properties;
import net.sf.crispy.Executor;
import net.sf.crispy.InvocationException;
import net.sf.crispy.InvocationStrategy;
import de.netseeker.ejoe.EJClient;
import de.netseeker.ejoe.EJConstants;
import de.netseeker.ejoe.adapter.AdapterFactory;
import de.netseeker.ejoe.adapter.SerializeAdapter;
import de.netseeker.ejoe.request.RemotingRequest;
import de.netseeker.ejoe.util.ContentStringBuilder;
/**
* A dynamic proxy implementation for the great Crispy framework. EJExcecutor makes it possible to use EJOE as service
* within Crispy:
*
* <pre>
* Properties prop = new Properties();
* prop.put(Property.EXECUTOR_CLASS, EJExecutor.class.getName());
* prop.put(EJExecutor.EJOE_SERIALIZATION_ADAPTER, ObjectStreamAdapter.class.getName());
* prop.put(Property.REMOTE_URL_AND_PORT, "socket://localhost:12577");
* prop.put(EJExecutor.EJOE_USE_PERSISTENT_CONNECTION, Boolean.toString(true));
* //prop.put(EJExecutor.EJOE_IN_JVM, Boolean.toString(true));
* ServiceManager manager = new ServiceManager(prop);
* Echo e = (Echo) manager.createService(Echo.class);
* ...
* </pre>
*
* @author netseeker
* @since 0.3.9.1
* @see http://crispy.sourceforge.net/index.html
* @see de.netseeker.ejoe.test.crispy.EJCrispyTest
*/
public class EJExecutor extends Executor
{
/**
* Tells the underlying EJClient which SerializationAdapter should be used
*/
public static final String EJOE_SERIALIZATION_ADAPTER = "EJOE_SERIALIZATION_ADAPTER";
/**
* Tells the underlying EJClient if it should compress serialized objects when sending them through the socket
*/
public static final String EJOE_USE_COMPRESSION = "EJOE_USE_COMPRESSION";
/**
* Tells the underlying EJClient if it should request and use a persistent connection from the EJServer
*/
public static final String EJOE_USE_PERSISTENT_CONNECTION = "EJOE_USE_PERSISTENT_CONNECTION";
/**
* Tells the underlying EJClient how long it will wait for server response until it will assume a connection timeout
*/
public static final String EJOE_CONNECTION_TIMEOUT = "EJOE_CONNECTION_TIMEOUT";
/**
* Tells the underlying EJClient if it should try to use EJOE remote classloading feature, eg. load unknown response
* types from the server via the EJClassLoader
*/
public static final String EJOE_USE_REMOTE_CLASSLOADER = "EJOE_USE_REMOTE_CLASSLOADER";
/**
* Tells the underlying EJClient if it should use an existent In-JVM instance of EJServer, no socket connections
* will be used
*/
public static final String EJOE_IN_JVM = "EJOE_IN_JVM";
private EJClient _ejclient;
/*
* (non-Javadoc)
*
* @see net.sf.crispy.Executor#getDefaultUrlAndPort()
*/
public String getDefaultUrlAndPort()
{
return "socket://localhost:" + EJConstants.EJOE_PORT;
}
/*
* (non-Javadoc)
*
* @see net.sf.crispy.Executor#getDefaultInvocationStrategy()
*/
public InvocationStrategy getDefaultInvocationStrategy()
{
return new ClassAndMethodArrayInvocationStrategy();
}
/*
* (non-Javadoc)
*
* @see net.sf.crispy.Executor#execute(java.lang.Class, java.lang.Object, java.lang.reflect.Method,
* java.lang.Object[])
*/
public Object execute( Class pvProxyClass, Object pvProxy, Method pvMethod, Object[] pvArgs ) throws Exception
{
if ( _ejclient == null )
{
Properties props = getProperties();
String adapterKey = props.getProperty( EJOE_SERIALIZATION_ADAPTER, EJConstants.EJOE_DEFAULT_ADAPTER
.getName() );
boolean compression = Boolean
.valueOf( props.getProperty( EJOE_USE_COMPRESSION, Boolean.toString( false ) ) ).booleanValue();
boolean persistent = Boolean.valueOf(
props.getProperty( EJOE_USE_PERSISTENT_CONNECTION, Boolean
.toString( true ) ) ).booleanValue();
boolean classloading = Boolean.valueOf(
props.getProperty( EJOE_USE_REMOTE_CLASSLOADER, Boolean
.toString( false ) ) ).booleanValue();
boolean injvm = Boolean.valueOf( props.getProperty( EJOE_IN_JVM, Boolean.toString( false ) ) )
.booleanValue();
String address[] = getUrlAndPort().split( "://" );
boolean isHttp = address[0].equalsIgnoreCase( "http" );
if ( log.isDebugEnabled() )
{
log.debug( "EJOE Server address: " + ContentStringBuilder.toString( address ) );
log.debug( "Will use serialize adapter: " + adapterKey );
}
SerializeAdapter adapter = AdapterFactory.createAdapter( adapterKey );
int index = address[1].lastIndexOf( ':' );
String host = address[1].substring( 0, index );
String sPort = address[1].substring( index + 1 );
int port = Integer.parseInt( sPort );
_ejclient = new EJClient( host, port, adapter, persistent, isHttp, compression );
if ( classloading )
{
_ejclient.enableRemoteClassloading();
}
if ( props.getProperty( EJOE_CONNECTION_TIMEOUT ) != null )
{
int timeout = Integer.parseInt( props.getProperty( EJOE_CONNECTION_TIMEOUT ) );
_ejclient.setConnectionTimeout( timeout );
}
if ( injvm )
{
_ejclient.setInJVM( true );
}
}
Object ret = null;
RemotingRequest lvStrService = (RemotingRequest) getInvocationStrategy();
lvStrService.setArgs( pvArgs );
if ( log.isDebugEnabled() )
{
log.debug( "Invocation target: " + lvStrService.toString() );
}
try
{
ret = _ejclient.execute( lvStrService );
}
catch ( Exception e )
{
Throwable t = e;
if ( e.getCause() != null )
{
t = e.getCause();
}
throw new InvocationException( "Error by execute service: " + lvStrService.toString() + " -- "
+ t.getMessage(), t );
}
return ret;
}
}