/* ================================================================== * DefaultAuthorizationManager.java - 8/06/2015 7:11:10 am * * Copyright 2007-2015 SolarNetwork.net Dev Team * * 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 net.solarnetwork.node.ocpp.auth; import java.util.List; import java.util.Locale; import java.util.Map; import net.solarnetwork.node.ocpp.Authorization; import net.solarnetwork.node.ocpp.AuthorizationDao; import net.solarnetwork.node.ocpp.AuthorizationManager; import net.solarnetwork.node.ocpp.support.CentralSystemServiceFactorySupport; import net.solarnetwork.node.settings.SettingSpecifier; import net.solarnetwork.node.settings.support.BasicToggleSettingSpecifier; import net.solarnetwork.util.OptionalService; import ocpp.v15.cs.AuthorizationStatus; import ocpp.v15.cs.AuthorizeRequest; import ocpp.v15.cs.AuthorizeResponse; /** * Default implementation of {@link AuthorizationManager}. This implementation * supports local caching of ID tags. * * @author matt * @version 1.0 */ public class DefaultAuthorizationManager extends CentralSystemServiceFactorySupport implements AuthorizationManager { private OptionalService<AuthorizationDao> authorizationDao; private boolean authorizeOnFailedCommunication = true; @Override public AuthorizationStatus authorize(String idTag) { Authorization auth = authorizationForTag(idTag); if ( isAuthorized(auth) ) { return auth.getStatus(); } else if ( isCachedAuthorizationValid(auth) ) { // no need to validate with central system return auth.getStatus(); } AuthorizeRequest req = new AuthorizeRequest(); req.setIdTag(idTag); AuthorizeResponse res = null; try { res = getCentralSystem().service().authorize(req, getCentralSystem().chargeBoxIdentity()); } catch ( RuntimeException e ) { log.warn("Exception authorizing {} with central system: {}", idTag, e.getMessage()); if ( authorizeOnFailedCommunication ) { return AuthorizationStatus.ACCEPTED; } throw e; } if ( res != null && res.getIdTagInfo() != null ) { auth = new Authorization(idTag, res.getIdTagInfo()); saveAuthorization(auth); return auth.getStatus(); } return AuthorizationStatus.INVALID; } /** * Return <em>true</em> if {@code auth} has an {@code expiryDate} whose date * is in the future. * * @param auth * The authorization to check (mey be <em>null</em>). * @return Cached validity flag. */ private boolean isCachedAuthorizationValid(Authorization auth) { return (auth != null && auth.getExpiryDate() != null && auth.getExpiryDate() .toGregorianCalendar().getTimeInMillis() > System.currentTimeMillis()); } private boolean isAuthorized(Authorization auth) { return (auth != null && auth.isAccepted()); } private Authorization authorizationForTag(String idTag) { AuthorizationDao dao = (authorizationDao != null ? authorizationDao.service() : null); if ( dao == null ) { return null; } return dao.getAuthorization(idTag); } private void saveAuthorization(Authorization auth) { AuthorizationDao dao = (authorizationDao != null ? authorizationDao.service() : null); if ( dao == null ) { return; } dao.storeAuthorization(auth); } // SettingSpecifierProvider @Override public String getSettingUID() { return "net.solarnetwork.node.ocpp.auth"; } @Override public String getDisplayName() { return "OCPP Authorization Manager"; } @Override public List<SettingSpecifier> getSettingSpecifiers() { List<SettingSpecifier> results = super.getSettingSpecifiers(); DefaultAuthorizationManager defaults = new DefaultAuthorizationManager(); results.add(new BasicToggleSettingSpecifier("authorizeOnFailedCommunication", defaults.authorizeOnFailedCommunication)); return results; } @Override protected String getInfoMessage(Locale locale) { AuthorizationDao dao = (authorizationDao != null ? authorizationDao.service() : null); if ( dao == null ) { return getMessageSource().getMessage("status.noDao", null, locale); } Map<AuthorizationStatus, Integer> statusCounts = dao.statusCounts(); if ( statusCounts.size() < 1 ) { return getMessageSource().getMessage("status.none", null, locale); } StringBuilder buf = new StringBuilder(); for ( Map.Entry<AuthorizationStatus, Integer> me : statusCounts.entrySet() ) { if ( buf.length() > 0 ) { buf.append("; "); } buf.append(me.getKey()).append(": ").append(me.getValue()); } return getMessageSource().getMessage("status.counts", new Object[] { buf.toString() }, locale); } public OptionalService<AuthorizationDao> getAuthorizationDao() { return authorizationDao; } public void setAuthorizationDao(OptionalService<AuthorizationDao> authorizationDao) { this.authorizationDao = authorizationDao; } /** * Get the authorize on communication failure setting. * * @return The setting value. Defaults to <em>true</em>. */ public boolean isAuthorizeOnFailedCommunication() { return authorizeOnFailedCommunication; } /** * Setting to allow authorization if there is a problem communicating with * the central system. * * @param authorizeOnFailedCommunication * <em>true</em> to authorize on communication failures, * <em>false</em> to reject */ public void setAuthorizeOnFailedCommunication(boolean authorizeOnFailedCommunication) { this.authorizeOnFailedCommunication = authorizeOnFailedCommunication; } }