/* * Password Management Servlets (PWM) * http://www.pwm-project.org * * Copyright (c) 2006-2009 Novell, Inc. * Copyright (c) 2009-2017 The PWM Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package password.pwm.util; import password.pwm.AppProperty; import password.pwm.PwmConstants; import password.pwm.config.Configuration; import password.pwm.config.PwmSetting; import password.pwm.config.PwmSettingTemplate; import password.pwm.error.PwmError; import password.pwm.health.HealthMessage; import password.pwm.i18n.Message; import password.pwm.util.java.JavaHelper; import password.pwm.util.java.JsonUtil; import password.pwm.util.logging.PwmLogger; import password.pwm.ws.server.rest.bean.HealthRecord; import java.lang.reflect.Method; import java.util.Date; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeSet; public class CodeIntegrityChecker { private static final PwmLogger LOGGER = PwmLogger.forClass(CodeIntegrityChecker.class); private static final boolean DEBUG_FLAG = false; private static final Map<Method,Object[]> CHECK_ENUM_METHODS = new LinkedHashMap<>(); static { try { CHECK_ENUM_METHODS.put(PwmSetting.class.getMethod("getDescription", Locale.class), new Object[]{ PwmConstants.DEFAULT_LOCALE, }); CHECK_ENUM_METHODS.put(PwmSetting.class.getMethod("getDefaultValue", PwmSettingTemplate.class), new Object[]{ PwmSettingTemplate.DEFAULT, }); CHECK_ENUM_METHODS.put(AppProperty.class.getMethod("getDefaultValue"), new Object[]{ }); CHECK_ENUM_METHODS.put(PwmError.class.getMethod("getLocalizedMessage", Locale.class, Configuration.class, String[].class), new Object[]{ PwmConstants.DEFAULT_LOCALE, null, null, }); CHECK_ENUM_METHODS.put(Message.class.getMethod("getLocalizedMessage", Locale.class, Configuration.class, String[].class), new Object[]{ PwmConstants.DEFAULT_LOCALE, null, null, }); } catch (NoSuchMethodException e) { final String message = CodeIntegrityChecker.class.getSimpleName() + " error setting up static check components: " + e.getMessage(); System.err.print(message); System.out.print(message); System.exit(-1); } } public CodeIntegrityChecker() { } public Set<password.pwm.health.HealthRecord> checkResources() { final Set<password.pwm.health.HealthRecord> returnSet = new TreeSet<>(); returnSet.addAll(checkEnumMethods()); return returnSet; } private Set<password.pwm.health.HealthRecord> checkEnumMethods() { final Set<password.pwm.health.HealthRecord> returnSet = new LinkedHashSet<>(); for (final Method method : CHECK_ENUM_METHODS.keySet()) { final Object[] arguments = CHECK_ENUM_METHODS.get(method); returnSet.addAll(checkEnumMethods(method,arguments)); } return returnSet; } private Set<password.pwm.health.HealthRecord> checkEnumMethods(final Method enumMethod, final Object[] arguments) { final Set<password.pwm.health.HealthRecord> returnRecords = new LinkedHashSet<>(); try { final Method enumValuesMethod = enumMethod.getDeclaringClass().getMethod("values"); final Object[] enumValues = (Object[])enumValuesMethod.invoke(null); for (final Object enumValue : enumValues) { try { enumMethod.invoke(enumValue,arguments); } catch (Exception e) { final Throwable cause = e.getCause(); final String errorMsg = cause != null ? cause.getMessage() != null ? cause.getMessage() : cause.toString() : e.getMessage(); final StringBuilder methodName = new StringBuilder(); methodName.append(enumMethod.getDeclaringClass().getName()).append(".").append(enumValue.toString()).append(":").append(enumMethod.getName()).append("("); for (int i = 0; i < enumMethod.getParameterTypes().length; i++) { methodName.append(enumMethod.getParameterTypes()[i].getSimpleName()); if (i < (enumMethod.getParameterTypes().length-1)) { methodName.append(","); } } methodName.append(")"); returnRecords.add(password.pwm.health.HealthRecord.forMessage(HealthMessage.BrokenMethod, methodName.toString(), errorMsg)); } } } catch (Exception e) { e.printStackTrace(); } return returnRecords; } public String asPrettyJsonOutput() { final Map<String,Object> outputMap = new LinkedHashMap<>(); outputMap.put("information", PwmConstants.PWM_APP_NAME + " " + PwmConstants.SERVLET_VERSION + " IntegrityCheck " + JavaHelper.toIsoDate( new Date())); { final Set<HealthRecord> healthBeans = new LinkedHashSet<>(); for (final password.pwm.health.HealthRecord record : this.checkEnumMethods()) { healthBeans.add( HealthRecord.fromHealthRecord(record, PwmConstants.DEFAULT_LOCALE, null)); } outputMap.put("enumMethodHealthChecks", healthBeans); } return JsonUtil.serializeMap(outputMap, JsonUtil.Flag.PrettyPrint); } }