/* * Copyright 2004-2009 the original author or authors. * * 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. */ package org.compass.core.support.session; import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.compass.core.Compass; import org.compass.core.CompassSession; import org.compass.core.spi.InternalCompassSession; /** * InvocationHandler for {@link org.compass.core.CompassSession}. Used * <b>within already transactional context</b> in order to simplify the usage * of CompassSession. With this wrapper, there is no need to call <code>openSession</code>, * or <code>close()</code> on the session. There is no need to use Compass transaction * API as well. * * @author kimchy */ public class CompassSessionTransactionalProxy implements InvocationHandler, Serializable { private Compass compass; /** * Constrcuts a new invocation handler based on the session. Allows for * proxing {@link org.compass.core.CompassSession} for simpler API usage * <b>within a transactional context</b>. * * @param compass The Compass instance to use for session creation */ public CompassSessionTransactionalProxy(Compass compass) { this.compass = compass; } /** * Creates a new proxied {@link org.compass.core.CompassSession} that can * be used within an already running transcational context without worrying * about session management API or transcation management API. * * @param compass The compass instance used to create the session * @return A proxied session for simpler session usage within an already running transactional context */ public static CompassSession newProxy(Compass compass) { return (CompassSession) Proxy.newProxyInstance( InternalCompassSession.class.getClassLoader(), new Class[]{InternalCompassSession.class}, new CompassSessionTransactionalProxy(compass)); } /** * Since Compass already does most of the session management, this wrapper around * {@link org.compass.core.CompassSession} invocation simply uses {@link org.compass.core.Compass#openSession()} * and invoke the appropiate method on the session returned. Compass will make sure that this is the correct * session within the context. */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("equals")) { // Only consider equal when proxies are identical. return proxy == args[0]; } else if (method.getName().equals("hashCode")) { // Use hashCode of Compass proxy. return hashCode(); } InternalCompassSession session = (InternalCompassSession) compass.openSession(); try { return method.invoke(session, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }