/*
* Copyright 2013 Hewlett-Packard Development Company, L.P
*
* 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 com.hp.alm.ali.idea.rest;
import com.hp.alm.ali.idea.util.ApplicationUtil;
import com.hp.alm.ali.rest.client.exception.AuthenticationFailureException;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.project.Project;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.TestOnly;
import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
public class TroubleShootService implements RestServiceLogger {
private PrintStream fos;
private long requestId;
private long lastNotification;
private long notificationDelay = 60000;
final Notification serviceNotification;
public TroubleShootService() {
serviceNotification = new Notification("HP ALM Integration", "Troubleshooting mode is on and all REST " +
"communication is being tracked.",
"<p>Don't forget to <a href=\"\">stop tracking</a> when no longer needed.</p>", NotificationType.INFORMATION,
new NotificationListener() {
public void hyperlinkUpdate(Notification notification, HyperlinkEvent event) {
notification.expire();
stop();
}
});
}
public synchronized boolean isRunning() {
return fos != null;
}
public synchronized void stop() {
if(fos != null) {
fos.flush();
fos = null;
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
serviceNotification.expire();
}
});
}
}
public synchronized void start(File file) {
if(fos != null) {
throw new IllegalStateException("Troubleshooting already running");
}
if(file == null) {
throw new IllegalArgumentException("file == null");
}
try {
fos = new PrintStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public synchronized long request(final Project project, String methodName, MyInputData input, String template, Object... params) {
long id = ++requestId;
if(fos != null) {
fos.println(">>>>> request: #" + id + " at " + new Date());
fos.println(">>>>> " + methodName + " " + template + " " + Arrays.asList(params));
if(project != null) {
fos.println(">>>>> project: " + project.getName());
}
if(input != null) {
Map<String, String> headers = input.getHeaders();
if(headers != null) {
fos.println(">>>>> headers: "+ headers);
}
String requestData = input.getRequestData();
if(requestData!= null) {
fos.println(">>>>> data: "+ requestData);
}
}
fos.flush();
long now = System.currentTimeMillis();
if(id % 10 == 0 && now >= lastNotification + notificationDelay && project != null) {
lastNotification = now;
ApplicationUtil.invokeLater(new Runnable() {
public void run() {
serviceNotification.expire();
Notifications.Bus.notify(serviceNotification, project);
}
});
}
}
return id;
}
public synchronized void response(long id, int status, MyResultInfo result) {
if(fos != null) {
fos.println("<<<<< response: #" + id + " at " + new Date());
fos.println("<<<<< status: " +status);
fos.println("<<<<< headers: "+ result.getHeaders());
fos.println("<<<<< data: "+ result.getBodyAsString());
fos.flush();
}
}
public synchronized void loginFailure(long id, AuthenticationFailureException e) {
if(fos != null) {
fos.println("<<<<< login failure: #" + id + " at " + new Date());
fos.println("<<<<< "+e.getMessage());
fos.flush();
}
}
@TestOnly
void _setNotificationDelay(long delay) {
this.notificationDelay = delay;
}
@TestOnly
void _reset() {
requestId = 0;
}
}