001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/util/CmsRfsFileViewer.java,v $
003: * Date : $Date: 2008-03-17 14:51:21 $
004: * Version: $Revision: 1.25 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.util;
033:
034: import org.opencms.i18n.CmsEncoder;
035: import org.opencms.main.CmsIllegalArgumentException;
036: import org.opencms.main.CmsLog;
037: import org.opencms.main.CmsRuntimeException;
038: import org.opencms.main.OpenCms;
039:
040: import java.io.BufferedReader;
041: import java.io.ByteArrayOutputStream;
042: import java.io.File;
043: import java.io.FileInputStream;
044: import java.io.FileNotFoundException;
045: import java.io.IOException;
046: import java.io.InputStreamReader;
047: import java.io.LineNumberReader;
048: import java.io.OutputStreamWriter;
049: import java.nio.charset.Charset;
050: import java.nio.charset.IllegalCharsetNameException;
051: import java.nio.charset.UnsupportedCharsetException;
052: import java.util.HashMap;
053: import java.util.Map;
054: import java.util.Stack;
055:
056: import org.apache.commons.logging.Log;
057:
058: /**
059: * The representation of a RFS file along with the settings to provide
060: * access to certain portions (amount of lines) of it. <p>
061: *
062: * Most often the underlying file will be the OpenCms logfile. <p>
063: *
064: * The portion of the file that is shown is defined by a "window" of "windowSize" lines of text
065: * at a position "windowPosition" which is an enumeration of windows in ascending order. <p>
066: *
067: * @author Achim Westermann
068: *
069: * @version $Revision: 1.25 $
070: *
071: * @since 6.0.0
072: */
073: public class CmsRfsFileViewer implements Cloneable {
074:
075: /** The log object for this class. */
076: protected static final Log LOG = CmsLog
077: .getLog(CmsRfsFileViewer.class);
078:
079: /** Decides whether the view onto the underlying file via readFilePortion is enabled. */
080: private boolean m_enabled;
081:
082: /** The character encoding of the underlying file. */
083: private Charset m_fileEncoding;
084:
085: /** Maps file paths to internal info instances. */
086: protected Map m_fileName2lineIndex;
087:
088: /** The path to the underlying file. */
089: protected String m_filePath;
090:
091: /** The path to the root for all accessible files. */
092: protected String m_rootPath;
093:
094: /**
095: * If value is <code>true</code>, all setter methods will throw a
096: * <code>{@link CmsRuntimeException}</code><p>.
097: *
098: * Only the method <code>{@link #clone()}</code> returns a clone that has set this
099: * member to <code>false</code> allowing modification to take place.<p>
100: */
101: private boolean m_frozen;
102:
103: /**
104: * If true the represented file is a standard OpenCms log file and may be displayed
105: * in more convenient ways (in future versions) because the format is known.
106: */
107: private boolean m_isLogfile;
108:
109: /** The current window (numbered from zero to amount of possible different windows). */
110: protected int m_windowPos;
111:
112: /** The amount of lines to show. */
113: protected int m_windowSize;
114:
115: /**
116: * Creates an instance with default settings that tries to use the log file path obtained
117: * from <code>{@link OpenCms}'s {@link org.opencms.main.CmsSystemInfo}</code> instance.<p>
118: *
119: * If the log file path is invalid or not configured correctly a logging is performed and the
120: * path remains empty to allow user-specified file selection.<p>
121: */
122: public CmsRfsFileViewer() {
123:
124: if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
125: m_rootPath = new File(OpenCms.getSystemInfo()
126: .getLogFileRfsPath()).getParent();
127: }
128: m_isLogfile = true;
129: m_fileName2lineIndex = new HashMap();
130: // system default charset: see http://java.sun.com/j2se/corejava/intl/reference/faqs/index.html#default-encoding
131: m_fileEncoding = Charset.forName(new OutputStreamWriter(
132: new ByteArrayOutputStream()).getEncoding());
133: m_enabled = true;
134: m_windowSize = 200;
135:
136: }
137:
138: /**
139: * Internal helper that throws a <code>{@link CmsRuntimeException}</code> if the
140: * configuration of this instance has been frozen ({@link #setFrozen(boolean)}).<p>
141: *
142: * @throws CmsRuntimeException if the configuration of this instance has been frozen
143: * ({@link #setFrozen(boolean)})
144: */
145: private void checkFrozen() throws CmsRuntimeException {
146:
147: if (m_frozen) {
148: throw new CmsRuntimeException(Messages.get().container(
149: Messages.ERR_FILE_VIEW_SETTINGS_FROZEN_0));
150: }
151: }
152:
153: /**
154: * Returns a clone of this file view settings that is not "frozen" and therefore allows modifications.<p>
155: *
156: * Every instance that plans to modify settings has to obtain a clone first that may be
157: * modified. The original instance returned from
158: * (<code>{@link org.opencms.workplace.CmsWorkplaceManager#getFileViewSettings()}</code>) will throw
159: * a <code>{@link CmsRuntimeException}</code> for each setter invocation. <p>
160: *
161: * @return a clone of this file view settings that is not "frozen" and therefore allows modifications
162: */
163: public Object clone() {
164:
165: // first run after installation: filePath & rootPath is null:
166: if (m_filePath == null) {
167: // below that runlevel the following call will fail (not initialized from config yet):
168: if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
169: m_filePath = OpenCms.getSystemInfo()
170: .getLogFileRfsPath();
171: }
172: }
173: if (m_rootPath == null) {
174: if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
175: m_rootPath = new File(OpenCms.getSystemInfo()
176: .getLogFileRfsPath()).getParent();
177: }
178: }
179: CmsRfsFileViewer clone = new CmsRfsFileViewer();
180: clone.m_rootPath = m_rootPath;
181: try {
182: // strings are immutable: no outside modification possible.
183: clone.setFilePath(m_filePath);
184: } catch (CmsRfsException e) {
185: // will never happen because m_filePath was verified in setFilePath of this instance.
186: } catch (CmsRuntimeException e) {
187: // will never happen because m_filePath was verified in setFilePath of this instance.
188: }
189: clone.m_fileEncoding = m_fileEncoding;
190: clone.m_isLogfile = m_isLogfile;
191: clone.m_enabled = m_enabled;
192: //clone.m_windowPos = m_windowPos;
193: clone.setWindowSize(m_windowSize);
194: clone.m_fileName2lineIndex = m_fileName2lineIndex;
195: // allow clone-modifications.
196: clone.m_frozen = false;
197: return clone;
198: }
199:
200: /**
201: * Returns the canonical name of the character encoding of the underlying file.<p>
202: *
203: * If no special choice is fed into
204: * <code>{@link #setFileEncoding(String)}</code> before this call
205: * always the system default character encoding is returned.<p>
206: *
207: * This value may be ignored outside and will be ignored inside if the
208: * underlying does not contain textual content.<p>
209: *
210: * @return the canonical name of the character encoding of the underlying file
211: */
212: public String getFileEncoding() {
213:
214: return m_fileEncoding.name();
215: }
216:
217: /**
218: * Returns the path denoting the file that is accessed.<p>
219: *
220: * @return the path denoting the file that is accessed
221: */
222: public String getFilePath() {
223:
224: return m_filePath;
225: }
226:
227: /**
228: * Returns true if the view's internal file path points to a log file in standard OpenCms format.<p>
229: *
230: * @return true if the view's internal file path points to a log file in standard OpenCms format
231: */
232: public boolean getIsLogfile() {
233:
234: // method name is bean-convention of apache.commons.beanutils (unlike eclipse's convention for booleans)
235: return m_isLogfile;
236: }
237:
238: /**
239: * Returns the start position of the current display.<p>
240: *
241: * This is a count of "windows" that
242: * consist of viewable text with "windowSize" lines of text (for a non-standard log file) or
243: * log-entries (for a standard log file).<p>
244: *
245: * @return the start position of the current display
246: */
247: public int getWindowPos() {
248:
249: return m_windowPos;
250: }
251:
252: /**
253: * Returns the path denoting the root folder for all accessible files.<p>
254: *
255: * @return the path denoting the root folder for all accessible files
256: */
257: public String getRootPath() {
258:
259: return m_rootPath;
260: }
261:
262: /**
263: * Get the amount of lines (or entries depending on wether a standard log file is shown)
264: * to display per page. <p>
265: *
266: * @return the amount of lines to display per page
267: */
268: public int getWindowSize() {
269:
270: return m_windowSize;
271: }
272:
273: /**
274: * Returns true if this view upon the underlying file via
275: * <code>{@link #readFilePortion()}</code> is enabled.<p>
276: *
277: *
278: * @return true if this view upon the underlying file via
279: * <code>{@link #readFilePortion()}</code> is enabled.<p>
280: */
281: public boolean isEnabled() {
282:
283: return m_enabled;
284: }
285:
286: /**
287: * Return the view portion of lines of text from the underlying file or an
288: * empty String if <code>{@link #isEnabled()}</code> returns <code>false</code>.<p>
289: *
290: * @return the view portion of lines of text from the underlying file or an
291: * empty String if <code>{@link #isEnabled()}</code> returns <code>false</code>
292: * @throws CmsRfsException if something goes wrong
293: */
294: public String readFilePortion() throws CmsRfsException {
295:
296: if (m_enabled) {
297: // if we want to view the logfile we have to set the internal m_windowPos to the last window
298: // to view the end:
299: int lines = -1;
300: int startLine;
301: if (m_isLogfile) {
302: lines = scrollToFileEnd();
303: // for logfile mode we show the last window of window size:
304: // it could be possible that only 4 lines are in the last window
305: // (e.g.: 123 lines with windowsize 10 -> last window has 3 lines)
306: // so we ignore the window semantics and show the n last lines:
307: startLine = lines - m_windowSize;
308: } else {
309: m_windowPos = 0;
310: startLine = m_windowPos * m_windowSize;
311: }
312: LineNumberReader reader = null;
313: try {
314: // don't make the buffer too big, just big enough for windowSize lines (estimation: avg. of 200 characters per line)
315: // to save reading too much (this optimizes to read the first windows, much later windows will be slower...)
316: reader = new LineNumberReader(new BufferedReader(
317: new InputStreamReader(new FileInputStream(
318: m_filePath), m_fileEncoding)),
319: m_windowSize * 200);
320: int currentLine = 0;
321: // skip the lines to the current window:
322: while (startLine > currentLine) {
323: reader.readLine();
324: currentLine++;
325: }
326: StringBuffer result = new StringBuffer();
327: String read = reader.readLine();
328:
329: // logfile treatment is different
330: // we invert the lines: latest come first
331: if (m_isLogfile) {
332:
333: // stack is java hall of shame member... but standard
334: Stack inverter = new Stack();
335: for (int i = m_windowSize; (i > 0)
336: && (read != null); i--) {
337: inverter.push(read);
338: read = reader.readLine();
339: }
340: // pop-off:
341: while (!inverter.isEmpty()) {
342: result.append(inverter.pop());
343: result.append('\n');
344: }
345:
346: } else {
347:
348: for (int i = m_windowSize; (i > 0)
349: && (read != null); i--) {
350: result.append(read);
351: result.append('\n');
352: read = reader.readLine();
353: }
354: }
355: return CmsEncoder.escapeXml(result.toString());
356: } catch (IOException ioex) {
357: CmsRfsException ex = new CmsRfsException(Messages.get()
358: .container(Messages.ERR_FILE_ARG_ACCESS_1,
359: m_filePath), ioex);
360: throw ex;
361: } finally {
362: if (reader != null) {
363: try {
364: reader.close();
365: } catch (IOException e) {
366: LOG.error(e.getLocalizedMessage(), e);
367: }
368:
369: }
370: }
371: } else {
372: return Messages.get().getBundle().key(
373: Messages.GUI_FILE_VIEW_NO_PREVIEW_0);
374: }
375:
376: }
377:
378: /**
379: * Internally sets the member <code>m_windowPos</code> to the last available
380: * window of <code>m_windowSize</code> windows to let further calls to
381: * <code>{@link #readFilePortion()}</code> display the end of the file. <p>
382: *
383: * This method is triggered when a new file is chosen
384: * (<code>{@link #setFilePath(String)}</code>) because the amount of lines changes.
385: * This method is also triggered when a different window size is chosen
386: * (<code>{@link #setWindowSize(int)}</code>) because the amount of lines to display change.
387: *
388: * @return the amount of lines in the file to view
389: */
390: private int scrollToFileEnd() {
391:
392: int lines = 0;
393: if (OpenCms.getRunLevel() < OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
394: // no scrolling if system not yet fully initialized
395: } else {
396: LineNumberReader reader = null;
397: // shift the window position to the end of the file: this is expensive but OK for ocs logfiles as they
398: // are ltd. to 2 MB
399: try {
400: reader = new LineNumberReader(new BufferedReader(
401: new InputStreamReader(new FileInputStream(
402: m_filePath))));
403: while (reader.readLine() != null) {
404: lines++;
405: }
406: reader.close();
407: // if 11.75 windows are available, we don't want to end on window nr. 10
408: int availWindows = (int) Math.ceil((double) lines
409: / (double) m_windowSize);
410: // we start with window 0
411: m_windowPos = availWindows - 1;
412: } catch (IOException ioex) {
413: LOG.error("Unable to scroll file " + m_filePath
414: + " to end. Ensure that it exists. ");
415: } finally {
416: if (reader != null) {
417: try {
418: reader.close();
419: } catch (Throwable f) {
420: LOG.info("Unable to close reader of file "
421: + m_filePath, f);
422: }
423: }
424: }
425: }
426: return lines;
427: }
428:
429: /**
430: * Set the boolean that decides if the view to the underlying file via
431: * <code>{@link #readFilePortion()}</code> is enabled.<p>
432: *
433: * @param preview the boolean that decides if the view to the underlying file via
434: * <code>{@link #readFilePortion()}</code> is enabled
435: */
436: public void setEnabled(boolean preview) {
437:
438: m_enabled = preview;
439: }
440:
441: /**
442: * Set the character encoding of the underlying file.<p>
443: *
444: * The given String has to match a valid charset name (canonical or alias)
445: * of one of the system's supported <code>{@link Charset}</code> instances
446: * (see <code>{@link Charset#forName(java.lang.String)}</code>).<p>
447: *
448: * This setting will be used for transcoding the file when portions
449: * of it are read via <code>{@link CmsRfsFileViewer#readFilePortion()}</code>
450: * to a String. This enables to correctly display files with text in various encodings
451: * in UIs.<p>
452: *
453: * @param fileEncoding the character encoding of the underlying file to set.
454: */
455: public void setFileEncoding(String fileEncoding) {
456:
457: checkFrozen();
458: try {
459: m_fileEncoding = Charset.forName(fileEncoding);
460: } catch (IllegalCharsetNameException icne) {
461: throw new CmsIllegalArgumentException(Messages.get()
462: .container(Messages.ERR_CHARSET_ILLEGAL_NAME_1,
463: fileEncoding));
464: } catch (UnsupportedCharsetException ucse) {
465: throw new CmsIllegalArgumentException(Messages.get()
466: .container(Messages.ERR_CHARSET_UNSUPPORTED_1,
467: fileEncoding));
468:
469: }
470:
471: }
472:
473: /**
474: * Set the path in the real file system that points to the file
475: * that should be displayed.<p>
476: *
477: * This method will only suceed if the file specified by the <code>path</code>
478: * argument is valid within the file system, no folder and may be read by the
479: * OpenCms process on the current platform.<p>
480: *
481: * @param path the path in the real file system that points to the file that should be displayed to set
482: *
483: * @throws CmsRuntimeException if the configuration of this instance has been frozen
484: * @throws CmsRfsException if the given path is invalid, does not point to a file or cannot be accessed
485: */
486: public void setFilePath(String path) throws CmsRfsException,
487: CmsRuntimeException {
488:
489: checkFrozen();
490:
491: if (path != null) {
492: // leading whitespace from CmsComboWidget causes exception
493: path = path.trim();
494: }
495: if (CmsStringUtil.isEmpty(path)) {
496: throw new CmsRfsException(Messages.get().container(
497: Messages.ERR_FILE_ARG_EMPTY_1,
498: new Object[] { String.valueOf(path) }));
499: }
500: try {
501: // just for validation :
502: File file = new File(path);
503: if (file.isDirectory()) {
504: // if wrong configuration perform self healing:
505: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
506: // this deletes the illegal entry and will default to the log file path
507: m_filePath = null;
508: m_isLogfile = true;
509: } else {
510: throw new CmsRfsException(Messages.get().container(
511: Messages.ERR_FILE_ARG_IS_FOLDER_1,
512: new Object[] { String.valueOf(path) }));
513: }
514: } else if (!file.isFile()) {
515: // if wrong configuration perform self healing:
516: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
517: // this deletes the illegal entry and will default to the log file path
518: m_filePath = null;
519: m_isLogfile = true;
520: } else {
521: throw new CmsRfsException(Messages.get().container(
522: Messages.ERR_FILE_ARG_NOT_FOUND_1,
523: new Object[] { String.valueOf(path) }));
524: }
525:
526: } else if (!file.canRead()) {
527: // if wrong configuration perform self healing:
528: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
529: // this deletes the illegal entry and will default to the log file path
530: m_filePath = null;
531: m_isLogfile = true;
532: } else {
533: throw new CmsRfsException(Messages.get().container(
534: Messages.ERR_FILE_ARG_NOT_READ_1,
535: new Object[] { String.valueOf(path) }));
536: }
537: } else if ((m_rootPath != null)
538: && !file.getCanonicalPath().startsWith(m_rootPath)) {
539: // if wrong configuration perform self healing:
540: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
541: // this deletes the illegal entry and will default to the log file path
542: m_filePath = null;
543: m_isLogfile = true;
544: } else {
545: throw new CmsRfsException(Messages.get().container(
546: Messages.ERR_FILE_ARG_NOT_READ_1,
547: new Object[] { String.valueOf(path) }));
548: }
549: } else {
550: m_filePath = file.getCanonicalPath();
551: }
552: } catch (FileNotFoundException fnfe) {
553: // if wrong configuration perform self healing:
554: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
555: // this deletes the illegal entry and will default to the log file path
556: m_filePath = null;
557: m_isLogfile = true;
558: } else {
559:
560: throw new CmsRfsException(Messages.get().container(
561: Messages.ERR_FILE_ARG_NOT_FOUND_1,
562: new Object[] { String.valueOf(path) }), fnfe);
563: }
564:
565: } catch (IOException ioex) {
566: // if wrong configuration perform self healing:
567: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
568: // this deletes the illegal entry and will default to the log file path
569: m_filePath = null;
570: m_isLogfile = true;
571: } else {
572:
573: throw new CmsRfsException(Messages.get().container(
574: Messages.ERR_FILE_ARG_ACCESS_1,
575: new Object[] { String.valueOf(path) }), ioex);
576: }
577:
578: }
579: }
580:
581: /**
582: * Package friendly access that allows the <code>{@link org.opencms.workplace.CmsWorkplaceManager}</code>
583: * to "freeze" this instance within the system-wide assignment in it's
584: * <code>{@link org.opencms.workplace.CmsWorkplaceManager#setFileViewSettings(org.opencms.file.CmsObject, CmsRfsFileViewer)}</code> method.<p>
585: *
586: * @param frozen if true this instance will freeze and throw <code>CmsRuntimeExceptions</code> upon setter invocations
587: *
588: * @throws CmsRuntimeException if the configuration of this instance has been frozen
589: * ({@link #setFrozen(boolean)})
590: *
591: */
592: public void setFrozen(boolean frozen) throws CmsRuntimeException {
593:
594: m_frozen = frozen;
595: }
596:
597: /**
598: * Set if the internal file is in standard logfile format (true) or not (false).<p>
599: *
600: * If set to true the file might be
601: * treated / displayed in a more convenient format than standard files in future.
602: * Currently it is only inverted (last lines appear first) and only the last
603: * <code>windowsize</code> lines of the file are displayed.<p>
604: *
605: * Do not activate this (it is possible from the log file viewer settings in the workplace
606: * administration) if your selected file is no log file: The display will confuse you and
607: * be more expensive (imaging scrolling a 20 MB file to view the last 200 lines). <p>
608: *
609: * @param isLogfile determines if the internal file is in standard logfile format (true) or not (false)
610: *
611: * @throws CmsRuntimeException if the configuration of this instance has been frozen
612: * ({@link #setFrozen(boolean)})
613: */
614: public void setIsLogfile(boolean isLogfile)
615: throws CmsRuntimeException {
616:
617: checkFrozen();
618: m_isLogfile = isLogfile;
619: }
620:
621: /**
622: * Set the path in the real file system that points to the folder/tree
623: * containing the logfiles.<p>
624: *
625: * This method will only suceed if the folder specified by the <code>path</code>
626: * argument is valid within the file system.<p>
627: *
628: * @param path the path in the real file system that points to the folder containing the logfiles
629: *
630: * @throws CmsRuntimeException if the configuration of this instance has been frozen
631: * @throws CmsRfsException if the given path is invalid
632: */
633: public void setRootPath(String path) throws CmsRfsException,
634: CmsRuntimeException {
635:
636: checkFrozen();
637:
638: if (path != null) {
639: // leading whitespace from CmsComboWidget causes exception
640: path = path.trim();
641: }
642: if (CmsStringUtil.isEmpty(path)) {
643: throw new CmsRfsException(Messages.get().container(
644: Messages.ERR_FILE_ARG_EMPTY_1,
645: new Object[] { String.valueOf(path) }));
646: }
647: try {
648: // just for validation :
649: File file = new File(path);
650: if (file.exists()) {
651: m_rootPath = file.getCanonicalPath();
652: } else {
653: // if wrong configuration perform self healing:
654: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
655: // this deletes the illegal entry
656: m_rootPath = new File(OpenCms.getSystemInfo()
657: .getLogFileRfsPath()).getParent();
658: } else {
659:
660: throw new CmsRfsException(Messages.get().container(
661: Messages.ERR_FILE_ARG_NOT_FOUND_1,
662: new Object[] { String.valueOf(path) }));
663: }
664: }
665: } catch (IOException ioex) {
666: // if wrong configuration perform self healing:
667: if (OpenCms.getRunLevel() == OpenCms.RUNLEVEL_2_INITIALIZING) {
668: // this deletes the illegal entry and will default to the log file path
669: m_rootPath = new File(OpenCms.getSystemInfo()
670: .getLogFileRfsPath()).getParent();
671: } else {
672:
673: throw new CmsRfsException(Messages.get().container(
674: Messages.ERR_FILE_ARG_ACCESS_1,
675: new Object[] { String.valueOf(path) }), ioex);
676: }
677: }
678: }
679:
680: /**
681: * Sets the start position of the current display.<p>
682: *
683: * This is a count of "windows" that
684: * consist of viewable text with "windowSize" lines of text (for a non-standard log file) or
685: * log-entries (for a standard log file).<p>
686: *
687: * @param windowPos the start position of the current display to set
688: * @throws CmsRuntimeException if the configuration of this instance has been frozen
689: * ({@link #setFrozen(boolean)})
690: */
691: public void setWindowPos(int windowPos) throws CmsRuntimeException {
692:
693: checkFrozen();
694: m_windowPos = windowPos;
695: }
696:
697: /**
698: * Set the amount of lines (or entries depending on wether a standard log file is shown)
699: * to display per page.<p>
700: *
701: * @param windowSize the amount of lines to display per page
702: * @throws CmsRuntimeException if the configuration of this instance has been frozen
703: * ({@link #setFrozen(boolean)})
704: *
705: */
706: public void setWindowSize(int windowSize)
707: throws CmsRuntimeException {
708:
709: checkFrozen();
710: m_windowSize = windowSize;
711: }
712: }
|