001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.security.remoting.jmx;
019
020 import java.io.ByteArrayOutputStream;
021 import java.io.IOException;
022 import java.io.ObjectOutputStream;
023 import java.net.URI;
024 import java.net.URISyntaxException;
025 import java.lang.reflect.InvocationHandler;
026 import java.lang.reflect.Method;
027
028 import org.activeio.Packet;
029 import org.activeio.RequestChannel;
030 import org.activeio.Service;
031 import org.activeio.SyncChannel;
032 import org.activeio.adapter.AsyncChannelToClientRequestChannel;
033 import org.activeio.adapter.PacketToInputStream;
034 import org.activeio.filter.PacketAggregatingSyncChannel;
035 import org.activeio.net.SocketMetadata;
036 import org.activeio.net.SocketSyncChannelFactory;
037 import org.activeio.packet.ByteArrayPacket;
038
039 import org.apache.geronimo.interceptor.Interceptor;
040 import org.apache.geronimo.interceptor.Invocation;
041 import org.apache.geronimo.interceptor.InvocationResult;
042 import org.apache.geronimo.kernel.ObjectInputStreamExt;
043
044 /**
045 * @version $Rev: 487175 $ $Date: 2006-12-14 03:10:31 -0800 (Thu, 14 Dec 2006) $
046 */
047 public class RequestChannelInterceptor implements Interceptor, InvocationHandler {
048
049 private final ClassLoader cl;
050 private final URI target;
051
052 public RequestChannelInterceptor(URI target, ClassLoader cl) {
053 this.target = target;
054 this.cl = cl;
055 }
056
057
058 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
059 Invocation invocation = new SerializableInvocation(method, args, proxy);
060 InvocationResult result = invoke(invocation);
061 if( result.isException() ) {
062 throw result.getException();
063 }
064 return result.getResult();
065 }
066
067 public InvocationResult invoke(Invocation invocation) throws Throwable {
068
069 ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
070 try {
071
072 RequestChannel channel = createRequestChannel(target);
073 Packet response;
074 try {
075 channel.start();
076 Packet request = serialize(invocation);
077 response = channel.request(request, Service.WAIT_FOREVER_TIMEOUT);
078 } finally {
079 channel.dispose();
080 }
081
082 Object obj;
083 try {
084 obj = deserialize(response, cl);
085 } catch ( ClassNotFoundException e ) {
086 // Weird.
087 Thread.currentThread().setContextClassLoader(RequestChannelInterceptor.class.getClassLoader());
088 response.clear();
089 obj = deserialize(response, cl);
090 }
091
092 // Are we demarshalling a thrown exception.
093 if (obj instanceof RequestChannelInterceptorInvoker.ThrowableWrapper) {
094 throw ((RequestChannelInterceptorInvoker.ThrowableWrapper) obj).exception;
095 }
096 return (InvocationResult)obj;
097
098 } finally {
099 Thread.currentThread().setContextClassLoader(originalLoader);
100 }
101 }
102
103 private static RequestChannel createRequestChannel(URI target) throws IOException, URISyntaxException {
104 SocketSyncChannelFactory factory = new SocketSyncChannelFactory();
105 SyncChannel channel = factory.openSyncChannel(target);
106 SocketMetadata socket = (SocketMetadata) channel.narrow(SocketMetadata.class);
107 socket.setTcpNoDelay(true);
108 return new AsyncChannelToClientRequestChannel(
109 new PacketAggregatingSyncChannel(
110 channel));
111 }
112
113 /**
114 * @param response
115 * @param cl
116 * @return
117 * @throws IOException
118 * @throws ClassNotFoundException
119 */
120 static public Object deserialize(Packet response, ClassLoader cl) throws IOException, ClassNotFoundException {
121 ObjectInputStreamExt is = new ObjectInputStreamExt(new PacketToInputStream(response), cl);
122 Object rc = is.readObject();
123 is.close();
124 return rc;
125 }
126
127 static public Packet serialize(Object object) throws IOException {
128 ByteArrayOutputStream baos = new ByteArrayOutputStream();
129 ObjectOutputStream oos = new ObjectOutputStream(baos);
130 oos.writeObject(object);
131 oos.close();
132 return new ByteArrayPacket(baos.toByteArray());
133 }
134 }