Java tutorial
/* * 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 3 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, see <http://www.gnu.org/licenses/>. */ package com.l2jfree.gameserver.model.restriction; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; import javolution.util.FastMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.l2jfree.L2DatabaseFactory; import com.l2jfree.gameserver.ThreadPoolManager; import com.l2jfree.gameserver.gameobjects.L2Player; import com.l2jfree.gameserver.model.world.L2World; /** * @author Noctarius */ public final class ObjectRestrictions { // Restrictions SQL String Definitions: private static final String RESTORE_RESTRICTIONS = "SELECT obj_Id, type, delay, message FROM obj_restrictions"; private static final String DELETE_RESTRICTIONS = "DELETE FROM obj_restrictions"; private static final String INSERT_RESTRICTIONS = "INSERT INTO obj_restrictions (`obj_Id`, `type`, `delay`, `message`) VALUES (?, ?, ?, ?)"; private static final Log _log = LogFactory.getLog(ObjectRestrictions.class); private static final ObjectRestrictions _instance = new ObjectRestrictions(); public static ObjectRestrictions getInstance() { return _instance; } private final Map<Integer, EnumSet<AvailableRestriction>> _restrictionList = new FastMap<Integer, EnumSet<AvailableRestriction>>(); private final Map<Integer, List<PausedTimedEvent>> _pausedActions = new FastMap<Integer, List<PausedTimedEvent>>(); private final Map<Integer, List<TimedRestrictionAction>> _runningActions = new FastMap<Integer, List<TimedRestrictionAction>>(); private ObjectRestrictions() { _log.info("ObjectRestrictions: loading..."); int count = 0; Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement(RESTORE_RESTRICTIONS); ResultSet rset = statement.executeQuery(); while (rset.next()) { final Integer objId = rset.getInt("obj_Id"); final AvailableRestriction type = AvailableRestriction.forName(rset.getString("type")); final int delay = rset.getInt("delay"); final String message = rset.getString("message"); switch (delay) { case -1: addRestriction(objId, type); break; default: timedRemoveRestriction(objId, type, delay, message); break; } count++; } rset.close(); statement.close(); } catch (SQLException e) { _log.warn("", e); } finally { L2DatabaseFactory.close(con); } for (Integer objectId : _runningActions.keySet()) pauseTasks(objectId); _log.info("ObjectRestrictions: loaded " + count + " restrictions."); } public void shutdown() { System.out.println("ObjectRestrictions: storing started:"); Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); // Clean up old table data PreparedStatement statement = con.prepareStatement(DELETE_RESTRICTIONS); statement.execute(); statement.close(); System.out.println("ObjectRestrictions: storing permanent restrictions."); // Store permanent restrictions for (Entry<Integer, EnumSet<AvailableRestriction>> entry : _restrictionList.entrySet()) { for (AvailableRestriction restriction : entry.getValue()) { statement = con.prepareStatement(INSERT_RESTRICTIONS); statement.setInt(1, entry.getKey()); statement.setString(2, restriction.name()); statement.setLong(3, -1); statement.setString(4, ""); statement.execute(); statement.close(); } } System.out.println("ObjectRestrictions: storing paused events."); // Store paused restriction events for (Entry<Integer, List<PausedTimedEvent>> entry : _pausedActions.entrySet()) { for (PausedTimedEvent paused : entry.getValue()) { statement = con.prepareStatement(INSERT_RESTRICTIONS); statement.setInt(1, entry.getKey()); statement.setString(2, paused.getAction().getRestriction().name()); statement.setLong(3, paused.getRemainingTime()); statement.setString(4, paused.getAction().getMessage()); statement.execute(); statement.close(); } } System.out.println("ObjectRestrictions: stopping and storing running events."); // Store running restriction events for (Entry<Integer, List<TimedRestrictionAction>> entry : _runningActions.entrySet()) { for (TimedRestrictionAction action : entry.getValue()) { // Shutdown task action.getTask().cancel(true); statement = con.prepareStatement(INSERT_RESTRICTIONS); statement.setInt(1, entry.getKey()); statement.setString(2, action.getRestriction().name()); statement.setLong(3, action.getRemainingTime()); statement.setString(4, action.getMessage()); statement.execute(); statement.close(); } } } catch (SQLException e) { e.printStackTrace(); } finally { L2DatabaseFactory.close(con); } System.out.println("ObjectRestrictions: All data saved."); } /** * Adds a restriction on startup * * @param objId * @param restriction */ private void addRestriction(Integer objId, AvailableRestriction restriction) { EnumSet<AvailableRestriction> set = _restrictionList.get(objId); if (set == null) _restrictionList.put(objId, set = EnumSet.noneOf(AvailableRestriction.class)); if (set.add(restriction)) { final L2Player player = L2World.getInstance().findPlayer(objId); if (player != null) restriction.activatedOn(player); } } /** * Adds a restriction without timelimit * * @param owner * @param restriction * @throws RestrictionBindClassException */ public void addRestriction(L2Player owner, AvailableRestriction restriction) { if (owner == null) return; addRestriction(owner.getObjectId(), restriction); } /** * Removes a restriction * * @param objId * @param restriction */ public void removeRestriction(Integer objId, AvailableRestriction restriction) { final EnumSet<AvailableRestriction> set = _restrictionList.get(objId); if (set != null) { if (set.remove(restriction)) { final L2Player player = L2World.getInstance().findPlayer(objId); if (player != null) restriction.deactivatedOn(player); } } final List<TimedRestrictionAction> runningActions = _runningActions.get(objId); if (runningActions != null) { for (Iterator<TimedRestrictionAction> iter = runningActions.iterator(); iter.hasNext();) { TimedRestrictionAction action = iter.next(); if (action.getRestriction() == restriction) { action.getTask().cancel(true); iter.remove(); } } } final List<PausedTimedEvent> pausedActions = _pausedActions.get(objId); if (pausedActions != null) { for (Iterator<PausedTimedEvent> iter = pausedActions.iterator(); iter.hasNext();) { PausedTimedEvent paused = iter.next(); if (paused.getAction().getRestriction() == restriction) { iter.remove(); } } } } /** * Removes a restriction * * @param owner * @param restriction */ public void removeRestriction(L2Player owner, AvailableRestriction restriction) { if (owner == null) return; removeRestriction(owner.getObjectId(), restriction); } /** * Checks if restriction is underway * * @param owner * @param restriction * @return */ public boolean checkRestriction(L2Player owner, AvailableRestriction restriction) { if (owner == null) return false; final EnumSet<AvailableRestriction> set = _restrictionList.get(owner.getObjectId()); if (set == null) return false; return set.contains(restriction); } /** * Schedules a new RemoveRestriction event without info message * * @param objId * @param restriction * @param delay */ public void timedRemoveRestriction(Integer objId, AvailableRestriction restriction, long delay) { timedRemoveRestriction(objId, restriction, delay, null); } /** * Schedules a new RemoveRestriction event with info message * * @param objId * @param restriction * @param delay * @param message */ public void timedRemoveRestriction(Integer objId, AvailableRestriction restriction, long delay, String message) { new TimedRestrictionAction(objId, restriction, delay, message); } /** * Adds a new active scheduled task * * @param objId * @param action */ private void addTask(Integer objId, TimedRestrictionAction action) { List<TimedRestrictionAction> list = _runningActions.get(objId); if (list == null) _runningActions.put(objId, list = new ArrayList<TimedRestrictionAction>()); if (!list.contains(action)) list.add(action); } private void removeTask(Integer objId, TimedRestrictionAction action) { List<TimedRestrictionAction> list = _runningActions.get(objId); if (list != null) list.remove(action); } /** * Adds a new paused scheduled task * * @param objId * @param action */ private void addPausedTask(Integer objId, PausedTimedEvent action) { List<PausedTimedEvent> list = _pausedActions.get(objId); if (list == null) _pausedActions.put(objId, list = new ArrayList<PausedTimedEvent>()); if (!list.contains(action)) list.add(action); } /** * Pauses tasks on player logout * * @param objId */ public void pauseTasks(Integer objId) { final List<TimedRestrictionAction> list = _runningActions.remove(objId); if (list == null || list.isEmpty()) return; for (TimedRestrictionAction action : list) action.pause(); } /** * Resumes tasks on player login * * @param objId */ public void resumeTasks(Integer objId) { final List<PausedTimedEvent> list = _pausedActions.remove(objId); if (list == null || list.isEmpty()) return; for (PausedTimedEvent paused : list) paused.activate(); } private final class TimedRestrictionAction implements Runnable { private final Integer _objId; private final AvailableRestriction _restriction; private final long _delay; private final String _message; private final long _starttime = System.currentTimeMillis(); private final ScheduledFuture<?> _task; private TimedRestrictionAction(Integer objId, AvailableRestriction restriction, long delay, String message) { _objId = objId; _restriction = restriction; _delay = delay; _message = message; _task = ThreadPoolManager.getInstance().schedule(this, delay); addTask(objId, this); } @Override public void run() { removeTask(getObjectId(), this); removeRestriction(getObjectId(), getRestriction()); if (getMessage() != null) { final L2Player owner = L2World.getInstance().findPlayer(getObjectId()); if (owner != null) owner.sendMessage(getMessage()); } } private void pause() { // Cancel active task getTask().cancel(true); // Save PausedEventObject new PausedTimedEvent(this); } private Integer getObjectId() { return _objId; } private AvailableRestriction getRestriction() { return _restriction; } private String getMessage() { return _message; } private long getDelay() { return _delay; } private long getRemainingTime() { return getDelay() - (System.currentTimeMillis() - _starttime); } private ScheduledFuture<?> getTask() { return _task; } } private final class PausedTimedEvent { private final TimedRestrictionAction _action; private final long _remainingTime; private PausedTimedEvent(TimedRestrictionAction action) { _action = action; _remainingTime = action.getRemainingTime(); addPausedTask(action.getObjectId(), this); } private long getRemainingTime() { return _remainingTime; } private TimedRestrictionAction getAction() { return _action; } private void activate() { timedRemoveRestriction(getAction().getObjectId(), getAction().getRestriction(), getRemainingTime(), getAction().getMessage()); } } }