/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ package org.apache.openejb.client.hessian; import org.apache.openejb.OpenEJBRuntimeException; import org.apache.openejb.core.ivm.naming.ContextWrapper; import org.apache.openejb.util.reflection.Reflections; import javax.naming.Context; import javax.naming.Name; import javax.naming.NamingException; import javax.naming.spi.InitialContextFactory; import java.lang.reflect.Constructor; import java.util.Hashtable; // all is done by reflection to let the use provide hessian in the app public class HessianInitialContextFactory implements InitialContextFactory { public static final String API = "openejb.hessian.client.api"; public static final String FORCE_SERIALIZABLE = "openejb.hessian.client.force-serializable"; public static final String CHUNKED = "openejb.hessian.client.chunked"; public static final String DEBUG = "openejb.hessian.client.debug"; public static final String READ_TIMEOUT = "openejb.hessian.client.read-timeout"; public static final String CONNECT_TIMEOUT = "openejb.hessian.client.connect-timeout"; private static final Class<?>[] BOOLEAN_PARAM = new Class<?>[]{boolean.class}; private static final Class<?>[] LONG_PARAM = new Class<?>[]{long.class}; private static final Class<?>[] STRING_PARAM = new Class<?>[]{String.class}; private static final Class<?>[] CREATE_PARAM = new Class<?>[]{Class.class, String.class, ClassLoader.class}; @Override public Context getInitialContext(final Hashtable<?, ?> environment) throws NamingException { return new HessianContext(environment); } private static class HessianContext extends ContextWrapper { private final Hashtable<?, ?> environment; private final ClassLoader loader; private final String url; private final Class<?> api; private final boolean allowNonSerializable; private final String user; private final String password; private final boolean chunked; private final boolean debug; private final int readTimeout; private final int connectTimeout; private final Constructor<?> factoryConstructor; private final Constructor<?> serializerConstructor; public HessianContext(final Hashtable<?, ?> environment) { super(null); // will lead to NPE if used but shouldn't be used in practise this.environment = environment; String baseUrl = String.class.cast(environment.get(Context.PROVIDER_URL)); if (baseUrl == null) { throw new IllegalArgumentException("provider url should be set"); } if (!baseUrl.endsWith("/")) { baseUrl += '/'; } this.url = baseUrl; this.loader = Thread.currentThread().getContextClassLoader(); this.user = String.class.cast(environment.get(Context.SECURITY_PRINCIPAL)); this.password = String.class.cast(environment.get(Context.SECURITY_CREDENTIALS)); this.allowNonSerializable = environment.get(FORCE_SERIALIZABLE) == null || !"true".equals(String.class.cast(environment.get(FORCE_SERIALIZABLE))); this.chunked = environment.get(CHUNKED) == null || "true".equals(String.class.cast(environment.get(CHUNKED))); this.debug = "true".equals(String.class.cast(environment.get(DEBUG))); this.readTimeout = environment.get(READ_TIMEOUT) == null ? -1 : Integer.parseInt(String.class.cast(environment.get(READ_TIMEOUT))); this.connectTimeout = environment.get(CONNECT_TIMEOUT) == null ? -1 : Integer.parseInt(String.class.cast(environment.get(CONNECT_TIMEOUT))); final String apiClassname = String.class.cast(environment.get(API)); if (apiClassname != null) { try { api = loader.loadClass(apiClassname); } catch (final ClassNotFoundException e) { throw new OpenEJBRuntimeException(e); } } else { api = null; } try { factoryConstructor = loader.loadClass("com.caucho.hessian.client.HessianProxyFactory").getConstructor(ClassLoader.class); serializerConstructor = loader.loadClass("com.caucho.hessian.io.SerializerFactory").getConstructor(ClassLoader.class); } catch (final Exception e) { throw new OpenEJBRuntimeException(e); } } @Override public Object lookup(final Name name) throws NamingException { return lookup(name.toString()); } @Override public Object lookup(final String name) throws NamingException { try { final Object clientFactory = factoryConstructor.newInstance(loader); final Object factory = serializerConstructor.newInstance(loader); Reflections.invokeByReflection(factory, "setAllowNonSerializable", BOOLEAN_PARAM, new Object[]{allowNonSerializable}); Reflections.invokeByReflection(clientFactory, "setSerializerFactory", new Class<?>[]{serializerConstructor.getDeclaringClass()}, new Object[]{factory}); if (user != null) { Reflections.invokeByReflection(clientFactory, "setUser", STRING_PARAM, new Object[]{user}); Reflections.invokeByReflection(clientFactory, "setPassword", STRING_PARAM, new Object[]{password}); } Reflections.invokeByReflection(clientFactory, "setChunkedPost", BOOLEAN_PARAM, new Object[]{chunked}); Reflections.invokeByReflection(clientFactory, "setDebug", BOOLEAN_PARAM, new Object[]{debug}); Reflections.invokeByReflection(clientFactory, "setReadTimeout", LONG_PARAM, new Object[]{readTimeout}); Reflections.invokeByReflection(clientFactory, "setConnectTimeout", LONG_PARAM, new Object[]{connectTimeout}); final String completeUrl = url + name; try { if (api != null) { // just use it return Reflections.invokeByReflection(clientFactory, "create", CREATE_PARAM, new Object[]{api, completeUrl, loader}); } return Reflections.invokeByReflection(clientFactory, "create", STRING_PARAM, new Object[]{completeUrl}); } catch (final Exception e) { throw new NamingException(e.getMessage()); } } catch (final Exception e) { throw new OpenEJBRuntimeException(e); } } @Override public Hashtable<?, ?> getEnvironment() throws NamingException { return environment; } } }