/*
* JBoss, Home of Professional Open Source
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.jboss.as.cli.gui.component;
import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.RowSorter;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import org.jboss.as.cli.gui.CliGuiContext;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.client.helpers.Operations;
import org.jboss.as.controller.client.helpers.Operations.CompositeOperationBuilder;
import org.jboss.dmr.ModelNode;
/**
* The TableModel for the server logs.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
*/
public class ServerLogsTableModel extends AbstractTableModel {
private static final char[] SIZE_CHARS = {'K', 'M', 'G', 'T', 'P', 'E'};
private CliGuiContext cliGuiCtx;
private List<ModelNode> allLogs;
private ServerLogsTable table;
private final AtomicBoolean initialized = new AtomicBoolean(false);
private final TableCellRenderer dateRenderer = new DefaultTableCellRenderer() {
@Override
protected void setValue(final Object value) {
final DateFormat formatter = DateFormat.getDateTimeInstance();
setText(value == null ? "" : formatter.format(value));
}
};
private final DefaultTableCellRenderer sizeRenderer = new DefaultTableCellRenderer() {
protected void setValue(final Object value) {
final String result;
if (value instanceof Long) {
final long len = (long) value;
final int unit = 1000;
if (len < unit) {
result = len + "B";
} else {
final int exp = (int) (Math.log(len) / Math.log(unit));
result = String.format("%.1f %sB", len / Math.pow(unit, exp), SIZE_CHARS[exp - 1]);
}
} else {
result = "";
}
setText(result);
}
};
protected final String[] colNames = new String[] {"File", "Last Modified", "Size"};
public ServerLogsTableModel(CliGuiContext cliGuiCtx, ServerLogsTable table) {
this.cliGuiCtx = cliGuiCtx;
this.table = table;
sizeRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
}
/**
* Initializes the model
*/
private void init() {
if (initialized.compareAndSet(false, true)) {
final RowSorter<? extends TableModel> rowSorter = table.getRowSorter();
rowSorter.toggleSortOrder(1); // sort by date
rowSorter.toggleSortOrder(1); // descending
final TableColumnModel columnModel = table.getColumnModel();
columnModel.getColumn(1).setCellRenderer(dateRenderer);
columnModel.getColumn(2).setCellRenderer(sizeRenderer);
}
}
public void refresh() {
try {
init();
this.allLogs = getLogFiles();
fireTableDataChanged();
if (!allLogs.isEmpty()) table.setRowSelectionInterval(0, 0);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public int getRowCount() {
if (allLogs == null) return 0;
return allLogs.size();
}
@Override
public int getColumnCount() {
return colNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
ModelNode row = allLogs.get(rowIndex);
if (columnIndex == 0) return row.get("file-name").asString();
if (columnIndex == 1) {
return new Date(row.get("last-modified-time").asLong());
}
// column 2
if (columnIndex == 2) {
return row.get("file-size").asLong();
}
return null;
}
@Override
public String getColumnName(int column) {
return colNames[column];
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 1) {
return Date.class;
} else if (columnIndex == 2) {
return Long.class;
}
return String.class;
}
private List<ModelNode> getLogFiles() throws IOException {
final ModelControllerClient client = cliGuiCtx.getCommmandContext().getModelControllerClient();
final ModelNode address = new ModelNode().setEmptyList();
address.add("subsystem", "logging");
// address.add("log-file", "*");
final ModelNode op = Operations.createOperation("read-children-names", address);
op.get("child-type").set("log-file");
ModelNode response = client.execute(op);
if (Operations.isSuccessfulOutcome(response)) {
ModelNode result = Operations.readResult(response);
final Collection<String> files = new ArrayList<>();
final CompositeOperationBuilder builder = CompositeOperationBuilder.create();
for (ModelNode file : result.asList()) {
files.add(file.asString());
builder.addStep(Operations.createReadAttributeOperation(address.clone().add("log-file", file.asString()), "file-size"))
.addStep(Operations.createReadAttributeOperation(address.clone().add("log-file", file.asString()), "last-modified-time"));
}
result = client.execute(builder.build());
ModelNode fileListing = new ModelNode().setEmptyList();
if (Operations.isSuccessfulOutcome(result)) {
final List<ModelNode> attributes = Operations.readResult(result).asList();
int i = 0;
if (attributes.size() != (files.size() * 2)) {
throw new IllegalStateException("Error occurred reading the file attributes");
}
// Each file result will have two step results from the composite operation
for (String file : files) {
final ModelNode node = new ModelNode();
node.get("file-name").set(file);
node.get("file-size").set(Operations.readResult(attributes.get(i++).get(0)));
node.get("last-modified-time").set(Operations.readResult(attributes.get(i++).get(0)));
fileListing.add(node);
}
}
return fileListing.asList();
}
throw new RuntimeException(Operations.getFailureDescription(response).asString());
}
}