/*******************************************************************************
* Copyright (c) Feb 17, 2012 Zend Technologies Ltd.
* 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
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.zend.sdklib.application;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.zend.sdklib.internal.application.ZendConnection;
import org.zend.sdklib.mapping.IMappingLoader;
import org.zend.sdklib.target.ITargetLoader;
import org.zend.webapi.core.WebApiClient;
import org.zend.webapi.core.WebApiException;
import org.zend.webapi.core.connection.data.CodeTrace;
import org.zend.webapi.core.connection.data.CodeTraceFile;
import org.zend.webapi.core.connection.data.CodeTracingList;
import org.zend.webapi.core.connection.data.CodeTracingStatus;
import org.zend.webapi.core.connection.data.CodeTracingStatus.State;
import org.zend.webapi.core.progress.BasicStatus;
import org.zend.webapi.core.progress.StatusCode;
/**
* Utility class which provides methods to perform operation related to code
* tracing feature provided by Zend Server.
*
* @author Wojciech Galanciak, 2012
*/
public class ZendCodeTracing extends ZendConnection {
private String targetId;
private int offset;
public ZendCodeTracing(String targetId) {
super();
this.targetId = targetId;
}
public ZendCodeTracing(String targetId, IMappingLoader mappingLoader) {
super(mappingLoader);
this.targetId = targetId;
}
public ZendCodeTracing(String targetId, ITargetLoader loader) {
super(loader);
this.targetId = targetId;
}
public ZendCodeTracing(String targetId, ITargetLoader loader,
IMappingLoader mappingLoader) {
super(loader, mappingLoader);
this.targetId = targetId;
}
/**
* Enables code tracing feature on Zend Server.
*
* @return code tracing status
* @throws WebApiException
*/
public CodeTracingStatus enable() throws WebApiException {
return enable(false);
}
/**
* Enables code tracing feature on Zend Server.
*
* @param restartPhp
* restart php during operation
* @return code tracing status
* @throws WebApiException
*/
public CodeTracingStatus enable(boolean restartPhp) throws WebApiException {
try {
return getClient(targetId).codeTracingEnable(restartPhp);
} catch (MalformedURLException e) {
String message = MessageFormat.format(
"Error during enabling code tracing for '{0}'", targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Enabling Code Tracing", message, e));
log.error(e);
}
return null;
}
/**
* Disables code tracing feature on Zend Server.
*
* @return code tracing status
* @throws WebApiException
*/
public CodeTracingStatus disable() throws WebApiException {
return disable(false);
}
/**
* Disables code tracing feature on Zend Server.
*
* @param restartPhp
* restart php during operation
* @return code tracing status
* @throws WebApiException
*/
public CodeTracingStatus disable(boolean restartPhp) throws WebApiException {
try {
return getClient(targetId).codeTracingDisable(restartPhp);
} catch (MalformedURLException e) {
String message = MessageFormat.format(
"Error during disabling code tracing for '{0}'", targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Disabling Code Tracing", message, e));
log.error(e);
}
return null;
}
/**
* Provides status of code tracing feature.
*
* @return <code>true</code> if code tracing is enabled; <code>false</code>
* otherwise.
*/
public boolean isEnabled() {
try {
CodeTracingStatus status = getClient(targetId)
.codeTracingIsEnabled();
return status.getTraceEnabled() == State.ON ? true : false;
} catch (WebApiException e) {
String message = MessageFormat.format(
"Error during checking code tracing state for '{0}'",
targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Checking Code Tracing State", message, e));
log.error(message + "':");
log.error("\tpossible error: " + e.getMessage());
} catch (MalformedURLException e) {
String message = MessageFormat.format(
"Error during checking code tracing state for '{0}'",
targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Checking Code Tracing State", message, e));
log.error(e);
}
return false;
}
/**
* Creates code trace for provided URL.
*
* @param url
* for which code trace should be generated
* @return created code trace
*/
public CodeTrace createTrace(URL url) {
try {
return getClient(targetId).codeTracingCreate(url.toString());
} catch (WebApiException e) {
String message = MessageFormat
.format("Error during creating code tracing for for '{0}' url on '{1}'",
url.toString(), targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Creating Code Tracing", message, e));
log.error(message + "':");
log.error("\tpossible error: " + e.getMessage());
} catch (MalformedURLException e) {
String message = MessageFormat
.format("Error during creating code tracing for for '{0}' url on '{1}'",
url.toString(), targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Creating Code Tracing", message, e));
log.error(e);
}
return null;
}
/**
* Deletes code trace with specified id.
*
* @param id
* code trace id
* @return deleted code trace
*/
public CodeTrace deleteTrace(String id) {
try {
return getClient(targetId).codeTracingDelete(id);
} catch (WebApiException e) {
String message = MessageFormat
.format("Error during deleting code tracing with id = {0}, on '{1}' target",
id, targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Deleting Code Tracing", message, e));
log.error(message + "':");
log.error("\tpossible error: " + e.getMessage());
} catch (MalformedURLException e) {
String message = MessageFormat
.format("Error during deleting code tracing with id = {0}, on '{1}' target",
id, targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Deleting Code Tracing", message, e));
log.error(e);
}
return null;
}
/**
* Provides list of code traces for this application. If passed argument is
* <code>true</code>, first call of this method returns all code traces
* generated for concrete application and each next call returns only code
* traces generated after last call. If argument is <code>false</code>, it
* provides all code traces which are available (without remembering the
* offset).
*
* @param all
* if it is <code>true</code> all code traces are returned,
* otherwise only those which were created after last call of
* this method
* @param appId
* application(s) id, if not provided then returns traces for all
* applications
* @return list of code traces
*/
public List<CodeTrace> getTraces(boolean all, String... appId) {
try {
if (all) {
return getAllTraces(appId);
} else {
CodeTracingList list = offset != 0 ? getClient(targetId)
.codeTracingList(null,
offset, null, null, appId) : getClient(targetId)
.codeTracingList(null, offset, null, null, appId);
offset += list.getTraces().size();
return list.getTraces();
}
} catch (WebApiException e) {
String message = MessageFormat
.format("Error during retrieving code traces for '{0}' application(s) on '{1}'",
Arrays.toString(appId), targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Retrieving Code Traces", message, e));
log.error(message + "':");
log.error("\tpossible error: " + e.getMessage());
} catch (MalformedURLException e) {
String message = MessageFormat
.format("Error during retrieving code traces for '{0}' application(s) on '{1}'",
Arrays.toString(appId), targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Retrieving Code Traces", message, e));
log.error(e);
}
return null;
}
/**
* Provides code trace file for specified trace id.
*
* @param traceId
* @return code trace file
*/
public File get(String traceId) {
return get(traceId, getTempFolder());
}
/**
* Provides code trace file for specified trace id.
*
* @param traceId
* @param destination
* location where code trace file will be stored
* @return code trace file
*/
public File get(String traceId, File destination) {
try {
CodeTraceFile codeTraceFile = getClient(targetId)
.codeTracingDownloadTraceFile(traceId);
File file = new File(destination, codeTraceFile.getFilename());
if (file.exists()) {
file.delete();
}
file.createNewFile();
FileOutputStream stream = new FileOutputStream(file);
stream.write(codeTraceFile.getFileContent());
closeStream(stream);
if (file.length() == codeTraceFile.getFileSize()) {
return file;
} else {
log.error("Invalid file size.");
}
} catch (WebApiException e) {
String message = MessageFormat.format(
"Error during downloading code trace from '{0}'", targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Downloading Code Trace", message, e));
log.error(message + "':");
log.error("\tpossible error: " + e.getMessage());
} catch (MalformedURLException e) {
String message = MessageFormat.format(
"Error during downloading code trace from '{0}'", targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Downloading Code Trace", message, e));
log.error(e);
} catch (IOException e) {
String message = MessageFormat.format(
"Error during downloading code trace from '{0}'", targetId);
notifier.statusChanged(new BasicStatus(StatusCode.ERROR,
"Downloading Code Trace", message, e));
log.error(e);
}
return null;
}
private List<CodeTrace> getAllTraces(String... appId)
throws MalformedURLException, WebApiException {
WebApiClient client = getClient(targetId);
List<CodeTrace> result = new ArrayList<CodeTrace>();
int offset = 0;
while (true) {
CodeTracingList list = client.codeTracingList(50, offset, null,
null, appId);
if (list != null) {
List<CodeTrace> newTraces = list.getTraces();
if (newTraces != null && newTraces.size() > 0) {
result.addAll(newTraces);
offset += 50;
} else {
return result;
}
}
}
}
}