001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.wake.impl; 020 021import org.apache.reef.wake.Identifier; 022import org.apache.reef.wake.IdentifierFactory; 023import org.apache.reef.wake.remote.exception.RemoteRuntimeException; 024import org.apache.reef.wake.remote.impl.SocketRemoteIdentifier; 025 026import javax.inject.Inject; 027import java.lang.reflect.Constructor; 028import java.lang.reflect.InvocationTargetException; 029import java.util.HashMap; 030import java.util.Map; 031 032/** 033 * Default remote identifier factory that creates a specific remote identifier 034 * from a string representation 035 * <p> 036 * A string representation is broken into two parts type and type-specific details separated by "://" 037 * A remote identifier implementation should implement a constructor that accepts a string. 038 * The factory invokes a proper constructor by reflection. 039 */ 040public class DefaultIdentifierFactory implements IdentifierFactory { 041 042 // map between type and remote identifier class 043 private final Map<String, Class<? extends Identifier>> typeToClazzMap; 044 045 /** 046 * Constructs a default remote identifier factory. 047 */ 048 @Inject 049 public DefaultIdentifierFactory() { 050 typeToClazzMap = new HashMap<>(); 051 typeToClazzMap.put("socket", SocketRemoteIdentifier.class); 052 } 053 054 /** 055 * Constructs a default remote identifier factory. 056 * 057 * @param typeToClazzMap the map of type strings to classes of remote identifiers 058 */ 059 public DefaultIdentifierFactory(final Map<String, Class<? extends Identifier>> typeToClazzMap) { 060 this.typeToClazzMap = typeToClazzMap; 061 } 062 063 /** 064 * Creates a new remote identifier instance. 065 * 066 * @param str a string representation 067 * @return a remote identifier 068 * @throws RemoteRuntimeException 069 */ 070 @Override 071 public Identifier getNewInstance(final String str) { 072 final int index = str.indexOf("://"); 073 if (index < 0) { 074 throw new RemoteRuntimeException("Invalid name " + str); 075 } 076 final String type = str.substring(0, index); 077 final Class<? extends Identifier> clazz = typeToClazzMap.get(type); 078 final Class<?>[] argTypes = {String.class}; 079 final Constructor<? extends Identifier> constructor; 080 try { 081 constructor = clazz.getDeclaredConstructor(argTypes); 082 final Object[] args = new Object[1]; 083 args[0] = str.substring(index + 3); 084 return constructor.newInstance(args); 085 } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | 086 IllegalArgumentException | InvocationTargetException e) { 087 e.printStackTrace(); 088 throw new RemoteRuntimeException(e); 089 } 090 } 091 092}