diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilePanel.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilePanel.java index f9f8d60fd..0538cd1f2 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilePanel.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilePanel.java @@ -38,6 +38,8 @@ import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import edu.ycp.cs.dh.acegwt.client.ace.AceEditor; + +import org.jboss.as.console.client.Console; import org.jboss.as.console.client.shared.runtime.logging.store.LogFile; import org.jboss.ballroom.client.widgets.tools.ToolButton; import org.jboss.ballroom.client.widgets.tools.ToolStrip; @@ -62,9 +64,11 @@ public class LogFilePanel extends Composite implements LogFilesId { private final VerticalPanel panel; private final AceEditor editor; private final HandlerRegistration resizeHandler; + private final LogFilesPresenter presenter; - public LogFilePanel(final LogFile logFile) { + public LogFilePanel(final LogFile logFile, LogFilesPresenter presenter) { this.name = logFile.getName(); + this.presenter = presenter; panel = new VerticalPanel(); panel.addStyleName("fill-layout-width"); @@ -170,11 +174,16 @@ public void onClick(ClickEvent event) { findNext.getElement().setAttribute("action", "findNext"); // AceEditor action wiring setId(findNext, BASE_ID + editorId, "next_match"); + ToolButton refresh = new ToolButton(Console.CONSTANTS.common_label_refresh(), + event -> presenter.onRefreshLogFile(name)); + ToolStrip searchTools = new ToolStrip(); searchTools.addToolWidget(findTextBox); searchTools.addToolButton(findButton); searchTools.addToolWidget(findPrev); searchTools.addToolWidget(findNext); + searchTools.addToolButton(refresh); + searchTools.getElement().getStyle().setPaddingLeft(0, PX); searchTools.getElement().getStyle().setMarginBottom(0.5, EM); findTextBox.getElement().getStyle().setWidth(30, EM); @@ -188,6 +197,7 @@ public void onClick(ClickEvent event) { findPrev.getElement().getParentElement().getStyle().setVerticalAlign(MIDDLE); findNext.getElement().getStyle().setHeight(25, PX); findNext.getElement().getParentElement().getStyle().setVerticalAlign(MIDDLE); + refresh.getElement().getStyle().setMarginLeft(1, EM); // next part: rebuild the original search box FlowPanel searchForm = div("ace_search_form", false); diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesPresenter.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesPresenter.java index d6ebebb62..5f099514d 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesPresenter.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesPresenter.java @@ -21,7 +21,9 @@ */ package org.jboss.as.console.client.shared.runtime.logging.files; -import com.google.gwt.core.client.GWT; +import static org.jboss.as.console.client.shared.runtime.logging.store.LogStore.FILE_NAME; +import static org.jboss.as.console.client.shared.runtime.logging.store.LogStore.FILE_SIZE; + import com.google.inject.Inject; import com.google.web.bindery.event.shared.EventBus; import com.gwtplatform.mvp.client.View; @@ -33,10 +35,11 @@ import org.jboss.as.console.client.core.CircuitPresenter; import org.jboss.as.console.client.core.HasPresenter; import org.jboss.as.console.client.core.NameTokens; -import org.jboss.as.console.client.core.UIConstants; import org.jboss.as.console.client.shared.runtime.logging.store.LogFile; import org.jboss.as.console.client.shared.runtime.logging.store.LogStore; import org.jboss.as.console.client.shared.runtime.logging.store.ReadLogFiles; +import org.jboss.as.console.client.shared.runtime.logging.store.ReadLogFilesForRefresh; +import org.jboss.as.console.client.shared.runtime.logging.store.RefreshLogFile; import org.jboss.as.console.client.shared.runtime.logging.store.SelectLogFile; import org.jboss.as.console.client.shared.runtime.logging.store.StreamLogFile; import org.jboss.as.console.client.shared.subsys.RevealStrategy; @@ -94,7 +97,7 @@ public LogFilesPresenter(EventBus eventBus, MyView view, MyProxy proxy, RevealSt this.circuit = circuit; this.logStore = logStore; this.hostStore = hostStore; - this.streamingProgress = new StreamingProgress(circuit, logStore, SHOW_STREAM_IN_PROGRESS_TIMEOUT); + this.streamingProgress = new StreamingProgress(logStore, SHOW_STREAM_IN_PROGRESS_TIMEOUT); } @Override @@ -114,6 +117,15 @@ public void onAction(Action action) { streamingProgress.done(); getView().open(logStore.getActiveLogFile()); + } else if (action instanceof ReadLogFilesForRefresh) { + getView().list(logStore.getLogFiles()); + String name = ((ReadLogFilesForRefresh) action).getName(); + refreshLogFile(name); + + } else if (action instanceof RefreshLogFile) { + streamingProgress.done(); + getView().refresh(logStore.getActiveLogFile()); + } else if (action instanceof SelectLogFile) { getView().open(logStore.getActiveLogFile()); @@ -152,12 +164,45 @@ public void onStreamLogFile(final String logFile, final int fileSize) { Console.CONSTANTS.downloadingLogFileConfirmation(), isConfirmed -> { if (isConfirmed) { + this.circuit.dispatch(new StreamLogFile(logFile)); streamingProgress.monitor(logFile); } }); } else { + this.circuit.dispatch(new StreamLogFile(logFile)); streamingProgress.monitor(logFile); } } } + + public void onRefreshLogFile(final String logFile) { + circuit.dispatch(new ReadLogFilesForRefresh(logFile)); + } + + private void refreshLogFile(String name) { + ModelNode fileNode = null; + for (ModelNode node: logStore.getLogFiles()) { + if (node.get(FILE_NAME).asString().equals(name)) { + fileNode = node; + break; + } + } + if (fileNode != null) { + int fileSize = fileNode.get(FILE_SIZE).asInt(); + if (fileSize > LOG_FILE_SIZE_THRESHOLD) { + Feedback.confirm( + Console.CONSTANTS.downloadLogFile(), + Console.CONSTANTS.downloadingLogFileConfirmation(), + isConfirmed -> { + if (isConfirmed) { + this.circuit.dispatch(new RefreshLogFile(name)); + streamingProgress.monitor(name); + } + }); + } else { + this.circuit.dispatch(new RefreshLogFile(name)); + streamingProgress.monitor(name); + } + } + } } diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTable.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTable.java index 2dde28751..8254027ef 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTable.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTable.java @@ -21,7 +21,6 @@ */ package org.jboss.as.console.client.shared.runtime.logging.files; -import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -36,9 +35,9 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SingleSelectionModel; import org.jboss.as.console.client.Console; -import org.jboss.as.console.client.core.UIConstants; import org.jboss.as.console.client.shared.runtime.logging.store.DownloadLogFile; import org.jboss.as.console.client.shared.runtime.logging.store.LogStore; +import org.jboss.as.console.client.shared.runtime.logging.store.ReadLogFiles; import org.jboss.as.console.client.widgets.ContentDescription; import org.jboss.as.console.mbui.widgets.ModelNodeCellTable; import org.jboss.ballroom.client.widgets.ContentHeaderLabel; @@ -136,6 +135,13 @@ public void onClick(ClickEvent event) { view.setOperationAddress("/{implicit.host}/{selected.server}/subsystem=logging/log-file=*", "read-log-file"); setId(view, BASE_ID, "view"); tools.addToolButtonRight(view); + + final ToolButton refresh = new ToolButton(Console.CONSTANTS.common_label_refresh(), + event -> circuit.dispatch(new ReadLogFiles())); + refresh.setOperationAddress("/{implicit.host}/{selected.server}/subsystem=logging", "read-resource"); + setId(refresh, BASE_ID, "refresh"); + tools.addToolButtonRight(refresh); + panel.add(tools); // table @@ -189,6 +195,7 @@ public String getValue(ModelNode node) { nameColumn.setSortable(true); sortHandler.setComparator(nameColumn, new NameComparator()); table.addColumn(nameColumn, "Log File Name"); + table.getColumnSortList().push(nameColumn); // column: last modified TextColumn lastModifiedColumn = new TextColumn() { @@ -242,7 +249,6 @@ public void list(List files) { list.addAll(files); // Make sure the new values are properly sorted - table.getColumnSortList().push(nameColumn); ColumnSortEvent.fire(table, table.getColumnSortList()); } diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTabs.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTabs.java index ef5452d7a..3b1209310 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTabs.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesTabs.java @@ -36,8 +36,11 @@ public class LogFilesTabs extends Composite { private final DefaultTabLayoutPanel tabLayout; + private final LogFilesPresenter presenter; + + public LogFilesTabs(final Dispatcher circuit, LogFilesPresenter presenter) { + this.presenter = presenter; - public LogFilesTabs(final Dispatcher circuit) { tabLayout = new DefaultTabLayoutPanel(40, Style.Unit.PX, true, true); tabLayout.addSelectionHandler(event -> { LogFilePanel logFilePanel = selectedLogFilePanel(); @@ -67,7 +70,7 @@ public void reset() { public void open(LogFile logFile) { if (!tabLayout.contains(logFile.getName())) { - tabLayout.add(new LogFilePanel(logFile), logFile.getName()); + tabLayout.add(new LogFilePanel(logFile, presenter), logFile.getName()); } tabLayout.selectTab(logFile.getName()); } diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesView.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesView.java index d1c09a82f..26ddebea2 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesView.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/LogFilesView.java @@ -50,7 +50,7 @@ public void setPresenter(LogFilesPresenter presenter) { @Override public Widget createWidget() { - logFilesTabs = new LogFilesTabs(circuit); + logFilesTabs = new LogFilesTabs(circuit, presenter); logFiles = new LogFilesTable(circuit, presenter); logFilesTabs.add(logFiles.asWidget(), "Log Files"); return logFilesTabs; diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/StreamingProgress.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/StreamingProgress.java index 7f1ef400a..ec4aae1c8 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/StreamingProgress.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/files/StreamingProgress.java @@ -21,7 +21,6 @@ */ package org.jboss.as.console.client.shared.runtime.logging.files; -import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -30,12 +29,9 @@ import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.PopupPanel; import org.jboss.as.console.client.Console; -import org.jboss.as.console.client.core.UIConstants; import org.jboss.as.console.client.shared.patching.ui.Pending; import org.jboss.as.console.client.shared.runtime.logging.store.LogStore; import org.jboss.as.console.client.shared.runtime.logging.store.LogStore.PendingStreamingRequest; -import org.jboss.as.console.client.shared.runtime.logging.store.StreamLogFile; -import org.jboss.gwt.circuit.Dispatcher; import static org.jboss.as.console.client.shared.runtime.logging.files.LogFilesId.BASE_ID; import static org.jboss.as.console.client.shared.util.IdHelper.WidgetType.BUTTON; @@ -50,16 +46,14 @@ public class StreamingProgress extends PopupPanel { private final static int WIDTH = 360; private final static int HEIGHT = 200; - private final Dispatcher circuit; private final int timeout; private final Button cancel; private String logFile; private boolean pending; - public StreamingProgress(final Dispatcher circuit, final LogStore logStore, int timeout) { + public StreamingProgress(final LogStore logStore, int timeout) { super(false, true); - this.circuit = circuit; this.timeout = timeout; setWidth(WIDTH + "px"); @@ -90,7 +84,6 @@ public void onClick(ClickEvent event) { public void monitor(final String logFile) { this.logFile = logFile; - this.circuit.dispatch(new StreamLogFile(logFile)); // deferred show pending = true; diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/LogStore.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/LogStore.java index a66e2fed0..05d36c13f 100644 --- a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/LogStore.java +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/LogStore.java @@ -113,7 +113,7 @@ public class LogStore extends ChangeSupport { protected int pageSize; /** - * Flag to pause the {@link LogStore.RefreshLogFile} command + * Flag to pause the {@link RefreshLogFileCmd} command * when the related log view is no longer visible. */ protected boolean pauseFollow; @@ -179,6 +179,11 @@ public void onSuccess(DMRResponse result) { }); } + @Process(actionType = ReadLogFilesForRefresh.class) + public void readLogFilesForRefresh(final Dispatcher.Channel channel) { + readLogFiles(channel); + } + @Process(actionType = OpenLogFile.class) public void openLogFile(final OpenLogFile action, final Dispatcher.Channel channel) { final LogFile logFile = states.get(action.getName()); @@ -222,38 +227,7 @@ public void streamLogFile(final StreamLogFile action, final Dispatcher.Channel c final LogFile logFile = states.get(action.getName()); if (logFile == null) { - RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, encode(streamUrl(action.getName()))); - requestBuilder.setHeader("Accept", "text/plain"); - requestBuilder.setHeader("Content-Type", "text/plain"); - requestBuilder.setIncludeCredentials(true); - try { - // store the request in order to cancel it later - pendingStreamingRequest = new PendingStreamingRequest(action.getName(), - requestBuilder.sendRequest(null, new RequestCallback() { - @Override - public void onResponseReceived(Request request, Response response) { - if (response.getStatusCode() >= 400) { - channel.nack(new IllegalStateException("Failed to stream log file " + - action.getName() + ": " + response.getStatusCode() + " - " + - response.getStatusText())); - } else { - LogFile newLogFile = new LogFile(action.getName(), response.getText()); - newLogFile.setFollow(false); - states.put(action.getName(), newLogFile); - activate(newLogFile); - channel.ack(); - } - } - - @Override - public void onError(Request request, Throwable exception) { - channel.nack(exception); - } - }), channel); - } catch (RequestException e) { - channel.nack(e); - } - + doStreamLogFile(action.getName(), channel); } else { // already streamed, just activate activate(logFile); @@ -261,6 +235,45 @@ public void onError(Request request, Throwable exception) { } } + @Process(actionType = RefreshLogFile.class) + public void refreshLogFile(final RefreshLogFile action, final Dispatcher.Channel channel) { + doStreamLogFile(action.getName(), channel); + } + + private void doStreamLogFile(final String fileName, final Dispatcher.Channel channel) { + RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, encode(streamUrl(fileName))); + requestBuilder.setHeader("Accept", "text/plain"); + requestBuilder.setHeader("Content-Type", "text/plain"); + requestBuilder.setIncludeCredentials(true); + try { + // store the request in order to cancel it later + pendingStreamingRequest = new PendingStreamingRequest(fileName, + requestBuilder.sendRequest(null, new RequestCallback() { + @Override + public void onResponseReceived(Request request, Response response) { + if (response.getStatusCode() >= 400) { + channel.nack(new IllegalStateException("Failed to stream log file " + + fileName + ": " + response.getStatusCode() + " - " + + response.getStatusText())); + } else { + LogFile newLogFile = new LogFile(fileName, response.getText()); + newLogFile.setFollow(false); + states.put(fileName, newLogFile); + activate(newLogFile); + channel.ack(); + } + } + + @Override + public void onError(Request request, Throwable exception) { + channel.nack(exception); + } + }), channel); + } catch (RequestException e) { + channel.nack(e); + } + } + @Process(actionType = DownloadLogFile.class) public void downloadLogFile(final DownloadLogFile action, final Dispatcher.Channel channel) { Window.open(streamUrl(action.getName()), "", ""); @@ -501,7 +514,7 @@ protected void activate(LogFile logFile) { } private void startFollowing(LogFile logFile) { - scheduler.scheduleFixedDelay(new RefreshLogFile(logFile.getName()), FOLLOW_INTERVAL); + scheduler.scheduleFixedDelay(new RefreshLogFileCmd(logFile.getName()), FOLLOW_INTERVAL); } private String streamUrl(final String name) { @@ -634,11 +647,11 @@ public void cancel() { // ------------------------------------------------------ polling - private class RefreshLogFile implements Scheduler.RepeatingCommand { + private class RefreshLogFileCmd implements Scheduler.RepeatingCommand { private final String name; - private RefreshLogFile(String name) { + private RefreshLogFileCmd(String name) { this.name = name; } diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/ReadLogFilesForRefresh.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/ReadLogFilesForRefresh.java new file mode 100644 index 000000000..e754691ae --- /dev/null +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/ReadLogFilesForRefresh.java @@ -0,0 +1,56 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2010, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.as.console.client.shared.runtime.logging.store; + +import org.jboss.gwt.circuit.Action; + +/** + * Downloads the entire log file using the streaming feature of the log-file resource. Be sure to call this action + * only if the log file does not exceed a reasonable file size. + * @author Harald Pehl + */ +public class ReadLogFilesForRefresh implements Action { + + private final String name; + + public ReadLogFilesForRefresh(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ReadLogFilesForRefresh)) return false; + + ReadLogFilesForRefresh that = (ReadLogFilesForRefresh) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + public String getName() { + return name; + } +} diff --git a/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/RefreshLogFile.java b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/RefreshLogFile.java new file mode 100644 index 000000000..38de677ec --- /dev/null +++ b/gui/src/main/java/org/jboss/as/console/client/shared/runtime/logging/store/RefreshLogFile.java @@ -0,0 +1,56 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2010, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.as.console.client.shared.runtime.logging.store; + +import org.jboss.gwt.circuit.Action; + +/** + * Downloads the entire log file using the streaming feature of the log-file resource. Be sure to call this action + * only if the log file does not exceed a reasonable file size. + * @author Harald Pehl + */ +public class RefreshLogFile implements Action { + + private final String name; + + public RefreshLogFile(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RefreshLogFile)) return false; + + RefreshLogFile that = (RefreshLogFile) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + public String getName() { + return name; + } +}