/*
* File : TCPReporter.java
* Created : 17-jul-2001 9:39
* By : fbusquets
*
* JClic - Authoring and playing system for educational activities
*
* Copyright (C) 2000 - 2005 Francesc Busquets & Departament
* d'Educacio de la Generalitat de Catalunya
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details (see the LICENSE file).
*/
package edu.xtec.jclic.report;
import edu.xtec.jclic.Activity;
import edu.xtec.jclic.project.JClicProject;
import edu.xtec.util.Domable;
import edu.xtec.util.JDomUtility;
import edu.xtec.util.Messages;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.Timer;
/**
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.09.10
*/
public class TCPReporter extends Reporter {
protected String currentSessionId;
protected ActivityReg lastActivity;
protected int actCount;
protected URL serviceUrl;
protected HashMap<String, String> dbProperties;
protected List<TCPReportBean> tasks;
protected Component parent;
protected Messages msg;
protected Timer timer;
protected int timerLap;
public static final String
SERVER_PATH="path", DEFAULT_SERVER_PATH="localhost:9000",
SERVER_PROTOCOL="protocol", DEFAULT_SERVER_PROTOCOL="http",
SERVER_SERVICE="service", DEFAULT_SERVER_SERVICE="/JClicReportService",
TIMER_LAP="lap";
public static final int DEFAULT_TIMER_LAP=20;
/** Creates new TCPReporter */
public TCPReporter(){
super();
currentSessionId=null;
lastActivity=null;
actCount=0;
serviceUrl=null;
tasks=new ArrayList<TCPReportBean>();
timerLap=DEFAULT_TIMER_LAP;
}
protected synchronized void flushTasks(){
if(!tasks.isEmpty() && serviceUrl!=null){
TCPReportBean bean=new TCPReportBean(TCPReportBean.MULTIPLE);
TCPReportBean[] items;
//synchronized(tasks){
items=tasks.toArray(new TCPReportBean[tasks.size()]);
//}
for(TCPReportBean item : items)
bean.addElement(item.getJDomElement());
if(transaction(bean)!=null){
for(TCPReportBean item : items)
tasks.remove(item);
}
}
}
@Override
public void end(){
super.end();
reportActivity();
flushTasks();
stopReporting();
}
protected void checkUrl() throws Exception{
if(serviceUrl==null)
throw new Exception("Service not available!!");
}
protected TCPReportBean transaction(String key, Domable[] data){
return transaction(new TCPReportBean(key, data));
}
protected TCPReportBean transaction(TCPReportBean request){
if(serviceUrl==null)
return null;
TCPReportBean result=null;
boolean loop=true;
while(result==null && loop){
try{
HttpURLConnection con=(HttpURLConnection)serviceUrl.openConnection();
con.setDoOutput(true);
// 7-july-2006
// Content-type header defaults to "application/x-www-form-urlencoded"
// Changed to "text/xml" in order to be compliant with PHP.
con.setRequestProperty("Content-type", "text/xml");
OutputStream out=con.getOutputStream();
JDomUtility.saveDocument(out, request.getJDomElement());
out.flush();
out.close();
InputStream in=con.getInputStream();
org.jdom.Document doc=JDomUtility.getSAXBuilder().build(con.getInputStream());
result=new TCPReportBean(doc.getRootElement());
}
catch(Exception ex){
if(msg!=null){
int r=msg.showErrorWarning(parent, "report_err_connect", ex, "ric");
switch(r){
case Messages.RETRY:
break;
case Messages.IGNORE:
loop=false;
break;
default:
stopReporting();
loop=false;
break;
}
}
else{
stopReporting();
loop=false;
}
}
}
return result;
}
protected void stopReporting(){
if(serviceUrl!=null){
serviceUrl=null;
if(description!=null && msg!=null)
description=description + " ("+msg.get("report_not_connected")+")";
}
if(timer!=null && timer.isRunning()){
timer.stop();
}
initiated=false;
}
@Override
public void init(HashMap properties, Component parent, Messages msg) throws Exception{
this.parent=parent;
this.msg=msg;
boolean success=false;
try{
super.init(properties, parent, msg);
String serverPath=(String)properties.get(SERVER_PATH);
if(serverPath==null)
serverPath=DEFAULT_SERVER_PATH;
description="TCP/IP "+serverPath;
String serverService=(String)properties.get(SERVER_SERVICE);
if(serverService==null)
serverService=DEFAULT_SERVER_SERVICE;
if(serverPath.length()<1 || serverService.length()<1)
throw new Exception("Bad server specification!");
if(!serverService.startsWith("/"))
serverService+="/";
String serverProtocol=(String)properties.get(SERVER_PROTOCOL);
if(serverProtocol==null)
serverProtocol=DEFAULT_SERVER_PROTOCOL;
serviceUrl=new URL(serverProtocol+"://"+serverPath+serverService);
if(userId==null)
userId=promptUserId(parent, msg);
if(userId!=null)
success=true;
} catch(Exception ex){
msg.showErrorWarning(parent, "report_err_init", description, ex, null);
}
if(success){
String tl=getProperty(TIME_LAP, Integer.toString(timerLap));
timerLap=Math.min(300, Math.max(1, Integer.parseInt(tl)));
timer=new Timer(timerLap*1000, new ActionListener(){
public void actionPerformed(ActionEvent ev){
flushTasks();
}
});
timer.setRepeats(true);
timer.start();
}
else{
stopReporting();
}
}
@Override
public void newSession(JClicProject jcp, Component parent, Messages msg){
super.newSession(jcp, parent, msg);
if(serviceUrl==null)
return;
if(userId==null){
try{
userId=promptUserId(parent, msg);
} catch(Exception ex){
msg.showErrorWarning(parent, "error_getting_user", ex);
}
}
if(userId!=null){
// ---------------
//reportActivity();
// ---------------
currentSessionId=null;
}
}
public void createDBSession(){
if(initiated && userId!=null){
flushTasks();
currentSessionId=null;
actCount=0;
TCPReportBean bean=new TCPReportBean(TCPReportBean.ADD_SESSION);
bean.setParam(TCPReportBean.PROJECT, currentSession.projectName);
bean.setParam(TCPReportBean.TIME, Long.toString(currentSession.timeMillis));
bean.setParam(TCPReportBean.CODE, currentSession.code);
bean.setParam(TCPReportBean.USER, userId);
bean.setParam(TCPReportBean.KEY, sessionKey);
bean.setParam(TCPReportBean.CONTEXT, sessionContext);
bean=transaction(bean);
if(bean!=null)
currentSessionId=bean.getParam(TCPReportBean.SESSION);
if(currentSessionId==null)
stopReporting();
}
}
protected void reportActivity(){
if(lastActivity!=null){
if(!lastActivity.closed)
lastActivity.closeActivity();
if(currentSessionId==null)
createDBSession();
if(currentSessionId!=null){
TCPReportBean bean=new TCPReportBean(TCPReportBean.ADD_ACTIVITY);
bean.setParam(TCPReportBean.SESSION, currentSessionId);
bean.setParam(TCPReportBean.NUM, Integer.toString(actCount++));
bean.setData(lastActivity);
tasks.add(bean);
}
}
if(currentSession!=null && currentSession.currentSequence!=null
&& currentSession.currentSequence.currentActivity!=lastActivity){
lastActivity=currentSession.currentSequence.currentActivity;
} else
lastActivity=null;
}
@Override
public String getProperty(String key, String defaultValue) throws Exception{
if(dbProperties==null){
dbProperties=new HashMap<String, String>();
TCPReportBean bean=transaction(new TCPReportBean(TCPReportBean.GET_PROPERTIES));
if(bean==null)
return defaultValue;
dbProperties.putAll(bean.getParams());
}
String result=(String)dbProperties.get(key);
if(result==null)
result=defaultValue;
return result;
}
@Override
public List<GroupData> getGroups() throws Exception{
TCPReportBean bean=transaction(TCPReportBean.GET_GROUPS, null);
if(bean==null)
return new ArrayList<GroupData>();
Domable[] data=bean.getData();
ArrayList<GroupData> result=new ArrayList<GroupData>(data.length);
//result.addAll(Arrays.asList(data));
for(Domable d : data)
if(d instanceof GroupData)
result.add((GroupData)d);
return result;
}
@Override
public List<UserData> getUsers(String groupId) throws Exception{
TCPReportBean bean=new TCPReportBean(TCPReportBean.GET_USERS);
bean.setParam(TCPReportBean.GROUP, groupId);
bean=transaction(bean);
if(bean==null)
return new ArrayList<UserData>();
Domable[] data=bean.getData();
ArrayList<UserData> result=new ArrayList<UserData>(data.length);
//result.addAll(Arrays.asList(data));
for(Domable d : data)
if(d instanceof UserData)
result.add((UserData)d);
return result;
}
@Override
public UserData getUserData(String userId) throws Exception{
UserData result=null;
TCPReportBean bean=new TCPReportBean(TCPReportBean.GET_USER_DATA);
bean.setParam(TCPReportBean.USER, userId);
if((bean=transaction(bean))!=null)
result=(UserData)bean.getSingleData();
return result;
}
@Override
public GroupData getGroupData(String groupId) throws Exception{
GroupData result=null;
TCPReportBean bean=new TCPReportBean(TCPReportBean.GET_GROUP_DATA);
bean.setParam(TCPReportBean.GROUP, groupId);
if((bean=transaction(bean))!=null)
result=(GroupData)bean.getSingleData();
return result;
}
@Override
public String newGroup(GroupData gd) throws Exception{
String result=null;
TCPReportBean bean=new TCPReportBean(TCPReportBean.NEW_GROUP);
bean.setData(gd);
if((bean=transaction(bean))!=null)
result=(String)bean.getParam(TCPReportBean.GROUP);
return result;
}
@Override
public String newUser(UserData ud) throws Exception{
String result=null;
TCPReportBean bean=new TCPReportBean(TCPReportBean.NEW_USER);
bean.setData(ud);
if((bean=transaction(bean))!=null)
result=(String)bean.getParam(TCPReportBean.USER);
return result;
}
@Override
public void newActivity(Activity act){
super.newActivity(act);
reportActivity();
}
}