X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=org.argeo.slc.client.ui%2Fsrc%2Forg%2Fargeo%2Fslc%2Fclient%2Fui%2Feditors%2FProcessLogPage.java;fp=org.argeo.slc.client.ui%2Fsrc%2Forg%2Fargeo%2Fslc%2Fclient%2Fui%2Feditors%2FProcessLogPage.java;h=0fb27e95e98d9be026fa3a883b1b6448995ffac1;hb=2db415932b071525adb52c6374e021174512a924;hp=0000000000000000000000000000000000000000;hpb=7e2f6c6ae08e97925955184aaa29035ac05de149;p=gpl%2Fargeo-slc.git diff --git a/org.argeo.slc.client.ui/src/org/argeo/slc/client/ui/editors/ProcessLogPage.java b/org.argeo.slc.client.ui/src/org/argeo/slc/client/ui/editors/ProcessLogPage.java new file mode 100644 index 000000000..0fb27e95e --- /dev/null +++ b/org.argeo.slc.client.ui/src/org/argeo/slc/client/ui/editors/ProcessLogPage.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.client.ui.editors; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Workspace; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventListener; +import javax.jcr.query.Query; + +import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.jcr.SlcNames; +import org.argeo.slc.jcr.SlcTypes; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; + +public class ProcessLogPage extends FormPage { + public final static String ID = "processLogPage"; + + private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + + /** Where the log is displayed. */ + private Text text; + /** + * Stores logs received before the text was shown. TODO : rather store in in + * JCR and reads it from there. + */ + private StringBuffer beforeTextInit = new StringBuffer(""); + + private Node processNode; + /** + * optimization field: we compute once the length of the path to slc:log so + * that we can easily substring the relative path of logs. + */ + //private Integer logPathLength; + + public ProcessLogPage(FormEditor editor, Node processNode) { + super(editor, ID, "Log"); + this.processNode = processNode; + + EventListener listener = new LogListener(editor.getSite().getPage() + .getWorkbenchWindow().getWorkbench().getDisplay()); + + try { + String logBasePath = processNode.getPath() + '/' + SlcNames.SLC_LOG; + //logPathLength = logBasePath.length(); + + Workspace ws = processNode.getSession().getWorkspace(); + + String statement = "SELECT * FROM [" + + SlcTypes.SLC_LOG_ENTRY + + "] as logEntry" + + " WHERE ISDESCENDANTNODE('" + + logBasePath + + "')" + + " ORDER BY logEntry.[slc:timestamp] ASC, NAME(logEntry) ASC"; + StringBuffer buf = new StringBuffer(""); + NodeIterator it = ws.getQueryManager() + .createQuery(statement, Query.JCR_SQL2).execute() + .getNodes(); + while (it.hasNext()) + appendLogEntry(buf, it.nextNode()); + beforeTextInit = new StringBuffer(buf.toString()); + // text.setText(buf.toString()); + ws.getObservationManager().addEventListener(listener, + Event.NODE_ADDED, logBasePath, true, null, null, false); + } catch (RepositoryException e) { + throw new SlcException("Cannot register listener", e); + } + } + + @Override + public synchronized void createPartControl(Composite parent) { + // bypass createFormContent + FormToolkit tk = getEditor().getToolkit(); + // parent.setLayout(new FillLayout()); + text = tk.createText(parent, "", SWT.MULTI | SWT.H_SCROLL + | SWT.V_SCROLL); + text.setEditable(false); + + // transfer the existing buffer the first time + if (beforeTextInit.length() > 0) { + text.append(beforeTextInit.toString()); + // clear buffer + beforeTextInit.setLength(0); + } + + } + + // @Override + // protected synchronized void createFormContent(IManagedForm mf) { + // ScrolledForm form = mf.getForm(); + // form.setExpandHorizontal(true); + // form.setExpandVertical(true); + // // form.setText("Log"); + // FillLayout mainLayout = new FillLayout(); + // form.getBody().setLayout(mainLayout); + // + // FormToolkit tk = getManagedForm().getToolkit(); + // text = tk.createText(form.getBody(), "", SWT.MULTI | SWT.H_SCROLL + // | SWT.V_SCROLL); + // text.setEditable(false); + // // transfer the existing buffer the first time + // if (beforeTextInit.length() > 0) { + // text.append(beforeTextInit.toString()); + // // clear buffer + // beforeTextInit.setLength(0); + // } + // } + + protected void appendLogEntry(StringBuffer buf, Node logEntry) + throws RepositoryException { + // +1 in order to remove the first slash +// String relPath = logEntry.getPath().substring(logPathLength + 1); + //System.out.println("relPath=" + relPath); +// int firstSlashIndex = relPath.indexOf('/'); +// int lastSlashIndex = relPath.lastIndexOf('/'); +// String thread = relPath.substring(0, firstSlashIndex); +// String location = relPath.substring(firstSlashIndex, lastSlashIndex); + + // String date = dateFormat.format(logEntry + // .getProperty(SlcNames.SLC_TIMESTAMP).getDate().getTime()); + String date = logEntry.getProperty(SlcNames.SLC_TIMESTAMP).getString(); + buf.append(date).append(' '); + String type = logEntry.getPrimaryNodeType().getName().substring(7); + buf.append(type).append('\t'); + // buf.append(thread).append('\t'); + // buf.append(location).append('\t'); + buf.append(logEntry.getProperty(SlcNames.SLC_MESSAGE).getString()); + buf.append('\n'); + + } + + /** @deprecated */ + public synchronized void addSteps(List steps) { + final StringBuffer buf = new StringBuffer(""); + for (ExecutionStep step : steps) { + buf.append(dateFormat.format(step.getTimestamp())); + buf.append(' '); + if (step.getType().equals(ExecutionStep.PHASE_START)) { + buf.append("## START ").append(step.getLog()); + buf.append('\n'); + } else if (step.getType().equals(ExecutionStep.PHASE_END)) { + buf.append("## END ").append(step.getLog()); + buf.append("\n"); + } else { + buf.append(step.getLog()); + } + } + + if (text != null) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + text.append(buf.toString()); + } + }); + } else + beforeTextInit.append(buf); + } + + @Override + public Control getPartControl() { + return text; + } + + @Override + public void setFocus() { + if (text != null) + text.setFocus(); + } + + /** JCR event listener notifying when new nodes are added */ + private class LogListener extends AsyncUiEventListener { + + public LogListener(Display display) { + super(display); + } + + @Override + protected void onEventInUiThread(List events) + throws RepositoryException { + // since we use batch save, order is not guaranteed + // so we need to reorder, according to log line number for the time + // being + SortedMap nodes = new TreeMap(); + + for (Event evt : events) { + Node newNode = ProcessLogPage.this.processNode.getSession() + .getNode(evt.getPath()); + if (newNode.isNodeType(SlcTypes.SLC_LOG_ENTRY)) { + nodes.put(Long.parseLong(newNode.getName()), newNode); + } + } + + StringBuffer buf = new StringBuffer(""); + for (Node logEntry : nodes.values()) { + appendLogEntry(buf, logEntry); + } + + if (text != null) + text.append(buf.toString()); + else + beforeTextInit.append(buf); + } + } +}