org.ubiquity.mirror.impl.MirrorFactoryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.ubiquity.mirror.impl.MirrorFactoryImpl.java

Source

/*
 * Copyright 2012 ubiquity-copy
 *
 * 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.
 */
package org.ubiquity.mirror.impl;

import com.google.common.base.Objects;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import org.ubiquity.mirror.Mirror;
import org.ubiquity.mirror.MirrorFactory;
import org.ubiquity.util.ClassDefinition;
import org.ubiquity.util.SimpleClassLoader;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * Default factory for mirrors
 */
public final class MirrorFactoryImpl implements MirrorFactory {

    private final LoadingCache<MirrorKey, Mirror<?>> mirrorCache;

    final SimpleClassLoader loader;

    public MirrorFactoryImpl(final SimpleClassLoader loader) {
        this.loader = loader;
        this.mirrorCache = CacheBuilder.newBuilder().build(new CacheLoader<MirrorKey, Mirror<?>>() {
            @Override
            public Mirror<?> load(MirrorKey aKey) throws Exception {
                Collection<ClassDefinition> definitions = MirrorGenerator.generateMirror(aKey.mirrorHandledClass,
                        aKey.generics);
                Class<?> c = null;
                for (ClassDefinition def : definitions) {
                    c = loader.defineClass(def.getClassName().replace('/', '.'), def.getClassContent());
                }
                if (c != null) {
                    return (Mirror) c.newInstance();
                }
                return null;
            }
        });
        this.mirrorCache.put(new MirrorKey(Map.class, null), new MapMirror());
    }

    @Override
    public <T> Mirror<T> getMirror(Class<T> requestedClass) {
        return getMirror(requestedClass, null);
    }

    @Override
    public <T> Mirror<T> getMirror(Class<T> requestedClass, Map<String, Class<?>> generics) {
        try {
            Class<?> resolvedClass = requestedClass;
            if (Map.class.isAssignableFrom(requestedClass)) {
                resolvedClass = Map.class;
            }
            return (Mirror<T>) mirrorCache.get(new MirrorKey(resolvedClass, generics));
        } catch (ExecutionException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private static final class MirrorKey {
        final Class<?> mirrorHandledClass;
        final Map<String, Class<?>> generics;

        MirrorKey(Class<?> mirrorHandledClass, Map<String, Class<?>> generics) {
            this.generics = generics == null ? ImmutableMap.<String, Class<?>>of() : ImmutableMap.copyOf(generics);
            this.mirrorHandledClass = mirrorHandledClass;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null || obj.getClass() != getClass()) {
                return false;
            }
            MirrorKey other = (MirrorKey) obj;
            return this.mirrorHandledClass == other.mirrorHandledClass && this.generics.equals(other.generics);
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(this.mirrorHandledClass, this.generics);
        }
    }
}