mirror of
https://github.com/EssentialsX/Essentials.git
synced 2024-08-26 23:40:17 +02:00
Statemachine for installation wizard (WIP)
This commit is contained in:
parent
aa922c5b67
commit
9433acf689
1
EssentialsUpdate/nbproject/pmd.settings
Normal file
1
EssentialsUpdate/nbproject/pmd.settings
Normal file
|
@ -0,0 +1 @@
|
|||
DoNotUseThreads
|
|
@ -22,7 +22,11 @@ public class GetFile
|
|||
|
||||
public GetFile(final String urlString) throws MalformedURLException, IOException
|
||||
{
|
||||
final URL url = new URL(urlString);
|
||||
this(new URL(urlString));
|
||||
}
|
||||
|
||||
public GetFile(final URL url) throws IOException
|
||||
{
|
||||
this.connection = url.openConnection();
|
||||
this.connection.setConnectTimeout(1000);
|
||||
this.connection.setReadTimeout(5000);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.earth2me.essentials.update;
|
||||
|
||||
import com.earth2me.essentials.update.states.StateMachine;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -18,6 +19,7 @@ public class UpdateProcess extends PlayerListener
|
|||
private transient Player currentPlayer;
|
||||
private final transient Plugin plugin;
|
||||
private final transient UpdateCheck updateCheck;
|
||||
private transient StateMachine stateMachine;
|
||||
|
||||
public UpdateProcess(final Plugin plugin, final UpdateCheck updateCheck)
|
||||
{
|
||||
|
@ -37,7 +39,16 @@ public class UpdateProcess extends PlayerListener
|
|||
{
|
||||
if (event.getPlayer() == currentPlayer)
|
||||
{
|
||||
reactOnMessage(event.getMessage());
|
||||
final StateMachine.MachineResult result = stateMachine.reactOnMessage(event.getMessage());
|
||||
if (result == StateMachine.MachineResult.ABORT)
|
||||
{
|
||||
currentPlayer.sendMessage("Installation wizard aborted. You can restart it using /essentialsupdate.");
|
||||
currentPlayer = null;
|
||||
}
|
||||
if (result == StateMachine.MachineResult.DONE)
|
||||
{
|
||||
startWork();
|
||||
}
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
@ -71,9 +82,9 @@ public class UpdateProcess extends PlayerListener
|
|||
}
|
||||
}
|
||||
|
||||
void doAutomaticUpdate()
|
||||
public void doAutomaticUpdate()
|
||||
{
|
||||
final UpdatesDownloader downloader = new UpdatesDownloader();
|
||||
|
||||
final VersionInfo info = updateCheck.getNewVersionInfo();
|
||||
final List<String> changelog = info.getChangelog();
|
||||
Bukkit.getLogger().info("Essentials changelog " + updateCheck.getNewVersion().toString());
|
||||
|
@ -81,15 +92,15 @@ public class UpdateProcess extends PlayerListener
|
|||
{
|
||||
Bukkit.getLogger().info(" - " + line);
|
||||
}
|
||||
downloader.start(plugin.getServer().getUpdateFolderFile(), info);
|
||||
final UpdatesDownloader downloader = new UpdatesDownloader(plugin, info);
|
||||
downloader.start();
|
||||
}
|
||||
|
||||
void doManualUpdate()
|
||||
public void doManualUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onCommand(CommandSender sender)
|
||||
public void onCommand(final CommandSender sender)
|
||||
{
|
||||
if (sender instanceof Player && sender.hasPermission("essentials.install"))
|
||||
{
|
||||
|
@ -107,7 +118,12 @@ public class UpdateProcess extends PlayerListener
|
|||
sender.sendMessage("Your answers will be saved for a later update.");
|
||||
sender.sendMessage("Please answer the messages with yes or no, if not otherwise stated.");
|
||||
sender.sendMessage("Write bye/exit/quit if you want to exit the wizard at anytime.");
|
||||
|
||||
stateMachine = new StateMachine(plugin, currentPlayer, updateCheck.getNewVersionInfo());
|
||||
final StateMachine.MachineResult result = stateMachine.askQuestion();
|
||||
if (result == StateMachine.MachineResult.DONE)
|
||||
{
|
||||
startWork();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!currentPlayer.equals(sender))
|
||||
|
@ -121,8 +137,16 @@ public class UpdateProcess extends PlayerListener
|
|||
}
|
||||
}
|
||||
|
||||
private void reactOnMessage(String message)
|
||||
private void startWork()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
currentPlayer.sendMessage("Installation wizard done. Starting installation.");
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
stateMachine.startWork();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.File;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public class UpdatesDownloader
|
||||
public class UpdatesDownloader extends WorkListener
|
||||
{
|
||||
|
||||
UpdatesDownloader()
|
||||
public UpdatesDownloader(final Plugin plugin, final VersionInfo newVersionInfo)
|
||||
{
|
||||
|
||||
super(plugin, newVersionInfo);
|
||||
}
|
||||
|
||||
void start(File updateFolderFile, VersionInfo newVersion)
|
||||
public void start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkAbort(String message)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkDone(String message)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class VersionInfo
|
||||
|
@ -11,18 +12,18 @@ public class VersionInfo
|
|||
private final transient List<String> changelog;
|
||||
private final transient int minBukkit;
|
||||
private final transient int maxBukkit;
|
||||
private final transient List<ModuleInfo> modules;
|
||||
private final transient Map<String, ModuleInfo> modules;
|
||||
|
||||
public VersionInfo(final Configuration updateConfig, final String path)
|
||||
{
|
||||
changelog = updateConfig.getList(path + ".changelog", Collections.<String>emptyList());
|
||||
minBukkit = updateConfig.getInt(path + ".min-bukkit", 0);
|
||||
maxBukkit = updateConfig.getInt(path + ".max-bukkit", 0);
|
||||
modules = new ArrayList<ModuleInfo>();
|
||||
modules = new HashMap<String, ModuleInfo>();
|
||||
final String modulesPath = path + ".modules";
|
||||
for (String module : updateConfig.getKeys(false))
|
||||
{
|
||||
modules.add(new ModuleInfo(updateConfig, modulesPath + module));
|
||||
modules.put(module, new ModuleInfo(updateConfig, modulesPath + module));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +42,8 @@ public class VersionInfo
|
|||
return maxBukkit;
|
||||
}
|
||||
|
||||
public List<ModuleInfo> getModules()
|
||||
public Map<String, ModuleInfo> getModules()
|
||||
{
|
||||
return Collections.unmodifiableList(modules);
|
||||
return Collections.unmodifiableMap(modules);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.earth2me.essentials.update;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public abstract class WorkListener
|
||||
{
|
||||
public WorkListener(final Plugin plugin, final VersionInfo newVersionInfo)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.newVersionInfo = newVersionInfo;
|
||||
}
|
||||
private final transient Plugin plugin;
|
||||
private final transient VersionInfo newVersionInfo;
|
||||
|
||||
public final void onWorkAbort() {
|
||||
onWorkAbort(null);
|
||||
}
|
||||
|
||||
public abstract void onWorkAbort(String message);
|
||||
|
||||
public final void onWorkDone() {
|
||||
onWorkDone(null);
|
||||
}
|
||||
|
||||
public abstract void onWorkDone(String message);
|
||||
|
||||
public VersionInfo getNewVersionInfo()
|
||||
{
|
||||
return newVersionInfo;
|
||||
}
|
||||
|
||||
public Plugin getPlugin()
|
||||
{
|
||||
return plugin;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.earth2me.essentials.update.states;
|
||||
|
||||
import com.earth2me.essentials.update.WorkListener;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public abstract class AbstractState
|
||||
{
|
||||
private transient boolean abortion = false;
|
||||
|
||||
public abstract AbstractState getNextState();
|
||||
|
||||
/**
|
||||
* Check if we already know the answer, so the user does not have to answer the question.
|
||||
*
|
||||
* @return true, if the answer could be guessed.
|
||||
*/
|
||||
public boolean guessAnswer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user the question.
|
||||
* @param sender
|
||||
*/
|
||||
public abstract void askQuestion(Player sender);
|
||||
|
||||
/**
|
||||
* React on the answer and set internal variables
|
||||
* @param answer
|
||||
* @return true, if the answer could be recognized as a valid answer
|
||||
*/
|
||||
public abstract boolean reactOnAnswer(String answer);
|
||||
|
||||
public final AbstractState reactOnAnswer(final Player sender, final String answer)
|
||||
{
|
||||
final String trimmedAnswer = answer.trim();
|
||||
if (trimmedAnswer.equalsIgnoreCase("quit")
|
||||
|| trimmedAnswer.equalsIgnoreCase("bye")
|
||||
|| trimmedAnswer.equalsIgnoreCase("abort"))
|
||||
{
|
||||
abortion = true;
|
||||
return null;
|
||||
}
|
||||
final boolean found = reactOnAnswer(trimmedAnswer);
|
||||
if (found)
|
||||
{
|
||||
return getNextState();
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage("Answer not recognized.");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do something based on the answer, that the user gave.
|
||||
*/
|
||||
public abstract void doWork(WorkListener workListener);
|
||||
|
||||
public boolean isAbortion()
|
||||
{
|
||||
return abortion;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.earth2me.essentials.update.states;
|
||||
|
||||
|
||||
public abstract class AbstractYesNoState extends AbstractState
|
||||
{
|
||||
private boolean answer = false;
|
||||
private final transient AbstractState yesState;
|
||||
private final transient AbstractState noState;
|
||||
|
||||
public AbstractYesNoState(final AbstractState yesState, final AbstractState noState)
|
||||
{
|
||||
this.yesState = yesState;
|
||||
this.noState = noState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractState getNextState()
|
||||
{
|
||||
return answer ? yesState : noState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reactOnAnswer(final String answer)
|
||||
{
|
||||
if (answer.equalsIgnoreCase("yes")
|
||||
|| answer.equalsIgnoreCase("y"))
|
||||
{
|
||||
this.answer = true;
|
||||
return true;
|
||||
}
|
||||
if (answer.equalsIgnoreCase("no")
|
||||
|| answer.equalsIgnoreCase("n"))
|
||||
{
|
||||
this.answer = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getAnswer()
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected void setAnswer(final boolean answer)
|
||||
{
|
||||
this.answer = answer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.earth2me.essentials.update.states;
|
||||
|
||||
import com.earth2me.essentials.update.WorkListener;
|
||||
import com.earth2me.essentials.update.tasks.InstallChat;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public class EssentialsChat extends AbstractYesNoState
|
||||
{
|
||||
public EssentialsChat(final AbstractState next)
|
||||
{
|
||||
super(next, next);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean guessAnswer()
|
||||
{
|
||||
final Plugin plugin = Bukkit.getPluginManager().getPlugin("EssentialsChat");
|
||||
if (plugin != null)
|
||||
{
|
||||
setAnswer(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void askQuestion(final Player sender)
|
||||
{
|
||||
sender.sendMessage("Do you want to install EssentialsChat? (yes/no)");
|
||||
sender.sendMessage("Short descriptive text about what EssentialsChat does.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWork(final WorkListener listener)
|
||||
{
|
||||
if (getAnswer())
|
||||
{
|
||||
new InstallChat(listener).start();
|
||||
return;
|
||||
}
|
||||
listener.onWorkDone();
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package com.earth2me.essentials.update.states;
|
||||
|
||||
|
||||
public class Modules
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package com.earth2me.essentials.update.states;
|
||||
|
||||
import com.earth2me.essentials.update.WorkListener;
|
||||
import com.earth2me.essentials.update.VersionInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
||||
public class StateMachine extends WorkListener
|
||||
{
|
||||
public enum MachineResult
|
||||
{
|
||||
ABORT, WAIT, DONE
|
||||
}
|
||||
private final transient List<AbstractState> states = new ArrayList<AbstractState>();
|
||||
private transient AbstractState current;
|
||||
private final transient Player player;
|
||||
|
||||
public StateMachine(final Plugin plugin, final Player player, final VersionInfo newVersionInfo)
|
||||
{
|
||||
super(plugin, newVersionInfo);
|
||||
this.player = player;
|
||||
states.clear();
|
||||
final AbstractState state = new EssentialsChat(null);
|
||||
states.add(state);
|
||||
current = state;
|
||||
}
|
||||
|
||||
public MachineResult askQuestion()
|
||||
{
|
||||
while (current.guessAnswer())
|
||||
{
|
||||
current = current.getNextState();
|
||||
if (current == null)
|
||||
{
|
||||
return MachineResult.DONE;
|
||||
}
|
||||
}
|
||||
current.askQuestion(player);
|
||||
return MachineResult.WAIT;
|
||||
}
|
||||
|
||||
public MachineResult reactOnMessage(final String message)
|
||||
{
|
||||
final AbstractState next = current.reactOnAnswer(player, message);
|
||||
if (next == null)
|
||||
{
|
||||
if (current.isAbortion())
|
||||
{
|
||||
return MachineResult.ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MachineResult.DONE;
|
||||
}
|
||||
}
|
||||
current = next;
|
||||
return askQuestion();
|
||||
}
|
||||
private int position = 0;
|
||||
|
||||
public void startWork()
|
||||
{
|
||||
callStateWork();
|
||||
}
|
||||
|
||||
private void callStateWork()
|
||||
{
|
||||
if (position > states.size())
|
||||
{
|
||||
if (player.isOnline())
|
||||
{
|
||||
player.sendMessage("Installation done.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
final AbstractState state = states.get(position);
|
||||
state.doWork(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkAbort(final String message)
|
||||
{
|
||||
position = 0;
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (message != null && !message.isEmpty() && StateMachine.this.player.isOnline())
|
||||
{
|
||||
StateMachine.this.player.sendMessage(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkDone(final String message)
|
||||
{
|
||||
position++;
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (message != null && !message.isEmpty() && StateMachine.this.player.isOnline())
|
||||
{
|
||||
StateMachine.this.player.sendMessage(message);
|
||||
}
|
||||
StateMachine.this.callStateWork();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.earth2me.essentials.update.tasks;
|
||||
|
||||
import com.earth2me.essentials.update.WorkListener;
|
||||
|
||||
|
||||
public class InstallChat extends InstallModule
|
||||
{
|
||||
public InstallChat(final WorkListener listener)
|
||||
{
|
||||
super(listener, "EssentialsChat");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.earth2me.essentials.update.tasks;
|
||||
|
||||
import com.earth2me.essentials.update.GetFile;
|
||||
import com.earth2me.essentials.update.ModuleInfo;
|
||||
import com.earth2me.essentials.update.VersionInfo;
|
||||
import com.earth2me.essentials.update.WorkListener;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
|
||||
public class InstallModule implements Runnable, Task
|
||||
{
|
||||
protected final transient WorkListener listener;
|
||||
private final transient String moduleName;
|
||||
private final transient String fileName;
|
||||
|
||||
public InstallModule(final WorkListener listener, final String moduleName)
|
||||
{
|
||||
this(listener, moduleName, moduleName + ".jar");
|
||||
}
|
||||
|
||||
public InstallModule(final WorkListener listener, final String moduleName, final String fileName)
|
||||
{
|
||||
this.listener = listener;
|
||||
this.moduleName = moduleName;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
Bukkit.getScheduler().scheduleAsyncDelayedTask(listener.getPlugin(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final VersionInfo info = listener.getNewVersionInfo();
|
||||
final ModuleInfo module = info.getModules().get(moduleName);
|
||||
if (module == null)
|
||||
{
|
||||
listener.onWorkAbort("Module " + moduleName + " not found in VersionInfo.");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
final URL downloadUrl = module.getUrl();
|
||||
final GetFile getFile = new GetFile(downloadUrl);
|
||||
getFile.saveTo(new File(listener.getPlugin().getServer().getUpdateFolderFile(), fileName), module.getHash());
|
||||
listener.onWorkDone("Module " + moduleName + " downloaded.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Failed to download module " + moduleName + " to " + fileName, ex);
|
||||
listener.onWorkAbort("An error occured, please check your server log.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.earth2me.essentials.update.tasks;
|
||||
|
||||
|
||||
public interface Task
|
||||
{
|
||||
void start();
|
||||
}
|
Loading…
Reference in New Issue
Block a user