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 synchronized void readCV(String CVname, ProgListener p, int startVal) throws jmri.ProgrammerException { 082 if (hasPermission()) { 083 _programmer.readCV(CVname, p, startVal); 084 } else { 085 notifyProgListenerEnd(p, 0, ProgListener.UnknownError); 086 } 087 } 088 089 /** {@inheritDoc} */ 090 @Override 091 public void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException { 092 if (hasPermission()) { 093 _programmer.confirmCV(CV, val, p); 094 } else { 095 notifyProgListenerEnd(p, 0, ProgListener.UnknownError); 096 } 097 } 098 099 /** {@inheritDoc} */ 100 @Override 101 public List<ProgrammingMode> getSupportedModes() { 102 return _programmer.getSupportedModes(); 103 } 104 105 /** {@inheritDoc} */ 106 @Override 107 public void setMode(ProgrammingMode p) { 108 _programmer.setMode(p); 109 } 110 111 /** {@inheritDoc} */ 112 @Override 113 public ProgrammingMode getMode() { 114 return _programmer.getMode(); 115 } 116 117 /** {@inheritDoc} */ 118 @Override 119 public boolean getCanRead() { 120 return _programmer.getCanRead(); 121 } 122 123 /** {@inheritDoc} */ 124 @Override 125 public boolean getCanRead(String addr) { 126 return _programmer.getCanRead(addr); 127 } 128 129 /** {@inheritDoc} */ 130 @Override 131 public boolean getCanWrite() { 132 return _programmer.getCanWrite(); 133 } 134 135 /** {@inheritDoc} */ 136 @Override 137 public boolean getCanWrite(String addr) { 138 return _programmer.getCanWrite(addr); 139 } 140 141 /** {@inheritDoc} */ 142 @Override 143 public WriteConfirmMode getWriteConfirmMode(String addr) { 144 return _programmer.getWriteConfirmMode(addr); 145 } 146 147 /** {@inheritDoc} */ 148 @Override 149 public void addPropertyChangeListener(PropertyChangeListener p) { 150 _programmer.addPropertyChangeListener(p); 151 } 152 153 /** {@inheritDoc} */ 154 @Override 155 public void removePropertyChangeListener(PropertyChangeListener p) { 156 _programmer.removePropertyChangeListener(p); 157 } 158 159 /** {@inheritDoc} */ 160 @Override 161 public String decodeErrorCode(int i) { 162 return _programmer.decodeErrorCode(i); 163 } 164 165 /** {@inheritDoc} */ 166 @Override 167 public Configurator getConfigurator() { 168 return _programmer.getConfigurator(); 169 } 170}