/* * DefaultRemoteServiceManager.java * * Copyright (C) 2010 Leo Osvald <leo.osvald@gmail.com> * * This file is part of SGLJ. * * SGLJ is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SGLJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. */ package org.sglj.service.rmi; import java.lang.reflect.Method; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.sglj.util.Pair; /** * The implementation of the {@link RemoteServiceManager} interface * which uses <tt>HashMap</tt> to provide efficient retrieval of services * by id.<br> * * @author Leo Osvald * @version 1.0 */ public class DefaultRemoteServiceManager<T extends RemoteService> extends AbstractRemoteServiceManager<T> { private final Map<Byte, T> serviceById; /** * A map of all remote methods in the registered services. * Each service has its own map which stores methods by * the pair ("method name", "argument count"). */ private final Map<Byte, Map<Pair<String, Integer>, Method>> methodMapByService; /** * This map cannot be initialized here (or in the constructor), since * it must be initialized before the call to super constructor from * which the {@link #registerRemoteMethod(byte, Method)} method * will be called. */ private Map<Byte, Map<Pair<String, Integer>, Method>> preMethodMapByService; @SuppressWarnings("unchecked") public <T2 extends T> DefaultRemoteServiceManager(T2... remoteServices) { super(remoteServices); HashMap<Byte, T> map = new HashMap<Byte, T>(); for (T service : availableServices()) { map.put(service.getId(), service); } this.serviceById = Collections.unmodifiableMap(map); // create method map from the map which (maybe) registered some services // it will be null if no remote services were registered methodMapByService = (preMethodMapByService == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(preMethodMapByService)); } @Override public T getService(byte serviceId) { return this.serviceById.get(serviceId); } @Override protected void registerRemoteMethod(byte serviceId, Method remoteMethod) { if (preMethodMapByService == null) { preMethodMapByService = new HashMap<Byte, Map<Pair<String,Integer>, Method>>(); } Map<Pair<String,Integer>, Method> methodMap = preMethodMapByService.get(serviceId); if (methodMap == null) { methodMap = new HashMap<Pair<String,Integer>,Method>(); preMethodMapByService.put(serviceId, methodMap); } methodMap.put(new Pair<String, Integer>(remoteMethod.getName(), remoteMethod.getParameterTypes().length), remoteMethod); } @Override public Method getRemoteMethod(byte serviceId, String methodName, int parameterCount) { Map<Pair<String,Integer>, Method> methodMap = methodMapByService .get(serviceId); if (methodMap != null) { return methodMap.get(new Pair<String, Integer>( methodName, parameterCount)); } return null; } }