Package org.beangle.struts2.convention.route.impl

Source Code of org.beangle.struts2.convention.route.impl.ProfileServiceImpl

/* Copyright c 2005-2012.
* Licensed under GNU  LESSER General Public License, Version 3.
* http://www.gnu.org/licenses
*/
package org.beangle.struts2.convention.route.impl;

import static org.apache.commons.lang.StringUtils.isEmpty;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.beangle.commons.collection.CollectUtils;
import org.beangle.commons.config.ConfigResource;
import org.beangle.struts2.convention.Constants;
import org.beangle.struts2.convention.route.Profile;
import org.beangle.struts2.convention.route.ProfileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProfileServiceImpl implements ProfileService {

  private final static Logger logger = LoggerFactory.getLogger(ProfileServiceImpl.class);

  private List<Profile> profiles = new ArrayList<Profile>();

  private Profile defaultProfile = new Profile();

  // 匹配缓存[String,Profile]
  private Map<String, Profile> cache = new ConcurrentHashMap<String, Profile>();

  private ConfigResource resource;

  public ProfileServiceImpl() {
    super();
    defaultProfile.setActionSuffix("Action");
    defaultProfile.setActionScan(true);
    defaultProfile.setDefaultMethod("index");
    defaultProfile.setUriPath("/");
    defaultProfile.setUriPathStyle(Constants.SEO_URI);
    defaultProfile.setUriExtension("action");
    defaultProfile.setViewPath("/pages/");
    defaultProfile.setViewPathStyle(Constants.SIMPLE_VIEWPATH);
    defaultProfile.setViewExtension("ftl");
    setResource(getDefaultResource());
  }

  // FIXME
  private ConfigResource getDefaultResource() {
    try {
      ConfigResource resource = new ConfigResource();
      resource.setGlobal(ProfileServiceImpl.class.getClassLoader().getResource(
          "META-INF/convention-default.properties"));
      Enumeration<URL> em = ProfileServiceImpl.class.getClassLoader().getResources(
          "META-INF/convention-route.properties");
      while (em.hasMoreElements()) {
        resource.getLocals().add(em.nextElement());
      }
      return resource;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public Profile getProfile(String className) {
    Profile matched = cache.get(className);
    if (null != matched) { return matched; }
    int index = -1;
    int patternLen = 0;
    for (Profile profile : profiles) {
      int newIndex = profile.matchedIndex(className);
      if (newIndex < 0) continue;
      if (newIndex >= index && profile.getActionPattern().length() >= patternLen) {
        matched = profile;
        index = newIndex;
        patternLen = profile.getActionPattern().length();
      }
    }
    if (matched == null) {
      matched = defaultProfile;
    }
    cache.put(className, matched);
    logger.debug("{} match profile:{}", className, matched);
    return matched;
  }

  public Profile getProfile(Class<?> clazz) {
    return getProfile(clazz.getName());
  }

  private Properties getProperties(URL url) {
    logger.debug("loading {}", url);
    InputStream in = null;
    try {
      in = url.openStream();
      if (in != null) {
        Properties p = new Properties();
        p.load(in);
        return p;
      }
    } catch (IOException e) {
      logger.error("Error while loading " + url, e);
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException io) {
          logger.warn("Unable to close input stream", io);
        }
      }
    }
    return null;
  }

  /**
   * 初始化配置
   */
  private void loadProfiles() {
    // META-INF/convention-default.properties
    // META-INF/convention-route.properties
    URL convention_default = resource.getGlobal();
    if (null == convention_default) { throw new RuntimeException(
        "cannot find convention-default.properties!"); }
    List<Profile> defaultProfiles = buildProfiles(convention_default, true);
    if (!defaultProfiles.isEmpty()) {
      defaultProfile = defaultProfiles.get(0);
    }
    for (URL url : resource.getLocals()) {
      profiles.addAll(buildProfiles(url, false));
    }
  }

  private List<Profile> buildProfiles(URL url, boolean isDefault) {
    List<Profile> myProfiles = CollectUtils.newArrayList();
    Properties props = getProperties(url);
    if (isDefault) {
      Profile profile = populatProfile(props, "default");
      myProfiles.add(profile);
    } else {
      int profileIndex = 0;
      while (true) {
        Profile profile = populatProfile(props, "profile" + profileIndex);
        if (null == profile) {
          break;
        } else {
          myProfiles.add(profile);
        }
        profileIndex++;
      }
    }
    return myProfiles;
  }

  private Profile populatProfile(Properties props, String name) {
    Profile profile = new Profile();
    profile.setName(name);
    String actionPattern = props.getProperty(profile.getName() + ".actionPattern");
    if (isEmpty(actionPattern)) { return null; }
    populateAttr(profile, "actionPattern", props);
    populateAttr(profile, "actionSuffix", props);
    populateAttr(profile, "viewPath", props);
    populateAttr(profile, "viewExtension", props);
    populateAttr(profile, "viewPathStyle", props);
    populateAttr(profile, "defaultMethod", props);
    populateAttr(profile, "uriPath", props);
    populateAttr(profile, "uriPathStyle", props);
    populateAttr(profile, "uriExtension", props);
    populateAttr(profile, "actionScan", props);
    // 保证页面路径以/结束
    // if (!profile.getViewPath().endsWith(Convention.separator + "")) {
    // profile.setViewPath(profile.getViewPath() + Convention.separator);
    // }
    // FIXME validate attribute
    return profile;
  }

  private void populateAttr(Profile profile, String attr, Properties props) {
    Object value = props.getProperty(profile.getName() + "." + attr);
    try {
      if (null == value) {
        value = PropertyUtils.getProperty(defaultProfile, attr);
      }
      BeanUtils.copyProperty(profile, attr, value);
    } catch (Exception e) {
      logger.error("error attr {} for profile", attr);
    }
  }

  public List<Profile> getProfiles() {
    return profiles;
  }

  public void setProfiles(List<Profile> profiles) {
    this.profiles = profiles;
  }

  public Profile getDefaultProfile() {
    return defaultProfile;
  }

  public void setDefaultProfile(Profile defaultProfile) {
    this.defaultProfile = defaultProfile;
  }

  public ConfigResource getResource() {
    return resource;
  }

  public void setResource(ConfigResource resource) {
    this.resource = resource;
    if (null != resource) {
      loadProfiles();
    } else {
      if (null != profiles) {
        profiles.clear();
      }
    }
  }

}
TOP

Related Classes of org.beangle.struts2.convention.route.impl.ProfileServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.