Skip to content

Commit

Permalink
NAS-2647: CR-NAS-353 review follow-up.
Browse files Browse the repository at this point in the history
  • Loading branch information
nclarkekb committed Feb 21, 2018
1 parent dd1af0a commit c48175e
Show file tree
Hide file tree
Showing 19 changed files with 174 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,10 @@ private static void generateLanguageLinks(JspWriter out) throws IOException {
* Prints out the navigation tree appearing as a <td>in the left column of the "main_table" table. Subpages are
* shown only for the currently-active main-heading of the sections defined in settings.
*
* @param out the writer to which the output must be written.
* @param sb the <code>StringBuilder</code> to which the output must be written.
* @param req the HTTP request object to respond to
* @param url the url of the page.
* @param subMenu submenu HTML to insert when required by non JSP pages
* @param locale The locale selecting the language.
* @throws IOException if the output cannot be written.
*/
Expand Down Expand Up @@ -525,6 +527,7 @@ public static void setUTF8(HttpServletRequest request) {
/**
* Given a URL in the sitesection hierarchy, returns the corresponding page title.
*
* @param req the HTTP request object to respond to
* @param url a given URL
* @param locale the current locale
* @return the corresponding page title, or string about "(no title)" if no title can be found
Expand Down Expand Up @@ -935,8 +938,7 @@ public static String parseDate(Date timestamp) {
}

public static void log(String classname, String msg) {
log.info(classname + ":" + msg);
log.info(classname + ":" + msg);
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public abstract class SiteSection {

private static final Logger log = LoggerFactory.getLogger(SiteSection.class);


/** The overall human-readable name of the section. */
private final String mainname;
/** The number of pages that should be visible in the sidebar. */
Expand Down Expand Up @@ -115,6 +114,7 @@ public SiteSection(String mainname, String prefix, int visiblePages, String[][]
/**
* Given a URL, returns the corresponding page title.
*
* @param req the HTTP request object to respond to
* @param url a given URL.
* @param locale the current locale.
* @return the corresponding page title, or null if it is not in this section, or is null.
Expand All @@ -137,6 +137,7 @@ public String getTitle(HttpServletRequest req, String url, Locale locale) {
/**
* Returns the page name from a URL, if the page is in this hierarchy, null otherwise.
*
* @param req the HTTP request object to respond to
* @param url Url to check
* @return Page name, or null for not in this hierarchy.
*/
Expand All @@ -158,19 +159,26 @@ private String getPage(HttpServletRequest req, String url) {
} else {
contextPath = req.getContextPath();
if (url.startsWith('/' + contextPath + '/')) {
// Context path is only /path.
page = url.substring(contextPath.length() + 2);
// Context path is only /path.
page = url.substring(contextPath.length() + 2);
}
}
if (page != null) {
index = page.indexOf('/');
if (index != -1) {
page = page.substring(0, index + 1);
}
index = page.indexOf('/');
if (index != -1) {
page = page.substring(0, index + 1);
}
}
return page;
}

/**
* Given a URL, returns the path part without schema, context path and query string.
*
* @param req the HTTP request object to respond to
* @param url a given URL.
* @return the path part of a URL without the schema, context path and query string
*/
public String getPath(HttpServletRequest req, String url) {
URL parsed;
String tmpPath;
Expand All @@ -187,7 +195,7 @@ public String getPath(HttpServletRequest req, String url) {
tmpPath = parsed.getPath();
index = tmpPath.indexOf('?');
if (index != -1) {
tmpPath = tmpPath.substring(0, index);
tmpPath = tmpPath.substring(0, index);
}
path = null;
index = tmpPath.lastIndexOf(dirname + "/");
Expand All @@ -196,20 +204,26 @@ public String getPath(HttpServletRequest req, String url) {
} else {
contextPath = req.getContextPath();
if (url.startsWith('/' + contextPath + '/')) {
// Context path is only /path.
path = url.substring(contextPath.length() + 2);
// Context path is only /path.
path = url.substring(contextPath.length() + 2);
}
}
return path;
}

/**
* Returns the first sub path of a given path without schema, context path and query string.
*
* @param page a processed path without schema, context path and query string
* @return
*/
public String getPageFromPage(String page) {
int index;
int index;
if (page != null) {
index = page.indexOf('/');
if (index != -1) {
page = page.substring(0, index + 1);
}
index = page.indexOf('/');
if (index != -1) {
page = page.substring(0, index + 1);
}
}
return page;
}
Expand Down Expand Up @@ -257,16 +271,16 @@ public void generateNavigationTree(StringBuilder sb, HttpServletRequest req, Str
sb.append(link);
sb.append("\"> ");
if (path.equals(link)) {
sb.append("<b>");
sb.append("<b>");
sb.append(HTMLUtils.escapeHtmlValues(I18n.getString(bundle, locale, pageAndTitle.getValue())));
sb.append("</b>");
sb.append("</b>");
} else {
sb.append(HTMLUtils.escapeHtmlValues(I18n.getString(bundle, locale, pageAndTitle.getValue())));
}
sb.append("</a></td>");
sb.append("</tr>\n");
if (subMenu != null && page != null && path.startsWith(link) && path.length() > link.length()) {
sb.append(subMenu);
sb.append(subMenu);
}
++i;
}
Expand All @@ -279,7 +293,7 @@ public void generateNavigationTree(StringBuilder sb, HttpServletRequest req, Str
* @return The dirname.
*/
public String getDirname() {
return dirname;
return dirname;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,42 @@

import javax.servlet.http.HttpServletRequest;

/**
* HTTP accept-language header state machine based parser.
* Example: "da, en-gb;q=0.8, en;q=0.7".
*/
public class AcceptLanguageParser {

/** Start state. Look for a language. */
public static final int S_START_SPC = 0;
/** Language state. Look for country, qvalue or start of next locale. */
public static final int S_LANG = 1;
/** Country state. Look for a country. */
public static final int S_COUNTRY = 2;
/** Country parsed state. Look for qvalue or next locale. */
public static final int S_COUNTRY_SPC = 3;
/** Semicolon state. Look for an optional qvalue. */
public static final int S_SEMICOLON = 4;
/** State name. Look for attribute name. */
public static final int S_NAME = 5;
/** State parsed name. Look for value or next attribute or next locale. */
public static final int S_NAME_SPC = 6;
/** State equal. Look for first value character or next attribute or next locale. */
public static final int S_EQ = 7;
/** State value. Look for the rest of the value and next attribute or next locale. */
public static final int S_VALUE = 8;

/**
* Parsed language, country, locale and qvalue.
*/
public static class AcceptLanguage {
/** Language type string. */
public String language;
/** Country subtype string. */
public String country;
/** Combined locale string. */
public String locale;
/** Optional qvalue, defaults to 1. */
public float qvalue = 1.0f;
}

Expand All @@ -33,12 +53,25 @@ public int compare(AcceptLanguage o1, AcceptLanguage o2) {
}
}

/** Reusable comparator used to sort languages by their qvalue. */
public static AcceptLanguageComparator acceptLanguageComparator = new AcceptLanguageComparator();

/**
* Parses a HTTP accept-language header, if present, from the supplied HTTP request and returns a sorted list of valid languages.
* Languages are sorted by their qvalue.
* @param acceptLanguageStr accept language header string from a HTTP request
* @return <code>List</code> of valid languages sorted by their qvalue
*/
public static List<AcceptLanguage> parseHeader(HttpServletRequest req) {
return parseHeader(req.getHeader("Accept-Language"));
}

/**
* Parses a HTTP accept-language header string and returns a sorted list of valid languages.
* Languages are sorted by their qvalue.
* @param acceptLanguageStr accept language header string from a HTTP request
* @return <code>List</code> of valid languages sorted by their qvalue
*/
public static List<AcceptLanguage> parseHeader(String acceptLanguageStr) {
List<AcceptLanguage> acceptLanguages = new ArrayList<>();
char[] charArr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.antiaction.common.servlet.AutoIncrement;
import com.antiaction.common.servlet.PathMap;

import dk.netarkivet.heritrix3.monitor.HttpLocaleUtils.HttpLocale;
import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale;
import dk.netarkivet.heritrix3.monitor.resources.ConfigResource;
import dk.netarkivet.heritrix3.monitor.resources.H3BudgetResource;
import dk.netarkivet.heritrix3.monitor.resources.H3CrawlLogCachedResource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,47 @@
import dk.netarkivet.common.utils.StringTree;
import dk.netarkivet.heritrix3.monitor.AcceptLanguageParser.AcceptLanguage;

public class HttpLocaleUtils {
/**
* A class used to determine the appropriate locale/language to use for generating a HTTP response.
* Uses the HTTP request "Accept-Language" header, locale cookie or default locale.
* Also caches a structure of all available locale combinations in the execution environment.
*/
public class HttpLocaleHandler {

/** <code>Map</code> of all Locale objects registered by the execution environment. */
public final Map<String, Locale> localeMap = new HashMap<String, Locale>();

/** Structure including the */
public final LinkedHashMap<String, Language> languageLHM = new LinkedHashMap<String, Language>();

/**
* Object constructed from language configuration in the settings xml file.
*/
public static class Language {
/** Locate string identifier. */
public String language;
/* Localized language description. */
public String language_name;
/** Execution environment <code>Locale</code> object retrieved from the identifier. */
public Locale locale;
}

/**
* HTTP locale object with information about the best matched locale based on Accept-Language header,
* cookie usage and the NAS language object.
*/
public class HttpLocale {
/** Did the HTTP request include a locale cookie. */
public boolean bCookie;
/** Language object based on NAS language configuration. */
public Language languageObj;
/** Best match locale object. */
public Locale locale;

/**
* Generate language selection HTML based on the matched locale and cookie usage.
* @return generated language HTML
*/
public String generateLanguageLinks() {
String languageStr = languageObj.locale.getLanguage();
StringBuilder sb = new StringBuilder();
Expand Down Expand Up @@ -76,11 +100,19 @@ public String generateLanguageLinks() {
}
}

public HttpLocaleUtils() {
/**
* Constructor should only be used locally or in unit test.
*/
protected HttpLocaleHandler() {
}

public static HttpLocaleUtils getInstance() {
HttpLocaleUtils httpLocaleUtils = new HttpLocaleUtils();
/**
* Construct a HTTP locale handler. Reads all available locates in the execution environment
* and in the NAS settings XML.
* @return initialised HTTP locale handler
*/
public static HttpLocaleHandler getInstance() {
HttpLocaleHandler httpLocaleHandler = new HttpLocaleHandler();
Locale[] locales = Locale.getAvailableLocales();
Locale locale;
String languageStr;
Expand All @@ -90,15 +122,15 @@ public static HttpLocaleUtils getInstance() {
languageStr = locale.getLanguage();
countryStr = locale.getCountry();
if (countryStr != null) {
httpLocaleUtils.localeMap.put(languageStr + '-' + countryStr, locale);
if (!httpLocaleUtils.localeMap.containsKey(languageStr)) {
httpLocaleUtils.localeMap.put(languageStr, locale);
httpLocaleHandler.localeMap.put(languageStr + '-' + countryStr, locale);
if (!httpLocaleHandler.localeMap.containsKey(languageStr)) {
httpLocaleHandler.localeMap.put(languageStr, locale);
}
}
else {
httpLocaleUtils.localeMap.put(languageStr, locale);
httpLocaleHandler.localeMap.put(languageStr, locale);
}
httpLocaleUtils.localeMap.put(locale.getLanguage(), locale);
httpLocaleHandler.localeMap.put(locale.getLanguage(), locale);
}

StringTree<String> webinterfaceSettings = Settings.getTree(CommonSettings.WEBINTERFACE_SETTINGS);
Expand All @@ -107,13 +139,22 @@ public static HttpLocaleUtils getInstance() {
languageObj = new Language();
languageObj.language = languageSetting.getValue(CommonSettings.WEBINTERFACE_LANGUAGE_LOCALE);
languageObj.language_name = languageSetting.getValue(CommonSettings.WEBINTERFACE_LANGUAGE_NAME);
languageObj.locale = httpLocaleUtils.localeMap.get(languageObj.language);
httpLocaleUtils.languageLHM.put(languageObj.language, languageObj);
languageObj.locale = httpLocaleHandler.localeMap.get(languageObj.language);
httpLocaleHandler.languageLHM.put(languageObj.language, languageObj);
}

return httpLocaleUtils;
return httpLocaleHandler;
}

/**
* Determine the closest locale that matches the information in the HTTP request.
* Depending on usage it manages a cookie.
* If no cookie exists reads/parses the HTTP request "Accept-Language" header.
*
* @param req HTTP request object
* @param resp HTTP response object
* @return <code>HttpLocale</code> object determined to be the closest match to what the request wants
*/
public HttpLocale localeGetSet(HttpServletRequest req, HttpServletResponse resp) {
HttpLocale httpLocale = new HttpLocale();
boolean bCookieDeleted = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class NASEnvironment {

public static String servicePath;

public HttpLocaleUtils httpLocaleUtils;
public HttpLocaleHandler httpLocaleUtils;

public static class StringMatcher {
public String str;
Expand All @@ -85,7 +85,7 @@ public String getResourceAsString(String resource) throws IOException {
}

public NASEnvironment(ServletContext servletContext, ServletConfig theServletConfig) throws ServletException {
httpLocaleUtils = HttpLocaleUtils.getInstance();
httpLocaleUtils = HttpLocaleHandler.getInstance();

try {
NAS_GROOVY_SCRIPT = getResourceAsString(NAS_GROOVY_RESOURCE_PATH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dk.netarkivet.heritrix3.monitor.HttpLocaleUtils.HttpLocale;
import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale;

public interface ResourceAbstract {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import dk.netarkivet.heritrix3.monitor.NASUser;
import dk.netarkivet.heritrix3.monitor.ResourceAbstract;
import dk.netarkivet.heritrix3.monitor.ResourceManagerAbstract;
import dk.netarkivet.heritrix3.monitor.HttpLocaleUtils.HttpLocale;
import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale;

public class ConfigResource implements ResourceAbstract {

Expand Down
Loading

0 comments on commit c48175e

Please sign in to comment.