001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.kernel.modeshape; 017 018import org.fcrepo.kernel.api.TxSession; 019 020import static java.lang.reflect.Proxy.newProxyInstance; 021 022import java.lang.reflect.InvocationHandler; 023import java.lang.reflect.InvocationTargetException; 024import java.lang.reflect.Method; 025 026import javax.jcr.Session; 027 028/** 029 * A dynamic proxy that wraps JCR sessions. It is aware of fcrepo transactions, 030 * and turns mutating methods (e.g. logout, session) into no-ops. Those no-op'ed 031 * methods should be called from the Transaction level instead. 032 * 033 * @author awoods 034 */ 035public class TxAwareSession implements InvocationHandler { 036 037 private final String txId; 038 039 private final Session session; 040 041 /** 042 * @param session a JCR session 043 * @param txID the transaction identifier 044 */ 045 public TxAwareSession(final Session session, final String txID) { 046 this.session = session; 047 this.txId = txID; 048 } 049 050 /** 051 * Wrap a JCR session with this dynamic proxy 052 * 053 * @param session a JCR session 054 * @param txId the transaction identifier 055 * @return a wrapped JCR session 056 */ 057 public static Session newInstance(final Session session, final String txId) { 058 return (Session) newProxyInstance(session.getClass().getClassLoader(), 059 new Class[] {TxSession.class}, 060 new TxAwareSession(session, txId)); 061 } 062 063 @Override 064 public Object invoke(final Object proxy, final Method method, 065 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}