001package jmri.implementation; 002 003import java.beans.PropertyChangeListener; 004import java.util.List; 005 006import jmri.*; 007 008/** 009 * A programmer which supports permissions. 010 * @author Daniel Bergqvist Copyright (C) 2025 011 */ 012public class PermissionProgrammer implements jmri.Programmer { 013 014 /** 015 * The minimum time to pass between requests to trigger an user request. 016 * During programming, JMRI might do thousands write requests, and to 017 * prevent that the user has to answer on each of these, this time needs 018 * to pass between two request to result in an user request to tell the 019 * user that permissions are denied. 020 */ 021 private static final long THROTTLE_USER_REQUEST_TIME = 3000; // time in milliseconds 022 023 private long _throttleUserRequestTime = 0L; 024 025 protected final Programmer _programmer; 026 027 public PermissionProgrammer(Programmer programmer) { 028 this._programmer = programmer; 029 } 030 031 protected boolean throttleUserRequest() { 032 long oldTime = _throttleUserRequestTime; 033 _throttleUserRequestTime = System.currentTimeMillis(); 034 return (_throttleUserRequestTime - oldTime) > THROTTLE_USER_REQUEST_TIME; 035 } 036 037 protected Permission getPermission() { 038 return PermissionsProgrammer.PERMISSION_PROGRAMMING_TRACK; 039 } 040 041 private boolean hasPermission() { 042 // Does the user has permission? 043 boolean hasPerm = InstanceManager.getDefault(PermissionManager.class) 044 .hasAtLeastPermission(getPermission(), 045 BooleanPermission.BooleanValue.TRUE); 046 047 if (!hasPerm && throttleUserRequest()) { 048 // Notify the user about lack of permission 049 InstanceManager.getDefault(PermissionManager.class) 050 .ensureAtLeastPermission(getPermission(), 051 BooleanPermission.BooleanValue.TRUE); 052 053 // Reset the time for throttle user request 054 throttleUserRequest(); 055 } 056 return hasPerm; 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 public void writeCV(String CV, int val, ProgListener p) throws ProgrammerException { 062 if (hasPermission()) { 063 _programmer.writeCV(CV, val, p); 064 } else { 065 notifyProgListenerEnd(p, 0, ProgListener.UnknownError); 066 } 067 } 068 069 /** {@inheritDoc} */ 070 @Override 071 public void readCV(String CV, ProgListener p) throws ProgrammerException { 072 if (hasPermission()) { 073 _programmer.readCV(CV, p); 074 } else { 075 notifyProgListenerEnd(p, 0, ProgListener.UnknownError); 076 } 077 } 078 079 /** {@inheritDoc} */ 080 @Override 081 public void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException { 082 if (hasPermission()) { 083 _programmer.confirmCV(CV, val, p); 084 } else { 085 notifyProgListenerEnd(p, 0, ProgListener.UnknownError); 086 } 087 } 088 089 /** {@inheritDoc} */ 090 @Override 091 public List<ProgrammingMode> getSupportedModes() { 092 return _programmer.getSupportedModes(); 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public void setMode(ProgrammingMode p) { 098 _programmer.setMode(p); 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public ProgrammingMode getMode() { 104 return _programmer.getMode(); 105 } 106 107 /** {@inheritDoc} */ 108 @Override 109 public boolean getCanRead() { 110 return _programmer.getCanRead(); 111 } 112 113 /** {@inheritDoc} */ 114 @Override 115 public boolean getCanRead(String addr) { 116 return _programmer.getCanRead(addr); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public boolean getCanWrite() { 122 return _programmer.getCanWrite(); 123 } 124 125 /** {@inheritDoc} */ 126 @Override 127 public boolean getCanWrite(String addr) { 128 return _programmer.getCanWrite(addr); 129 } 130 131 /** {@inheritDoc} */ 132 @Override 133 public WriteConfirmMode getWriteConfirmMode(String addr) { 134 return _programmer.getWriteConfirmMode(addr); 135 } 136 137 /** {@inheritDoc} */ 138 @Override 139 public void addPropertyChangeListener(PropertyChangeListener p) { 140 _programmer.addPropertyChangeListener(p); 141 } 142 143 /** {@inheritDoc} */ 144 @Override 145 public void removePropertyChangeListener(PropertyChangeListener p) { 146 _programmer.removePropertyChangeListener(p); 147 } 148 149 /** {@inheritDoc} */ 150 @Override 151 public String decodeErrorCode(int i) { 152 return _programmer.decodeErrorCode(i); 153 } 154 155 /** {@inheritDoc} */ 156 @Override 157 public Configurator getConfigurator() { 158 return _programmer.getConfigurator(); 159 } 160}