com.delphix.session.module.rmi.impl.RmiFactoryImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.delphix.session.module.rmi.impl.RmiFactoryImpl.java

Source

/**
 * 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.
 */

/**
 * Copyright (c) 2014 by Delphix. All rights reserved.
 */

package com.delphix.session.module.rmi.impl;

import com.delphix.appliance.server.exception.DelphixInterruptedException;
import com.delphix.appliance.server.util.ExceptionUtil;
import com.delphix.session.module.rmi.ObjectCreator;
import com.delphix.session.module.rmi.RmiFactory;
import com.delphix.session.module.rmi.RmiProtocolClient;
import com.delphix.session.module.rmi.RmiProtocolServer;
import com.delphix.session.module.rmi.protocol.MethodCallRequest;
import com.delphix.session.module.rmi.protocol.MethodCallResponse;
import com.delphix.session.module.rmi.protocol.ObjectDestroyRequest;
import com.delphix.session.service.ServiceNexus;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

public class RmiFactoryImpl implements RmiFactory, ApplicationContextAware {

    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context = context;
    }

    @Override
    public RmiProtocolClient createClient() {
        return new RmiProtocolClientImpl();
    }

    @Override
    public RmiProtocolServer createServer(ObjectCreator objectCreator) {
        return new RmiProtocolServerImpl(objectCreator);
    }

    @Override
    public RmiProtocolServer createServer() {
        return createServer(new ObjectCreator() {

            @Override
            public <T> T create(Class<T> type) {
                String[] names = context.getBeanNamesForType(type);
                if (names.length == 0) {
                    throw new RuntimeException("there is no spring bean of type " + type.getCanonicalName());
                } else if (names.length > 1) {
                    throw new RuntimeException(
                            "there is more than one spring bean of type " + type.getCanonicalName());
                }

                if (!context.isPrototype(names[0])) {
                    throw new RuntimeException(String.format("the spring bean '%s' of type '%s' is not a prototype",
                            names[0], type.getCanonicalName()));
                }

                return type.cast(context.getBean(names[0]));
            }
        });
    }

    @Override
    public <T> T createProxy(final Class<T> type, final ServiceNexus nexus, final UUID objectId) {
        Object proxy = Proxy.newProxyInstance(RmiFactoryImpl.class.getClassLoader(), new Class[] { type },
                new InvocationHandler() {
                    private RmiMethodOrdering ifm = new RmiMethodOrdering(type);

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if (args == null) {
                            args = new Object[0];
                        }

                        if (method.getName().equals("close") && args.length == 0) {
                            ObjectDestroyRequest request = new ObjectDestroyRequest();
                            request.setObjectId(objectId);

                            try {
                                nexus.execute(request).get();
                            } catch (InterruptedException e) {
                                throw new DelphixInterruptedException(e);
                            } catch (ExecutionException e) {
                                throw new RuntimeException(ExceptionUtil.unwrap(e));
                            }
                            return null;
                        } else {
                            MethodCallRequest request = new MethodCallRequest();
                            request.setObjectId(objectId);
                            request.setMethod(ifm.getPlacement(method));
                            request.setArguments(args);

                            MethodCallResponse response;
                            try {
                                response = (MethodCallResponse) nexus.execute(request).get();
                            } catch (InterruptedException e) {
                                throw new DelphixInterruptedException(e);
                            } catch (ExecutionException e) {
                                throw new RuntimeException(ExceptionUtil.unwrap(e));
                            }

                            if (response.getException()) {
                                throw ExceptionUtil.unwrap(new ExecutionException((Throwable) response.getValue()));
                            } else {
                                return response.getValue();
                            }
                        }
                    }
                });

        return type.cast(proxy);
    }
}