diff options
Diffstat (limited to 'org.eclipse.help.webapp/src')
5 files changed, 283 insertions, 44 deletions
diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.java b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.java index 6661e5088..5aaf0c9e3 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.java +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -66,6 +66,29 @@ public class WebappResources { } } + + /** + * Returns a string from a property file. It uses 'name' as the key to + * retrieve from the webapp.properties file. And it uses args[] to replace the variables in property string. + */ + public static String getString(String name, Locale locale, String[] args) { + + // get bundle + ResourceBundle bundle = getBundle(locale); + if (bundle == null) { + return name; + } + + // get value + try { + String stringFromPropertiesFile = bundle.getString(name); + stringFromPropertiesFile = MessageFormat.format( + stringFromPropertiesFile, args); + return stringFromPropertiesFile; + } catch (Exception e) { + return name; + } + } /** * Obtains resource bundle for specified locale. Loads bundle if necessary * diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.properties b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.properties index 322dd9343..3852b7c4c 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.properties +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/WebappResources.properties @@ -182,3 +182,10 @@ aboutPlugins=About Plug-Ins userAgent=User Agent preferences=Preferences badPreferences=Unable to read preferences + +# Quick print page +topicNumExceeded=You have chosen to print {0} individual topics. The maximum number of topics allowed to be printed is {1}. To continue printing the first {1} documents of your selection click ''{2}''. Click ''{3}'' to cancel this print job. +noConnection=The maximum capacity for active connections to the server has been reached. Unfortunately, your print job can not be completed at this time. Please try again.\n +ioException=An error occured during content retrieval.\n +alert=Alert +error=Error diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/PrintData.java b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/PrintData.java index 2bd36a326..4c01453a8 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/PrintData.java +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/PrintData.java @@ -24,7 +24,9 @@ import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -42,6 +44,12 @@ import org.eclipse.help.internal.xhtml.DynamicXHTMLProcessor; */ public class PrintData extends RequestData { + // default max connections for concurrent print + private static final int defaultMaxConnections = 10; + + // default max topics allowed for one print request + private static final int defaultMaxTopics = 500; + // where to inject the section numbers private static final Pattern PATTERN_HEADING = Pattern.compile("<body.*?>[\\s]*?([\\w])", Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ @@ -51,11 +59,36 @@ public class PrintData extends RequestData { // Where to inject css private static final Pattern PATTERN_END_HEAD = Pattern.compile("</head.*?>", Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ + private static boolean initialized = false; + + private static int allowedConnections; + + private static int allowedMaxTopics; + + private boolean confirmed; + + // flag right-to-left direction of text + private boolean isRTL; + /* * Constructs the print data for the given request. */ public PrintData(ServletContext context, HttpServletRequest request, HttpServletResponse response) { super(context, request, response); + + if (!initialized) { + initPreferences(preferences); + } + + isRTL = UrlUtil.isRTL(request, response); + + String confirmString = request.getParameter("confirmed"); //$NON-NLS-1$ + if ((confirmString != null) && ("true".equals(confirmString))) { //$NON-NLS-1$ + confirmed = true; + } else { + confirmed = false; + } + } /* @@ -80,74 +113,212 @@ public class PrintData extends RequestData { } /* + * init properties set in base preference.ini for quick print + */ + private static synchronized void initPreferences(WebappPreferences preferences) { + + if (initialized) { + return; + } + + // set max connection numbers for concurrent access + String maxConnections = preferences.getQuickPrintMaxConnections(); + if ((null == maxConnections) || ("".equals(maxConnections.trim()))) { //$NON-NLS-1$ + allowedConnections = defaultMaxConnections; + } else { + try { + allowedConnections = Integer.parseInt(maxConnections); + } catch (NumberFormatException e) { + HelpWebappPlugin.logError("Init maxConnections error. Set to default.", e); //$NON-NLS-1$ + allowedConnections = defaultMaxConnections; + } + } + + // set max topics allowed to print in one request + String maxTopics = preferences.getQuickPrintMaxTopics(); + if ((null == maxTopics) || ("".equals(maxTopics.trim()))) { //$NON-NLS-1$ + allowedMaxTopics = defaultMaxTopics; + } else { + try { + allowedMaxTopics = Integer.parseInt(maxTopics); + } catch (NumberFormatException e) { + HelpWebappPlugin.logError("Init maxTopics error. Set to default.", e); //$NON-NLS-1$ + allowedMaxTopics = defaultMaxTopics; + } + } + + initialized = true; + } + + /* + * Generates resources to print + */ + public void generateResources(Writer out) throws IOException, ServletException { + // check resource allocation + if (!getConnection()) { + RequestDispatcher rd = context.getRequestDispatcher("/advanced/printError.jsp"); //$NON-NLS-1$ + request.setAttribute("msg", "noConnection"); //$NON-NLS-1$ //$NON-NLS-2$ + rd.forward(request, response); + return; + } + + + ITopic topic = getTopic(); // topic selected for print + int topicRequested = topicsRequested(topic); + if (topicRequested > allowedMaxTopics) { + if (!confirmed) { + releaseConnection(); + RequestDispatcher rd = context.getRequestDispatcher("/advanced/printConfirm.jsp"); //$NON-NLS-1$ + request.setAttribute("topicsRequested", String.valueOf(topicRequested)); //$NON-NLS-1$ + request.setAttribute("allowedMaxTopics", String.valueOf(allowedMaxTopics)); //$NON-NLS-1$ + rd.forward(request, response); + return; + } + } + + try { + generateToc(out); + generateContent(out); + } catch (IOException e) { + RequestDispatcher rd = context.getRequestDispatcher("/advanced/printError.jsp"); //$NON-NLS-1$ + request.setAttribute("msg", "ioException"); //$NON-NLS-1$ //$NON-NLS-2$ + rd.forward(request, response); + } finally { + releaseConnection(); + } + } + + private static synchronized boolean getConnection() { + if (allowedConnections > 0) { + allowedConnections--; + return true; + } + return false; + } + + private static synchronized void releaseConnection() { + allowedConnections++; + } + + /* + * Calculate the amount of topics to print in one request + */ + private int topicsRequested(ITopic topic) { + int topicsRequested = 0; + if (topic.getHref() != null && topic.getHref().length() > 0) { + topicsRequested++; + } + + ITopic[] subtopics = EnabledTopicUtils.getEnabled(topic.getSubtopics()); + for (int i = 0; i < subtopics.length; ++i) { + topicsRequested += topicsRequested(subtopics[i]); + } + return topicsRequested; + } + + /* * Generates and outputs a table of contents div with links. */ - public void generateToc(Writer out) throws IOException { - out.write("<div id=\"toc\">"); //$NON-NLS-1$ + private void generateToc(Writer out) throws IOException { + int tocGenerated = 0; + + out.write("<html>\n"); //$NON-NLS-1$ + out.write("<head>\n"); //$NON-NLS-1$ + out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); //$NON-NLS-1$ + out.write("<title>" + UrlUtil.htmlEncode(getTitle()) +"</title>\n"); //$NON-NLS-1$ //$NON-NLS-2$ + out.write("<link rel=\"stylesheet\" href=\"print.css\" charset=\"utf-8\" type=\"text/css\">\n"); //$NON-NLS-1$ + out.write("</head>\n"); //$NON-NLS-1$ + out.write("<body dir=\"" + (isRTL ? "right" : "left") + "\" onload=\"print()\">\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + out.write("<div id=\"toc\">\n"); //$NON-NLS-1$ out.write("<h1>"); //$NON-NLS-1$ out.write(getTitle()); - out.write("</h1>"); //$NON-NLS-1$ + out.write("</h1>\n"); //$NON-NLS-1$ out.write("<h2>"); //$NON-NLS-1$ out.write(ServletResources.getString("TocHeading", request)); //$NON-NLS-1$ - out.write("</h2>"); //$NON-NLS-1$ - out.write("<div id=\"toc_content\">"); //$NON-NLS-1$ + out.write("</h2>\n"); //$NON-NLS-1$ + out.write("<div id=\"toc_content\">\n"); //$NON-NLS-1$ ITopic topic = getTopic(); + + String href = topic.getHref(); + if (href != null && href.length() > 0) { + tocGenerated++; + } ITopic[] subtopics = EnabledTopicUtils.getEnabled(topic.getSubtopics()); - for (int i=0;i<subtopics.length;++i) { - generateToc(subtopics[i], String.valueOf(i + 1), out); + for (int i = 0; i < subtopics.length; ++i) { + tocGenerated = generateToc(subtopics[i], String.valueOf(i + 1), tocGenerated, out); } - out.write("</div>"); //$NON-NLS-1$ - out.write("</div>"); //$NON-NLS-1$ + + out.write("</div>\n"); //$NON-NLS-1$ + out.write("</div>\n"); //$NON-NLS-1$ + out.write("</body>\n"); //$NON-NLS-1$ + out.write("</html>\n"); //$NON-NLS-1$ } /* * Auxiliary method for recursively generating table of contents div. */ - private void generateToc(ITopic topic, String sectionId, Writer out) throws IOException { - out.write("<div class=\"toc_" + (sectionId.length() > 2 ? "sub" : "") + "entry\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - out.write(sectionId + ". " + "<a href=\"#section" + sectionId + "\">" + topic.getLabel() + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - ITopic[] subtopics = EnabledTopicUtils.getEnabled(topic.getSubtopics()); - for (int i=0;i<subtopics.length;++i) { - String subsectionId = sectionId + "." + (i + 1); //$NON-NLS-1$ - generateToc(subtopics[i], subsectionId, out); + private int generateToc(ITopic topic, String sectionId, int tocGenerated, Writer out) throws IOException { + if (tocGenerated < allowedMaxTopics) { + out.write("<div class=\"toc_" + (sectionId.length() > 2 ? "sub" : "") + "entry\">\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + out.write(sectionId + ". " + "<a href=\"#section" + sectionId + "\">" + topic.getLabel() + "</a>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + String href = topic.getHref(); + if (href != null && href.length() > 0) { + tocGenerated++; + } + + ITopic[] subtopics = EnabledTopicUtils.getEnabled(topic.getSubtopics()); + for (int i = 0; i < subtopics.length; ++i) { + String subsectionId = sectionId + "." + (i + 1); //$NON-NLS-1$ + tocGenerated = generateToc(subtopics[i], subsectionId, tocGenerated, out); + } + out.write("</div>\n"); //$NON-NLS-1$ + return tocGenerated; } - out.write("</div>"); //$NON-NLS-1$ + return tocGenerated; } /* * Generates the content to print (the merged topics). */ public void generateContent(Writer out) throws IOException { - generateContent(getTopic(), null, out, new HashSet()); + int topicsGenerated = 0; + generateContent(getTopic(), null, topicsGenerated, new HashSet(), out); } - + /* * Auxiliary method for recursively generating print content. */ - private void generateContent(ITopic topic, String sectionId, Writer out, Set generated) throws IOException { - String href = topic.getHref(); - if (href != null) { - // get the topic content - href = removeAnchor(href); - String pathHref = href.substring(0, href.lastIndexOf('/') + 1); - String baseHref = "../topic" + pathHref; //$NON-NLS-1$ - String content; - if (!generated.contains(href)) { - generated.add(href); - content = getContent(href, locale); - // root topic doesn't have sectionId - if (sectionId != null) { - content = injectHeading(content, sectionId); + private int generateContent(ITopic topic, String sectionId, int topicsGenerated, Set generated, Writer out) throws IOException { + if (topicsGenerated < allowedMaxTopics) { + String href = topic.getHref(); + if (href != null && href.length() > 0) { + topicsGenerated++; + // get the topic content + href = removeAnchor(href); + String pathHref = href.substring(0, href.lastIndexOf('/') + 1); + String baseHref = "../topic" + pathHref; //$NON-NLS-1$ + String content; + if (!generated.contains(href)) { + generated.add(href); + content = getContent(href, locale); + // root topic doesn't have sectionId + if (sectionId != null) { + content = injectHeading(content, sectionId); + } + content = normalizeHrefs(content, baseHref); + content = injectCss(content); + out.write(content); } - content = normalizeHrefs(content, baseHref); - content = injectCss(content); - out.write(content); - } - } - ITopic[] subtopics = EnabledTopicUtils.getEnabled(topic.getSubtopics()); - for (int i=0;i<subtopics.length;++i) { - String subsectionId = (sectionId != null ? sectionId + "." : "") + (i + 1); //$NON-NLS-1$ //$NON-NLS-2$ - generateContent(subtopics[i], subsectionId, out, generated); + } + ITopic[] subtopics = EnabledTopicUtils.getEnabled(topic.getSubtopics()); + for (int i = 0; i < subtopics.length; ++i) { + String subsectionId = (sectionId != null ? sectionId + "." : "") + (i + 1); //$NON-NLS-1$ //$NON-NLS-2$ + topicsGenerated = generateContent(subtopics[i], subsectionId, topicsGenerated, generated, out); + } + return topicsGenerated; + } else { + return topicsGenerated; } } @@ -208,6 +379,11 @@ public class PrintData extends RequestData { InputStream rawInput = HelpSystem.getHelpContent(href, locale); boolean filter = BaseHelpSystem.getMode() != BaseHelpSystem.MODE_INFOCENTER; in = DynamicXHTMLProcessor.process(href, rawInput, locale, filter); + + if (in == null) { + in = HelpSystem.getHelpContent(href, locale); + } + Reader reader = new BufferedReader(new InputStreamReader(in, charset)); char[] cbuf = new char[4096]; int num; diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/ServletResources.java b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/ServletResources.java index 5f5599d83..4e6cad921 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/ServletResources.java +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/ServletResources.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -81,6 +81,31 @@ public class ServletResources { return property.substring(0, amp - 1) + property.substring(amp + 1, property.length()); } + + /** + * Returns a string from a property file. It uses 'name' as a the key to + * retrieve from the webapp.properties file. 'args[]' is used to replace + * the variables in property string. + * + * @param request + * HttpServletRequest or null; default locale will be used if + * null passed + */ + public static String getString(String name, String[] args, + HttpServletRequest request) { + String property = WebappResources.getString(name, UrlUtil.getLocaleObj( + request, null), args); + if (property == null || property.length() <= 0) { + return property; + } + int amp = property.indexOf('&'); + if (amp <0 || amp >= property.length() - 1) { + return property; + } + return property.substring(0, amp - 1) + + property.substring(amp + 1, property.length()); + } + /** * Returns a string from a property file, with underlined access key. Access * key can be specified in the label by &: character following character diff --git a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/WebappPreferences.java b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/WebappPreferences.java index 40cee20d9..97f2a7c5b 100644 --- a/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/WebappPreferences.java +++ b/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/WebappPreferences.java @@ -109,6 +109,14 @@ public class WebappPreferences { return getPreferenceString("titleResource"); //$NON-NLS-1$ } + public String getQuickPrintMaxConnections(){ + return getPreferenceString("maxConnections"); //$NON-NLS-1$ + } + + public String getQuickPrintMaxTopics(){ + return getPreferenceString("maxTopics"); //$NON-NLS-1$ + } + public boolean isWindowTitlePrefix() { return ProductPreferences.getBoolean(HelpBasePlugin.getDefault(), "windowTitlePrefix"); //$NON-NLS-1$ } |