001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.console.securitymanager.realm; 018 019 import java.io.Serializable; 020 import java.io.InputStream; 021 import java.io.IOException; 022 import java.util.List; 023 import java.util.ArrayList; 024 import java.util.Properties; 025 import java.util.Iterator; 026 import java.util.Map; 027 import java.util.HashMap; 028 import java.util.Collections; 029 import java.util.Comparator; 030 import org.apache.commons.logging.Log; 031 import org.apache.commons.logging.LogFactory; 032 033 /** 034 * Describes an available login module, including how to create and configure it. 035 * Reads the list of available login modules from a properties file on the class path. 036 * 037 * @version $Rev: 476061 $ $Date: 2006-11-17 01:36:50 -0500 (Fri, 17 Nov 2006) $ 038 */ 039 public class MasterLoginModuleInfo implements Serializable { 040 private final static Log log = LogFactory.getLog(MasterLoginModuleInfo.class); 041 private static MasterLoginModuleInfo[] allModules; 042 private String name; 043 private String className; 044 private boolean testable = true; 045 private OptionInfo[] options = new OptionInfo[0]; 046 047 private MasterLoginModuleInfo(String name, String className) { 048 this.name = name; 049 this.className = className; 050 } 051 052 public OptionInfo[] getOptions() { 053 return options; 054 } 055 056 public Map getOptionMap() { 057 Map map = new HashMap(); 058 for (int i = 0; i < options.length; i++) { 059 OptionInfo info = options[i]; 060 map.put(info.getName(), info); 061 } 062 return map; 063 } 064 065 public String getName() { 066 return name; 067 } 068 069 public String getClassName() { 070 return className; 071 } 072 073 public boolean isTestable() { 074 return testable; 075 } 076 077 private void setTestable(boolean testable) { 078 this.testable = testable; 079 } 080 081 private void setOptions(OptionInfo[] options) { 082 this.options = options; 083 } 084 085 public static MasterLoginModuleInfo[] getAllModules() { 086 if(allModules == null) { 087 allModules = loadModules(); 088 } 089 return allModules; 090 } 091 092 private static MasterLoginModuleInfo[] loadModules() { 093 List list = new ArrayList(); 094 Map map = new HashMap(), fieldMap = new HashMap(); 095 InputStream in = MasterLoginModuleInfo.class.getResourceAsStream("/login-modules.properties"); 096 if(in == null) { 097 log.error("Unable to locate login module properties file"); 098 return null; 099 } 100 Properties props = new Properties(); 101 try { 102 props.load(in); 103 } catch (IOException e) { 104 log.error("Unable to read login module properties file", e); 105 } finally { 106 try { 107 in.close(); 108 } catch (java.io.IOException ignored) { 109 // ignore 110 } 111 } 112 for (Iterator it = props.keySet().iterator(); it.hasNext();) { 113 String key = (String) it.next(); 114 if(key.startsWith("module.")) { 115 String name = key.substring(7, key.indexOf('.', 7)); 116 MasterLoginModuleInfo info = (MasterLoginModuleInfo) map.get(name); 117 if(info == null) { 118 info = new MasterLoginModuleInfo(props.getProperty("module."+name+".name"), 119 props.getProperty("module."+name+".class")); 120 String test = props.getProperty("module."+name+".testable"); 121 if(test != null) { 122 info.setTestable(new Boolean(test.trim()).booleanValue()); 123 } 124 map.put(name, info); 125 list.add(info); 126 } 127 String prefix = "module."+name+".field."; 128 if(key.startsWith(prefix)) { 129 String fieldName = key.substring(prefix.length(), key.indexOf('.', prefix.length())); 130 List fields = (List) fieldMap.get(name); 131 if(fields == null) { 132 fields = new ArrayList(); 133 fieldMap.put(name, fields); 134 } 135 OptionInfo option = null; 136 for (int i = 0; i < fields.size(); i++) { 137 OptionInfo opt = (OptionInfo) fields.get(i); 138 if(opt.getName().equals(fieldName)) { 139 option = opt; 140 break; 141 } 142 } 143 if(option == null) { 144 option = new OptionInfo(fieldName, props.getProperty(prefix+fieldName+".displayName"), 145 props.getProperty(prefix+fieldName+".description")); 146 String test = props.getProperty(prefix+fieldName+".password"); 147 if(test != null) { 148 option.setPassword(true); 149 } 150 test = props.getProperty(prefix+fieldName+".length"); 151 if(test != null) { 152 option.setLength(Integer.parseInt(test.trim())); 153 } 154 test = props.getProperty(prefix+fieldName+".displayOrder"); 155 if(test != null) { 156 option.setDisplayOrder(Integer.parseInt(test.trim())); 157 } 158 test = props.getProperty(prefix+fieldName+".blankAllowed"); 159 if(test != null) { 160 option.setBlankAllowed("true".equalsIgnoreCase(test.trim())); 161 } 162 fields.add(option); 163 } 164 } 165 } 166 } 167 for (Iterator it = map.keySet().iterator(); it.hasNext();) { 168 String name = (String) it.next(); 169 MasterLoginModuleInfo info = (MasterLoginModuleInfo) map.get(name); 170 List fields = (List) fieldMap.get(name); 171 if(fields != null) { 172 Collections.sort(fields); 173 info.setOptions((OptionInfo[]) fields.toArray(new OptionInfo[fields.size()])); 174 } 175 } 176 Collections.sort(list, new Comparator() { 177 public int compare(Object o1, Object o2) { 178 MasterLoginModuleInfo m1 = (MasterLoginModuleInfo) o1, m2 = (MasterLoginModuleInfo) o2; 179 if(m1.getName().equals("Other")) { 180 return 1; 181 } else if(m2.getName().equals("Other")) { 182 return -1; 183 } else { 184 return m1.getName().compareTo(m2.getName()); 185 } 186 } 187 }); 188 return (MasterLoginModuleInfo[]) list.toArray(new MasterLoginModuleInfo[list.size()]); 189 } 190 191 public final static class OptionInfo implements Serializable, Comparable { 192 private final String name; 193 private final String displayName; 194 private final String description; 195 private boolean password = false; 196 private int length = 30; 197 private int displayOrder = 1; 198 private boolean blankAllowed = false; 199 200 public OptionInfo(String name, String displayName, String description) { 201 this.name = name; 202 this.displayName = displayName; 203 this.description = description; 204 } 205 206 public String getName() { 207 return name; 208 } 209 210 public String getDisplayName() { 211 return displayName; 212 } 213 214 public String getDescription() { 215 return description; 216 } 217 218 public boolean isPassword() { 219 return password; 220 } 221 222 public void setPassword(boolean password) { 223 this.password = password; 224 } 225 226 public int getLength() { 227 return length; 228 } 229 230 public void setLength(int length) { 231 this.length = length; 232 } 233 234 public int getDisplayOrder() { 235 return displayOrder; 236 } 237 238 public void setDisplayOrder(int displayOrder) { 239 this.displayOrder = displayOrder; 240 } 241 242 public int compareTo(Object o) { 243 return displayOrder - ((OptionInfo)o).displayOrder; 244 } 245 246 public boolean isBlankAllowed() { 247 return this.blankAllowed; 248 } 249 250 public void setBlankAllowed(boolean blankAllowed) { 251 this.blankAllowed = blankAllowed; 252 } 253 } 254 }