Package com.abiquo.hypervisor.plugin.internal

Source Code of com.abiquo.hypervisor.plugin.internal.TryInvocationHandler$UnsupportedOp

/**
* Copyright (C) 2008 - Abiquo Holdings S.L. All rights reserved.
*
* Please see /opt/abiquo/tomcat/webapps/legal/ on Abiquo server
* or contact contact@abiquo.com for licensing information.
*/
package com.abiquo.hypervisor.plugin.internal;

import static com.abiquo.hypervisor.plugin.internal.function.Functions.METHOD_NAME;
import static com.google.common.base.Objects.firstNonNull;
import static com.google.common.collect.ImmutableSet.copyOf;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.transform;
import static java.util.Arrays.asList;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.abiquo.hypervisor.plugin.Pluggable;
import com.abiquo.hypervisor.plugin.UnsupportedOperation;
import com.abiquo.hypervisor.plugin.exception.ComputeException;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;

/**
* Handles automatically unsupported operations. Memoizes the operation.
*
* @author <a href="mailto:serafin.sedano@abiquo.com">Serafin Sedano</a>
*/
public class TryInvocationHandler implements InvocationHandler
{
    private static final Logger LOGGER = LoggerFactory.getLogger(TryInvocationHandler.class);

    private static final Set<String> ALL_METHODS = copyOf(transform(
        asList(Plugin.class.getMethods()), METHOD_NAME));

    private class UnsupportedOp
    {
        private final Set<String> types;

        private final Set<String> regions;

        UnsupportedOp(final String[] types, final String[] regions)
        {
            this.types = copyOf(firstNonNull(types, new String[0]));
            this.regions = copyOf(firstNonNull(regions, new String[0]));
        }
    }

    private final Map<String, UnsupportedOp> UNSUPPORTED_OPERATIONS;

    private final Pluggable target;

    private final String type;

    public TryInvocationHandler(final Pluggable target, final String type)
    {
        this.target = target;
        this.type = type; // Plugin manager rejects empty types
        UNSUPPORTED_OPERATIONS = operationsUnsupported(target);
    }

    @Override
    public Object invoke(final Object proxy, final Method method, final Object[] args)
        throws UnsupportedOperationException, ComputeException
    {
        if (target == null)
        {
            LOGGER.warn("checkOperationSupported: method {} unsupported for type {}", new Object[] {
            method.getName(), type});
            return false;
        }

        UnsupportedOp supported = UNSUPPORTED_OPERATIONS.get(method.getName());
        if (supported == null)
        {
            return true;
        }

        if (supported.types.isEmpty() && supported.regions.isEmpty())
        {
            return false;
        }

        if (supported.types.contains(type))
        {
            return false;
        }

        if (args != null && args.length == 1)
        {
            if (args[0] instanceof String)
            {
                String region = (String) args[0];
                if (supported.regions.contains(region))
                {
                    return false;
                }
            }
        }
        return true;

    }

    /** If method is not implemented or annotated with UnsupportedOperation is not added in the set. */
    private Map<String, UnsupportedOp> operationsUnsupported(final Pluggable plugin)
    {
        Builder<String, UnsupportedOp> builder = ImmutableMap.<String, UnsupportedOp> builder();
        if (target != null)
        {
            addUnsupported(plugin, builder);
            addNotImplemented(plugin, builder);
        }
        return builder.build();
    }

    private void addUnsupported(final Pluggable plugin, final Builder<String, UnsupportedOp> builder)
    {
        for (Method m : plugin.getClass().getMethods())
        {
            if (!m.isSynthetic() && !m.isBridge())
            {
                UnsupportedOperation uns = m.getAnnotation(UnsupportedOperation.class);
                if (uns != null)
                {
                    builder.put(m.getName(), new UnsupportedOp(uns.types(), uns.regions()));
                }
            }
        }
    }

    /**
     * All methods present in {@link Plugin} that are not present in <code>plugin</code> are added
     * as unsupported.
     */
    private void addNotImplemented(final Pluggable plugin,
        final Builder<String, UnsupportedOp> builder)
    {
        Iterable<String> notImplemented =
            filter(ALL_METHODS, Predicates.not(Predicates.in(transform(asList(plugin.getClass()
                .getMethods()), METHOD_NAME))));
        for (String method : notImplemented)
        {
            builder.put(method, new UnsupportedOp(null, null));
        }

    }
}
TOP

Related Classes of com.abiquo.hypervisor.plugin.internal.TryInvocationHandler$UnsupportedOp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.