View Javadoc

1   /**********************************************************************
2    * EJExecutor.java
3    * created on 09.07.2006 by netseeker
4    * $Source$
5    * $Date$
6    * $Revision$
7    *
8    * ====================================================================
9    *
10   *  Copyright 2006 netseeker aka Michael Manske
11   *
12   *  Licensed under the Apache License, Version 2.0 (the "License");
13   *  you may not use this file except in compliance with the License.
14   *  You may obtain a copy of the License at
15   *
16   *      http://www.apache.org/licenses/LICENSE-2.0
17   *
18   *  Unless required by applicable law or agreed to in writing, software
19   *  distributed under the License is distributed on an "AS IS" BASIS,
20   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21   *  See the License for the specific language governing permissions and
22   *  limitations under the License.
23   * ====================================================================
24   *
25   * This file is part of the de.netseeker.ejoe.ext.crispy framework.
26   * For more information on the author, please see
27   * <http://www.manskes.de/>.
28   *
29   *********************************************************************/
30  
31  package de.netseeker.ejoe.ext.crispy;
32  
33  import java.lang.reflect.Method;
34  import java.util.Properties;
35  
36  import net.sf.crispy.Executor;
37  import net.sf.crispy.InvocationException;
38  import net.sf.crispy.InvocationStrategy;
39  import de.netseeker.ejoe.EJClient;
40  import de.netseeker.ejoe.EJConstants;
41  import de.netseeker.ejoe.adapter.AdapterFactory;
42  import de.netseeker.ejoe.adapter.SerializeAdapter;
43  import de.netseeker.ejoe.request.RemotingRequest;
44  import de.netseeker.ejoe.util.ContentStringBuilder;
45  
46  /***
47   * A dynamic proxy implementation for the great Crispy framework. EJExcecutor makes it possible to use EJOE as service
48   * within Crispy:
49   * 
50   * <pre>
51   *       Properties prop = new Properties(); 
52   *       prop.put(Property.EXECUTOR_CLASS, EJExecutor.class.getName()); 
53   *       prop.put(EJExecutor.EJOE_SERIALIZATION_ADAPTER, ObjectStreamAdapter.class.getName());
54   *       prop.put(Property.REMOTE_URL_AND_PORT, &quot;socket://localhost:12577&quot;); 
55   *    	 prop.put(EJExecutor.EJOE_USE_PERSISTENT_CONNECTION, Boolean.toString(true));
56   *       //prop.put(EJExecutor.EJOE_IN_JVM, Boolean.toString(true)); 
57   *       ServiceManager manager = new ServiceManager(prop); 
58   *       Echo e = (Echo) manager.createService(Echo.class);
59   *       ...
60   * </pre>
61   * 
62   * @author netseeker
63   * @since 0.3.9.1
64   * @see http://crispy.sourceforge.net/index.html
65   * @see de.netseeker.ejoe.test.crispy.EJCrispyTest
66   */
67  public class EJExecutor extends Executor
68  {
69      /***
70       * Tells the underlying EJClient which SerializationAdapter should be used
71       */
72      public static final String EJOE_SERIALIZATION_ADAPTER     = "EJOE_SERIALIZATION_ADAPTER";
73  
74      /***
75       * Tells the underlying EJClient if it should compress serialized objects when sending them through the socket
76       */
77      public static final String EJOE_USE_COMPRESSION           = "EJOE_USE_COMPRESSION";
78  
79      /***
80       * Tells the underlying EJClient if it should request and use a persistent connection from the EJServer
81       */
82      public static final String EJOE_USE_PERSISTENT_CONNECTION = "EJOE_USE_PERSISTENT_CONNECTION";
83  
84      /***
85       * Tells the underlying EJClient how long it will wait for server response until it will assume a connection timeout
86       */
87      public static final String EJOE_CONNECTION_TIMEOUT        = "EJOE_CONNECTION_TIMEOUT";
88  
89      /***
90       * Tells the underlying EJClient if it should try to use EJOE remote classloading feature, eg. load unknown response
91       * types from the server via the EJClassLoader
92       */
93      public static final String EJOE_USE_REMOTE_CLASSLOADER    = "EJOE_USE_REMOTE_CLASSLOADER";
94  
95      /***
96       * Tells the underlying EJClient if it should use an existent In-JVM instance of EJServer, no socket connections
97       * will be used
98       */
99      public static final String EJOE_IN_JVM                    = "EJOE_IN_JVM";
100 
101     private EJClient           _ejclient;
102 
103     /*
104      * (non-Javadoc)
105      * 
106      * @see net.sf.crispy.Executor#getDefaultUrlAndPort()
107      */
108     public String getDefaultUrlAndPort()
109     {
110         return "socket://localhost:" + EJConstants.EJOE_PORT;
111     }
112 
113     /*
114      * (non-Javadoc)
115      * 
116      * @see net.sf.crispy.Executor#getDefaultInvocationStrategy()
117      */
118     public InvocationStrategy getDefaultInvocationStrategy()
119     {
120         return new ClassAndMethodArrayInvocationStrategy();
121     }
122 
123     /*
124      * (non-Javadoc)
125      * 
126      * @see net.sf.crispy.Executor#execute(java.lang.Class, java.lang.Object, java.lang.reflect.Method,
127      *      java.lang.Object[])
128      */
129     public Object execute( Class pvProxyClass, Object pvProxy, Method pvMethod, Object[] pvArgs ) throws Exception
130     {
131         if ( _ejclient == null )
132         {
133             Properties props = getProperties();
134             String adapterKey = props.getProperty( EJOE_SERIALIZATION_ADAPTER, EJConstants.EJOE_DEFAULT_ADAPTER
135                     .getName() );
136             boolean compression = Boolean
137                     .valueOf( props.getProperty( EJOE_USE_COMPRESSION, Boolean.toString( false ) ) ).booleanValue();
138             boolean persistent = Boolean.valueOf(
139                                                   props.getProperty( EJOE_USE_PERSISTENT_CONNECTION, Boolean
140                                                           .toString( true ) ) ).booleanValue();
141             boolean classloading = Boolean.valueOf(
142                                                     props.getProperty( EJOE_USE_REMOTE_CLASSLOADER, Boolean
143                                                             .toString( false ) ) ).booleanValue();
144 
145             boolean injvm = Boolean.valueOf( props.getProperty( EJOE_IN_JVM, Boolean.toString( false ) ) )
146                     .booleanValue();
147 
148             String address[] = getUrlAndPort().split( "://" );
149             boolean isHttp = address[0].equalsIgnoreCase( "http" );
150 
151             if ( log.isDebugEnabled() )
152             {
153                 log.debug( "EJOE Server address: " + ContentStringBuilder.toString( address ) );
154                 log.debug( "Will use serialize adapter: " + adapterKey );
155             }
156 
157             SerializeAdapter adapter = AdapterFactory.createAdapter( adapterKey );
158 
159             int index = address[1].lastIndexOf( ':' );
160             String host = address[1].substring( 0, index );
161             String sPort = address[1].substring( index + 1 );
162             int port = Integer.parseInt( sPort );
163             _ejclient = new EJClient( host, port, adapter, persistent, isHttp, compression );
164 
165             if ( classloading )
166             {
167                 _ejclient.enableRemoteClassloading();
168             }
169 
170             if ( props.getProperty( EJOE_CONNECTION_TIMEOUT ) != null )
171             {
172                 int timeout = Integer.parseInt( props.getProperty( EJOE_CONNECTION_TIMEOUT ) );
173                 _ejclient.setConnectionTimeout( timeout );
174             }
175 
176             if ( injvm )
177             {
178                 _ejclient.setInJVM( true );
179             }
180         }
181 
182         Object ret = null;
183         RemotingRequest lvStrService = (RemotingRequest) getInvocationStrategy();
184         lvStrService.setArgs( pvArgs );
185 
186         if ( log.isDebugEnabled() )
187         {
188             log.debug( "Invocation target: " + lvStrService.toString() );
189         }
190 
191         try
192         {
193             ret = _ejclient.execute( lvStrService );
194         }
195         catch ( Exception e )
196         {
197             Throwable t = e;
198             if ( e.getCause() != null )
199             {
200                 t = e.getCause();
201             }
202 
203             throw new InvocationException( "Error by execute service: " + lvStrService.toString() + " -- "
204                     + t.getMessage(), t );
205         }
206 
207         return ret;
208     }
209 }