001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015-2016 ForgeRock AS. 015 */ 016package org.opends.server.tools; 017 018import java.util.ArrayList; 019import java.util.Iterator; 020import java.util.LinkedList; 021import java.util.List; 022import java.util.regex.Matcher; 023import java.util.regex.Pattern; 024 025import org.forgerock.opendj.config.AbstractManagedObjectDefinition; 026import org.forgerock.opendj.config.DefinedDefaultBehaviorProvider; 027import org.forgerock.opendj.config.ManagedObjectDefinition; 028import org.forgerock.opendj.server.config.client.BackendCfgClient; 029import org.forgerock.opendj.server.config.meta.PluggableBackendCfgDefn; 030import org.forgerock.opendj.server.config.server.BackendCfg; 031import org.opends.guitools.controlpanel.util.Utilities; 032 033/** 034 * Helper class for setup applications. It helps applications to provide a 035 * backend type choice to the user. 036 */ 037public class BackendTypeHelper 038{ 039 /** 040 * Filter the provided backend name by removing the backend suffix. 041 * 042 * @param dsCfgBackendName 043 * The backend name 044 * @return The backend name with the '-backend' suffix filtered out 045 */ 046 public static String filterSchemaBackendName(final String dsCfgBackendName) 047 { 048 final String cfgNameRegExp = "(.*)-backend.*"; 049 final Matcher regExpMatcher = Pattern.compile(cfgNameRegExp, Pattern.CASE_INSENSITIVE).matcher(dsCfgBackendName); 050 if (regExpMatcher.matches()) 051 { 052 return regExpMatcher.group(1); 053 } 054 055 return dsCfgBackendName; 056 } 057 058 /** Adaptor to allow backend type selection in UIs. */ 059 public static class BackendTypeUIAdapter 060 { 061 private final ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backend; 062 063 /** 064 * Create a new {@code BackendTypeUIAdapter}. 065 * 066 * @param backend 067 * The backend to adapt 068 */ 069 private BackendTypeUIAdapter(ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backend) 070 { 071 this.backend = backend; 072 } 073 074 /** 075 * Return a user friendly readable name for this backend. 076 * 077 * @return A user friendly readable name for this backend. 078 */ 079 @Override 080 public String toString() 081 { 082 return backend.getUserFriendlyName().toString(); 083 } 084 085 @Override 086 public boolean equals(Object obj) 087 { 088 return obj instanceof BackendTypeUIAdapter && ((BackendTypeUIAdapter) obj).toString().equals(toString()); 089 } 090 091 @Override 092 public int hashCode() 093 { 094 return toString().hashCode(); 095 } 096 097 /** 098 * Return the adapted backend object. 099 * 100 * @return The adapted backend object 101 */ 102 public ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> getBackend() 103 { 104 return backend; 105 } 106 } 107 108 private final List<ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>> backends; 109 110 /** Creates a new backend type helper. */ 111 @SuppressWarnings("unchecked") 112 public BackendTypeHelper() 113 { 114 Utilities.initializeConfigurationFramework(); 115 116 backends = new LinkedList<>(); 117 118 for (AbstractManagedObjectDefinition<?, ?> backendType : PluggableBackendCfgDefn.getInstance().getAllChildren()) 119 { 120 // Filtering out only the non-abstract backends to avoid users attempt to create abstract ones 121 if (backendType instanceof ManagedObjectDefinition) 122 { 123 final DefinedDefaultBehaviorProvider<String> defaultBehaviorProvider = 124 (DefinedDefaultBehaviorProvider<String>) backendType.getPropertyDefinition("java-class") 125 .getDefaultBehaviorProvider(); 126 final Iterator<String> defaultBackendClassNameIterator = defaultBehaviorProvider.getDefaultValues().iterator(); 127 if (!defaultBackendClassNameIterator.hasNext()) 128 { 129 return; 130 } 131 addToBackendListIfClassExists(defaultBackendClassNameIterator.next(), 132 (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) backendType); 133 } 134 } 135 } 136 137 private void addToBackendListIfClassExists(final String backendClassName, 138 final ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendToAdd) 139 { 140 try 141 { 142 Class.forName(backendClassName); 143 backends.add(backendToAdd); 144 } 145 catch (ClassNotFoundException ignored) 146 { 147 // The backend is not supported in the running version. 148 } 149 } 150 151 ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> retrieveBackendTypeFromName( 152 final String backendTypeStr) 153 { 154 for (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType : getBackendTypes()) 155 { 156 final String name = backendType.getName(); 157 if (backendTypeStr.equalsIgnoreCase(name) 158 || backendTypeStr.equalsIgnoreCase(filterSchemaBackendName(name))) 159 { 160 return backendType; 161 } 162 } 163 164 return null; 165 } 166 167 List<ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>> getBackendTypes() 168 { 169 return backends; 170 } 171 172 String getPrintableBackendTypeNames() 173 { 174 String backendTypeNames = ""; 175 for (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backend : getBackendTypes()) 176 { 177 backendTypeNames += filterSchemaBackendName(backend.getName()) + ", "; 178 } 179 180 if (backendTypeNames.isEmpty()) 181 { 182 return "Impossible to retrieve supported backend type list"; 183 } 184 185 return backendTypeNames.substring(0, backendTypeNames.length() - 2); 186 } 187 188 /** 189 * Return a list which contains all available backend type adapted for UI. 190 * 191 * @return a list which contains all available backend type adapted for UI 192 */ 193 public BackendTypeUIAdapter[] getBackendTypeUIAdaptors() 194 { 195 List<BackendTypeUIAdapter> adaptors = new ArrayList<>(); 196 for (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backend : getBackendTypes()) 197 { 198 adaptors.add(new BackendTypeUIAdapter(backend)); 199 } 200 201 return adaptors.toArray(new BackendTypeUIAdapter[adaptors.size()]); 202 } 203 204 /** 205 * Return a BackendTypeUIAdapter which adapts the backend identified by the 206 * provided backend name. 207 * 208 * @param backendName 209 * the backend name which identifies the backend to adapt. 210 * @return a BackendTypeUIAdapter which adapts the backend identified by the 211 * provided backend name. 212 */ 213 public static BackendTypeUIAdapter getBackendTypeAdapter(String backendName) 214 { 215 ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backend = 216 new BackendTypeHelper().retrieveBackendTypeFromName(backendName); 217 return backend != null ? getBackendTypeAdapter(backend) : null; 218 } 219 220 /** 221 * Return a BackendTypeUIAdapter which adapts the provided backend. 222 * 223 * @param backend 224 * the backend type to adapt. 225 * @return a BackendTypeUIAdapter which adapts the provided backend. 226 */ 227 private static BackendTypeUIAdapter getBackendTypeAdapter( 228 ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backend) 229 { 230 return new BackendTypeUIAdapter(backend); 231 } 232}