/* * Copyright 2014 The Skfiy Open Association. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.skfiy.typhon.spi; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; import javax.management.MBeanException; import javax.management.ObjectName; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.modeler.ManagedBean; import org.skfiy.typhon.AbstractComponent; import org.skfiy.typhon.ComponentException; import org.skfiy.typhon.ConnectionProvider; import org.skfiy.typhon.DbException; import org.skfiy.typhon.TyphonException; import org.skfiy.typhon.Typhons; import org.skfiy.typhon.dobj.HeroItemDobj; import org.skfiy.typhon.dobj.ItemDobj; import org.skfiy.typhon.domain.Bag.Node; import org.skfiy.typhon.domain.Mail; import org.skfiy.typhon.domain.Normal; import org.skfiy.typhon.domain.Player; import org.skfiy.typhon.domain.PveProgress; import org.skfiy.typhon.domain.User; import org.skfiy.typhon.domain.item.HeroItem; import org.skfiy.typhon.repository.UserRepository; import org.skfiy.typhon.session.BagUtils; import org.skfiy.typhon.session.Session; import org.skfiy.typhon.session.SessionConstants; import org.skfiy.typhon.session.SessionContext; import org.skfiy.typhon.session.SessionManager; import org.skfiy.typhon.session.SessionUtils; import org.skfiy.typhon.spi.pve.Chapter; import org.skfiy.typhon.spi.pve.PveProvider; import org.skfiy.typhon.util.DbUtils; import org.skfiy.typhon.util.MBeanUtils; import org.skfiy.util.Assert; import org.skfiy.util.ReflectionUtils; /** * * @author Kevin Zou <kevinz@skfiy.org> */ @Singleton public class GMConsoleProvider extends AbstractComponent { private static final int[] MAIL_TYPES = {Mail.UPDATED_NOTICE_TYPE, Mail.ACTIVITY_NOTICE_TYPE, Mail.MAINTAIN_NOTICE_TYPE, Mail.REPARATION_NOTICE_TYPE, Mail.REWARD_NOTICE_TYPE}; private ThreadLocal<Session> _local_session; @Inject private SessionManager sessionManager; @Inject private ItemProvider itemProvider; @Inject private PveProvider pveProvider; @Inject private RoleProvider roleProvider; @Inject private UserRepository userRepository; @Inject private ConnectionProvider connectionProvider; private ObjectName oname; @Override protected void doInit() { ManagedBean managedBean = MBeanUtils.findManagedBean(getClass()); oname = MBeanUtils.registerComponent(this, managedBean); // initSessionThreadLocal(); } @Override protected void doReload() { } @Override protected void doDestroy() { if (oname != null) { MBeanUtils.REGISTRY.unregisterComponent(oname); } } /** * * @param uid * @param propertyName * @param val * @throws javax.management.MBeanException */ public void changeProperty(final String uid, final String propertyName, final String val) throws MBeanException { try { invoke(transcoding(uid), new Handler() { @Override void execute() { Player player = SessionUtils.getPlayer(); try { Class<?> propertyType = PropertyUtils.getPropertyType(player, propertyName); if (propertyType == null) { // Not found property throw new IllegalArgumentException("Not found property[" + propertyName + "]"); } if (propertyType == Byte.class || propertyType == Byte.TYPE) { BeanUtils.setProperty(player, propertyName, Byte.valueOf(val)); } else if (propertyType == Character.class || propertyType == Character.TYPE) { BeanUtils.setProperty(player, propertyName, val.charAt(0)); } else if (propertyType == Boolean.class || propertyType == Boolean.TYPE) { BeanUtils.setProperty(player, propertyName, Boolean.valueOf(val)); } else if (propertyType == Integer.class || propertyType == Integer.TYPE) { BeanUtils.setProperty(player, propertyName, Integer.valueOf(val)); } else if (propertyType == Long.class || propertyType == Long.TYPE) { BeanUtils.setProperty(player, propertyName, Long.valueOf(val)); } else if (propertyType == Float.class || propertyType == Float.TYPE) { BeanUtils.setProperty(player, propertyName, Float.valueOf(val)); } else if (propertyType == Double.class || propertyType == Double.TYPE) { BeanUtils.setProperty(player, propertyName, Double.valueOf(val)); } else { BeanUtils.setProperty(player, propertyName, val); } } catch (Exception ex) { throw new IllegalArgumentException(ex.getMessage()); } } }); } catch (Exception e) { throw new MBeanException(e, e.getMessage()); } } /** * * @param key * @param value * @throws javax.management.MBeanException */ public void changeSystemProperties(final String key, final String value) throws MBeanException { try { Typhons.setProperty(key, value); Typhons.refresh(); } catch (Exception e) { throw new MBeanException(e, e.getMessage()); } } /** * * @param uid * @param iid * @param level * @throws MBeanException */ public void changeHeroLevel(final String uid, final String iid, final String level) throws MBeanException { try { invoke(transcoding(uid), new Handler() { @Override void execute() { Player player = SessionUtils.getPlayer(); Node node = player.getHeroBag().findNode(iid); if (node == null) { HeroItemDobj itemDobj = itemProvider.getItem(iid); int pos = player.getHeroBag().intoItem(itemDobj); node = player.getHeroBag().findNode(pos); } HeroItem heroItem = node.getItem(); int lv = Integer.valueOf(level); if (lv > 150) { lv = 150; } heroItem.setLevel(lv); } }); } catch (Exception e) { throw new MBeanException(e, e.getMessage()); } } /** * 为玩家增加一个英雄. * * @param uid 用户名称 * @param iid Item ID * @throws javax.management.MBeanException */ public void pushHero(final String uid, final String iid) throws MBeanException { try { invoke(transcoding(uid), new Handler() { @Override void execute() { // Player player = SessionUtils.getPlayer(); HeroItemDobj itemDobj = itemProvider.getItem(iid); BagUtils.intoItem(itemDobj); } }); } catch (Exception e) { throw new MBeanException(e, e.getMessage()); } } /** * * @param uid * @param iid * @throws javax.management.MBeanException */ public void pushItem(final String uid, final String iid) throws MBeanException { pushItem(uid, iid, "1"); } /** * * @param uid * @param iid * @param count * @throws javax.management.MBeanException */ public void pushItem(final String uid, final String iid, final String count) throws MBeanException { try { invoke(transcoding(uid), new Handler() { @Override void execute() { // Player player = SessionUtils.getPlayer(); ItemDobj itemDobj = itemProvider.getItem(iid); if (itemDobj instanceof HeroItemDobj) { throw new TyphonException("不能在通过背包中添加英雄"); } BagUtils.intoItem(itemDobj, Integer.valueOf(count)); } }); } catch (Exception e) { throw new MBeanException(e, e.getMessage()); } } /** * * @param uid * @throws javax.management.MBeanException */ public void openAllPve(final String uid) throws MBeanException { try { invoke(transcoding(uid), new Handler() { @Override void execute() { Player player = SessionUtils.getPlayer(); Normal normal = player.getNormal(); // 史实篇 Field field = ReflectionUtils.findField(PveProvider.class, "historyChapters"); normal.setHpveProgresses(newPveProgressList(field)); // 史实篇(困难) field = ReflectionUtils.findField(PveProvider.class, "historyDifficultChapters"); normal.setHdpveProgresses(newPveProgressList(field)); } List<PveProgress> newPveProgressList(Field field) { field.setAccessible(true); List<Chapter> chapters = (List<Chapter>) ReflectionUtils.getField(field, pveProvider); List<PveProgress> list = new ArrayList<>(); for (int i = 0; i < chapters.size(); i++) { Chapter c = chapters.get(i); for (int j = 0; j < c.getParts().length; j++) { PveProgress pp = new PveProgress(i, j); list.add(pp); } } return list; } }); } catch (Exception e) { throw new MBeanException(e, e.getMessage()); } } /** * * @param uid * @param title * @param content * @param appendix * @param count * @param type * @throws java.lang.Exception */ public void sendMail(final String uid, final String title, final String content, final String appendix, final String count, final String type) throws Exception { try { User user = userRepository.findByUid(Integer.parseInt(uid)); if (user == null) { throw new RuntimeException("Not found user[" + uid + "]"); } roleProvider.sendMail(user.getUid(), newMail(new String(title.getBytes("ISO-8859-1"), "UTF-8"), new String(content.getBytes("ISO-8859-1"), "UTF-8"), appendix, Integer.valueOf(count), Integer.valueOf(type))); } catch (Exception e) { throw new MBeanException(e); } } /** * * @param title * @param content * @param appendix * @param count * @param type * @throws java.lang.Exception */ public void sendAllMail(final String title, final String content, final String appendix, final String count, final String type) throws Exception { try { String _title = new String(title.getBytes("ISO-8859-1"), "UTF-8"); String _content = new String(content.getBytes("ISO-8859-1"), "UTF-8"); List<Integer> rids = loadAllRids(); for (int rid : rids) { roleProvider.sendMail(rid, newMail(_title, _content, appendix, Integer.valueOf(count), Integer.valueOf(type))); } } catch (Exception e) { throw new MBeanException(e); } } /** * * @param rid * @param cash */ public void recharge(final String rid, final String cash) { Recharging recharging = new Recharging(); recharging.setRid(Integer.valueOf(rid)); recharging.setCash(Integer.valueOf(cash)); roleProvider.recharge(recharging); } private List<Integer> loadAllRids() { List<Integer> rids = new ArrayList<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = connectionProvider.getConnection(); ps = conn.prepareStatement("select t.rid from t_role t"); rs = ps.executeQuery(); while (rs.next()) { rids.add(rs.getInt("rid")); } DbUtils.commitQuietly(conn); } catch (SQLException e) { DbUtils.rollbackQuietly(conn); throw new DbException(e); } finally { DbUtils.closeQuietly(conn, ps, rs); } return rids; } private Mail newMail(final String title, final String content, final String appendix, final int count, final int type) { // 查检邮件的标题 Assert.hasLength(title, "mail title not empty"); // 检查邮件的内容 Assert.hasLength(content, "mail content not empty"); // 检查类型是否存在 if (ArrayUtils.indexOf(MAIL_TYPES, type) < 0) { throw new ComponentException("No mail type [" + type + "], optional" + ArrayUtils.toString(MAIL_TYPES)); } if (StringUtils.isNotEmpty(appendix)) { // 检查道具是否存在 itemProvider.getItem(appendix); } if (count <= 0) { throw new ComponentException("appendix count[" + count + "]"); } Mail mail = new Mail(); mail.setTitle(title); mail.setContent(content); if (StringUtils.isNotEmpty(appendix)) { mail.setAppendix(appendix); mail.setCount(count); } mail.setType(type); if (type == Mail.UPDATED_NOTICE_TYPE) { mail.setExpiredTime(mail.getCreationTime() + 7 * 24 * 60 * 60 * 1000); } return mail; } private void invoke(final String uid, final Handler handler) { for (Session session : sessionManager.findSessions()) { User user = (User) session.getAttribute(SessionConstants.ATTR_USER); if (user.getUid() == Integer.valueOf(uid).intValue()) { synchronized (session) { _local_session.set(session); handler.execute(); } return; } } throw new TyphonException("[" + uid + "]用户不存在或不在线"); } private void initSessionThreadLocal() { try { Field field = SessionContext.class.getDeclaredField("LOCAL_SESSION"); field.setAccessible(true); _local_session = (ThreadLocal<Session>) field.get(SessionContext.class); } catch (NoSuchFieldException ex) { throw new ComponentException("SessionContext中不存在[LOCAL_SESSION]属性", ex); } catch (SecurityException ex) { throw new ComponentException( getClass() + " 缺少访问SessionContext [LOCAL_SESSION] 属性的权限", ex); } catch (Exception ex) { throw new ComponentException(ex.getMessage(), ex); } } private abstract class Handler { /** * SessionContext.getSession(); */ abstract void execute(); } // 转换 private String transcoding(String userName) throws Exception { try { return new String(userName.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception e) { throw new MBeanException(e); } } }