001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.kernel.modeshape; 019 020import static com.google.common.reflect.Reflection.newProxy; 021 022import java.lang.reflect.InvocationTargetException; 023import java.lang.reflect.Method; 024 025import javax.jcr.Session; 026 027import org.fcrepo.kernel.api.TxSession; 028 029import com.google.common.reflect.AbstractInvocationHandler; 030 031/** 032 * A dynamic proxy that wraps JCR sessions. It is aware of fcrepo transactions, 033 * and turns mutating methods (e.g. logout, session) into no-ops. Those no-op'ed 034 * methods should be called from the Transaction level instead. 035 * 036 * @author awoods 037 */ 038public class TxAwareSession extends AbstractInvocationHandler { 039 040 private final String txId; 041 042 private final Session session; 043 044 /** 045 * @param session a JCR session 046 * @param txID the transaction identifier 047 */ 048 public TxAwareSession(final Session session, final String txID) { 049 this.session = session; 050 this.txId = txID; 051 } 052 053 /** 054 * Wrap a JCR session with this dynamic proxy 055 * 056 * @param session a JCR session 057 * @param txId the transaction identifier 058 * @return a wrapped JCR session 059 */ 060 public static Session newInstance(final Session session, final String txId) { 061 return newProxy(TxSession.class, new TxAwareSession(session, txId)); 062 } 063 064 @Override 065 protected Object handleInvocation(final Object proxy, final Method method, final Object[] args) throws Throwable { 066 final String name = method.getName(); 067 if (name.equals("logout") || name.equals("save")) { 068 return null; 069 } else if (name.equals("getTxId")) { 070 return txId; 071 } else { 072 final Object invocationResult; 073 try { 074 invocationResult = method.invoke(session, args); 075 } catch (final InvocationTargetException e) { 076 throw e.getCause(); 077 } 078 if (name.equals("impersonate")) { 079 return newInstance((Session) invocationResult, txId); 080 } 081 return invocationResult; 082 } 083 } 084}