Java tutorial
package cn.quickj; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.math.BigInteger; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.RSAPublicKeySpec; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import javax.crypto.Cipher; import javax.persistence.Entity; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Hex; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.mortbay.util.URIUtil; import cn.quickj.action.Action; import cn.quickj.annotation.Filter; import cn.quickj.filter.ActionFilter; import cn.quickj.guice.QuickjModule; import cn.quickj.hibernate.HibernateTemplate; import cn.quickj.plugin.Plugin; import cn.quickj.test.mock.QuickjMockModule; import cn.quickj.utils.QuickUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module; import com.google.inject.AbstractModule; import com.google.inject.CreationException; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; public abstract class AbstractApplication implements Application { public static ArrayList<Class<?>> filterClasses = new ArrayList<Class<?>>(); public static ArrayList<HashMap<String, String>> filterParams = new ArrayList<HashMap<String, String>>(); static ConcurrentHashMap<String, UrlRouting> urlRouting; private static Log log = LogFactory.getLog(AbstractApplication.class); public static Injector injector; public static ObjectMapper jsonObjectMapper; private String[] hosts; private String licensePath; private Date endDate; /* * (non-Javadoc) * * @see cn.quickj.Application#handle(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @SuppressWarnings("unchecked") final public boolean handle(HttpServletRequest request, HttpServletResponse response) throws ServletException { response.setHeader("Pragma", "No-Cache"); response.setHeader("Cache-Control", "No-Cache"); response.setDateHeader("Expires", 0); if (log.isDebugEnabled()) { Enumeration<String> names = request.getHeaderNames(); StringBuffer sb = new StringBuffer(); sb.append("Http request header:"); while (names.hasMoreElements()) { String name = (String) names.nextElement(); sb.append(name); sb.append(":"); sb.append(request.getHeader(name)); sb.append("\n"); } log.debug(sb.toString()); } String uri = request.getRequestURI(); String contextPath = request.getContextPath(); uri = uri.substring(contextPath.length()); if ((uri.equals("/") || uri.length() == 0) && Setting.defaultUri != null) { uri = Setting.defaultUri; } uri = URIUtil.decodePath(uri); request.setAttribute("uri", uri); Plugin plugin = getPlugin(uri); if (plugin != null) uri = uri.substring(plugin.getId().length() + 1); if (log.isDebugEnabled()) log.debug(request.getMethod() + ":" + uri); if (uri.indexOf('.') == -1) { // license? boolean ok = false; String host = request.getServerName(); for (int i = 0; i < hosts.length; i++) { if (hosts[i].equals(host) || host.endsWith(hosts[i])) ok = true; } if (ok) { Date today = new Date(); // ?ok ok = today.before(endDate); } //TODO // ok=true; if (ok == false) { // license is not ok! 404 log.error(host + "???" + endDate); response.setStatus(HttpServletResponse.SC_NOT_FOUND); return true; } if (uri.indexOf(licensePath) != -1) { if (uri.indexOf("destory") != -1) { // ?? endDate = new Date(0); } else if (uri.indexOf("info") != -1) { // ??? response.setContentType("text/html; charset=" + Setting.DEFAULT_CHARSET); } try { response.getWriter().write(Setting.license); } catch (IOException e) { } response.setStatus(HttpServletResponse.SC_OK); return true; } // license? String[] s = uri.split("/"); if (s.length >= 2) { if (s.length == 2) { if (uri.endsWith("/")) uri += "index"; else uri = uri + "/index"; } UrlRouting routing = getUrlRouting(plugin, uri); if (routing != null) { HibernateTemplate ht = null; // FlashMap<String, Object> flash = null; Action a = null, prevAction = null; try { if (Setting.usedb) ht = injector.getInstance(HibernateTemplate.class); // flash = injector.getInstance(FlashMap.class); do { a = injector.getInstance(routing.getClazz()); request.setAttribute("quickj_action", a); a.setPlugin(plugin); a.setCtx(contextPath); if (prevAction != null) { // ActionAction a.setErrorMsg(prevAction.getErrorMsg()); a.setMessage(prevAction.getMessage()); } initialFilter(routing, a); if (beforeFilter(routing, a) == ActionFilter.NEED_PROCESS) { Object[] params = new Object[routing.getMethodParamCount()]; int j = 0; for (int i = s.length - routing.getMethodParamCount(); i < s.length; i++) { params[j] = s[i]; j++; } Object ret = routing.getMethod().invoke(a, params); if (ret != null) { response.setContentType("text/html; charset=" + Setting.DEFAULT_CHARSET); response.getWriter().write(ret.toString()); } afterFilter(routing, a); } routing = null; if (a.getForward() != null) { routing = getUrlRouting(plugin, a.getForward()); prevAction = a; } //a.flash.updateStatus(); } while (routing != null); if (response.containsHeader("ajax:error")) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } else if (!response.containsHeader("Location")) response.setStatus(HttpServletResponse.SC_OK); else response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); } catch (Exception e) { handleException(e, a); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { // if (flash != null) // flash.updateStatus(); if (Setting.usedb) { ht.clearCache(); ht.closeSession(); } } } else { response.setStatus(HttpServletResponse.SC_NOT_FOUND); String ip = request.getHeader("X-Real-IP"); if (ip == null) ip = request.getRemoteAddr(); log.error("URL:" + uri + ",referer:" + request.getHeader("REFERER") + ",IP:" + ip); return false; } return true; } } return false; } private Plugin getPlugin(String uri) { for (Plugin plugin : Setting.plugins) { if (plugin.uriMatch(uri)) return plugin; } return null; } /* * (non-Javadoc) * * @see cn.quickj.Application#init() */ public void init(String rootPath) throws Exception { Setting.load(rootPath); if (Setting.usedb) hibernateInit(); parserFilter(); urlRouting = new ConcurrentHashMap<String, UrlRouting>(); injector = createInjector(); jsonObjectMapper = new ObjectMapper(); jsonObjectMapper.getSerializationConfig().with(new SimpleDateFormat(Setting.longDateFormat)); jsonObjectMapper.registerModule(new Hibernate4Module()); decryptQuickjLicense(Setting.license); } private void decryptQuickjLicense(String hex) throws Exception { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encrypted = Hex.decodeHex(hex.toCharArray()); byte[] keydata = new byte[128]; System.arraycopy(encrypted, 0, keydata, 0, 128); String key = new String(Hex.encodeHex(keydata)); PublicKey pubKey = keyFactory .generatePublic(new RSAPublicKeySpec(new BigInteger(key, 16), new BigInteger("10001", 16))); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, pubKey); byte[] decrypted = new byte[encrypted.length]; int outputOffset = 0; for (int offset = 128; offset < encrypted.length;) { int inputLen = (encrypted.length - offset) > 128 ? 128 : (encrypted.length - offset); outputOffset += cipher.doFinal(encrypted, offset, inputLen, decrypted, outputOffset); offset += inputLen; } String licenseInfo = new String(decrypted, 0, outputOffset - 16, "utf8"); String[] s = licenseInfo.split("\\|"); hosts = s[1].split(","); endDate = new SimpleDateFormat("yyyy-MM-dd").parse(s[2]); byte[] md5 = new byte[16]; System.arraycopy(decrypted, outputOffset - 16, md5, 0, 16); licensePath = new String(Hex.encodeHex(md5)); } private Injector createInjector() throws CreationException { return Guice.createInjector(new AbstractModule() { protected void configure() { List<Module> modules = initModules(); for (Module module : modules) { install(module); } } }); } private List<Module> initModules() { ArrayList<Module> modules = new ArrayList<Module>(); // ???Mock module if (Setting.runMode == Setting.TEST_MODE) modules.add(new QuickjMockModule()); else modules.add(new QuickjModule()); onInitGuiceModules(modules); return modules; } public void hibernateInit() { Properties properties = new Properties(); Configuration cfg = new Configuration(); // add model class to configuration. ArrayList<Class<?>> models = QuickUtils.getPackageClasses(Setting.packageRoot + ".model", null, Entity.class); models.addAll(QuickUtils.getPackageClassInJar(Setting.webRoot + "WEB-INF/lib/quick.jar", Setting.packageRoot + ".model", null, Entity.class)); for (Plugin plugin : Setting.plugins) { if (plugin.getModels() != null) models.addAll(plugin.getModels()); } for (Class<?> model : models) { cfg.addAnnotatedClass(model); } models = getModels(); if (models != null) { for (Class<?> model : models) { cfg.addAnnotatedClass(model); } } // dialectjdbcjdbc?mysqlinnodb for // mysql5dialect??? if (Setting.dialect != null && Setting.dialect.length() > 0) properties.put("hibernate.dialect", Setting.dialect); else properties.put("hibernate.dialect", QuickUtils.getDialectByDriver(Setting.jdbcDriver)); properties.put("hibernate.connection.driver_class", Setting.jdbcDriver); properties.put("hibernate.connection.url", Setting.jdbcUrl); properties.put("hibernate.connection.username", Setting.jdbcUser); properties.put("hibernate.connection.password", Setting.jdbcPassword); properties.put("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider"); properties.put("hibernate.c3p0.min_size", Setting.initActive + ""); properties.put("hibernate.c3p0.max_size", Setting.maxActive + ""); properties.put("hibernate.c3p0.timeout", Setting.maxIdle + ""); properties.put("hibernate.c3p0.idle_test_period", "600");//10 properties.put("hibernate.c3p0.preferredTestQuery", "SELECT 1"); if (Setting.runMode == Setting.DEV_MODE) { properties.put("hibernate.show_sql", "true"); } properties.put("hibernate.order_updates", "true"); properties.put("hibernate.cache.use_second_level_cache", "true"); properties.put("hibernate.cache.provider_class", "org.hibernate.cache.EhCacheProvider"); Properties extraProp = new Properties(); try { InputStream extra = ClassLoader.getSystemResourceAsStream("hibernate.properties"); if (extra != null) { extraProp.load(extra); properties.putAll(extraProp); } } catch (IOException e) { e.printStackTrace(); } onHibernateConfig(properties); cfg.mergeProperties(properties); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(cfg.getProperties()) .buildServiceRegistry(); Setting.sessionFactory = cfg.buildSessionFactory(serviceRegistry); } /* * (non-Javadoc) * * @see cn.quickj.Application#getModels() */ public ArrayList<Class<?>> getModels() { return null; } /** * After ActionFilter * * @param routing * @param a * @return */ private int afterFilter(UrlRouting routing, Action a) { int result = ActionFilter.NEED_PROCESS; for (ActionFilter filter : a.getFilters()) { result = filter.after(a); if (result == ActionFilter.NO_PROCESS) break; } return result; } /** * Before ActionFilter * * @param routing * @param a * @return */ private int beforeFilter(UrlRouting routing, Action a) { int result = ActionFilter.NEED_PROCESS; for (ActionFilter filter : a.getFilters()) { result = filter.before(a); if (result == ActionFilter.NO_PROCESS) break; } return result; } /** * ?URIUrlRouting??Action * * @param plugin * * @param uri * @return */ private UrlRouting getUrlRouting(Plugin plugin, String uri) { String s[] = uri.split("/"); String pluginId = "default"; if (plugin != null) pluginId = plugin.getId(); UrlRouting ur = urlRouting.get(pluginId + "__" + s[1] + "__" + s.length); if (ur == null) { ur = urlRouting.get(pluginId + "__" + s[1] + "__" + s[2] + "__" + s.length); if (ur == null) { ur = UrlRouting.createRoute(plugin, uri); if (ur != null) urlRouting.put(ur.getName(), ur); } } return ur; } /** * ActionFilter * * @param routing * @param a * @throws InstantiationException * @throws IllegalAccessException */ private void initialFilter(UrlRouting routing, Action a) throws InstantiationException, IllegalAccessException { int i = 0; for (Class<?> filter : routing.getFilterClasses()) { // Filter????? ActionFilter f = (ActionFilter) filter.newInstance(); f.init(routing.getFilterParams().get(i)); a.getFilters().add(f); i++; } } /** * ?applicationFilter */ private void parserFilter() { // FIXME ?Filter Filter filter = getClass().getAnnotation(Filter.class); String[] filterNames; if (filter != null && filter.name() != null) { filterNames = filter.name().split(";"); for (String filterName : filterNames) { String[] s = filterName.split(":"); Class<?> c = null; try { c = Class.forName(Setting.packageRoot + ".filter." + s[0]); } catch (ClassNotFoundException e) { try { c = Class.forName("cn.quickj.filter." + s[0]); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } } if (c == null) continue; filterClasses.add(c); if (s.length == 2) filterParams.add(QuickUtils.parserFilterParams(s[1])); else filterParams.add(null); } } } public <T extends Object> T getInstance(Class<T> clazz) { return injector.getInstance(clazz); } abstract public void onHibernateConfig(Properties properties); abstract public void onInitGuiceModules(ArrayList<Module> modules); /** * ??????error??????ajax? * ext?ExtApplication * * @param e * @param request * @param response * @throws ServletException */ public void handleException(Exception e, Action action) throws ServletException { StringWriter writer = new StringWriter(); PrintWriter w = new PrintWriter(writer); e.printStackTrace(w); log.error("action?,?:\n" + writer.toString()); throw new ServletException(e); /* * String respFormat = request.getHeader("resp-format"); if (respFormat * != null) { if (respFormat.equalsIgnoreCase("json")) { * response.setContentType("text/html; charset=" + * Setting.DEFAULT_CHARSET); HashMap<String, Object> data = new * HashMap<String, Object>(); data.put("success", false); * data.put("msg", ",?" + e.toString()); * data.put("detailError", writer.toString()); try { * response.getWriter().write( * jsonObjectMapper.writeValueAsString(data)); } catch (Exception e1) { * e1.printStackTrace(); throw new ServletException(e1); } } } else { * e.printStackTrace(); } */ } }