package atujplag.client;
import java.awt.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.rmi.RemoteException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import jplagWsClient.jplagClient.JPlagException;
import jplagWsClient.jplagClient.JPlagTyp_Stub;
import jplagWsClient.jplagClient.Option;
import jplagWsClient.jplagClient.ServerInfo;
import jplagWsClient.jplagClient.StartResultDownloadData;
import jplagWsClient.jplagClient.Status;
import jplagWsClient.util.JPlagClientAccessHandler;
import atujplag.ATUJPLAG;
import atujplag.util.Messages;
import atujplag.util.TagParser;
import atujplag.util.ZipUtil;
import atujplag.view.InfoPanel;
import atujplag.view.JPlagCreator;
public abstract class Client {
protected ServerInfo serverInfo = null;
protected ATUJPLAG atujplag = null;
/**
* START this are related to the internal state of the comparison in JPLAG
* SERVICE you will extend it with all other internal state of JPLAG SERVICE
* to have a better description of the comparison --Tchao Emeric
*/
public static final int SERVICE_UPLOADING = 0;
public static final int SERVICE_WAITING_IN_QUEUE = 50;
public static final int SERVICE_PARSING = 100;
public static final int SERVICE_COMPARING = 200;
public static final int SERVICE_COMPARE_SOURCE_DONE = 300;
public static final int SERVICE_ERROR = 400;
public static final int SERVICE_BAD_LANGUAGE_ERROR = 401;
public static final int SERVICE_NOT_ENOUGH_SUBMISSIONS_ERROR = 402;
public static final int SERVICE_BAD_PARAMETER = 403;
public static final int SERVICE_BAD_SENSITIVITY_OF_COMPARISON = 404;
public ServerInfo getServerInfo() {
return serverInfo;
}
protected JPlagClientAccessHandler accessHandler = null;
// TODO: Why is there an addition client name field inspite of Option.title?
protected String clientName;
protected String index_html = null;
protected String index_html_enc = null; // for URL encoded version
protected InfoPanel gui = null;
private int state = -1;
private String message = ""; //$NON-NLS-1$
private String details = ""; //$NON-NLS-1$
private int progress = 0;
private boolean errorOccurred = false;
protected boolean is_for_general_purpose = false;
protected Boolean modus = new Boolean(false);
protected Option options = new Option();
protected String parserlog;
protected String submissionDirectory = null;
protected Status status = null;
protected JPlagTyp_Stub stub = null;
protected String submissionID = null;
protected boolean forceStop = false;
public final static int ERROR_MESSAGE = -100;
public static final int PACKING = 0;
public static final int SENDING = 1;
public static final int WAITING = 2;
public static final int PARSING = 3;
public static final int COMPARING = 4;
public static final int LOADING = 5;
public static final int END = 6;
public static final int CANCELLING = 7;
public static final int STOPPED = 8;
protected int internalState = 0;
public Client(String clientName, ATUJPLAG atujplag) {
this.atujplag = atujplag;
if (clientName.length() > 25) {
String tmp = clientName.substring(0, 24);
this.clientName = tmp;
} else
this.clientName = clientName;
initSSL();
}
public Client(ATUJPLAG atujplag) {//String username, String password) {
this.atujplag = atujplag;
this.is_for_general_purpose = true;
initSSL();
}
protected boolean execGetStatus() {
if(isForceStop())
return false;
try {
status = stub.getStatus(this.submissionID);
} catch (JPlagException e) {
e.printStackTrace();
setState(TagParser.parse(
Messages.getString("Client.Error_occurred_{1_DESC}"), //$NON-NLS-1$
new String[] {e.getDescription()}),
TagParser.parse(Messages.getString(
"Client.Caused_by_{1_CAUSE}"), //$NON-NLS-1$
new String[] {String.valueOf(e.getCause())}),
0, internalState, false);
return false;
} catch (Exception e) {
e.printStackTrace();
setState(TagParser.parse(
Messages.getString("Client.Error_occurred_{1_DESC}"), //$NON-NLS-1$
new String[] {e.getMessage()}),
TagParser.parse(
Messages.getString("Client.Caused_by_{1_CAUSE}"), //$NON-NLS-1$
new String[] {String.valueOf(e.getCause())}),
0, internalState, false);
return false;
}
if(isForceStop())
return false;
String stateStr = stateInterpreter();
if(status.getState() < SERVICE_ERROR) {
setState(stateStr, "", status.getProgress(), //$NON-NLS-1$
internalState, true);
return true;
}
else {
setState(stateStr, "", 0, internalState, false); //$NON-NLS-1$
return false;
}
}
/**
* Sends a zipped file and all necessary options to the JPlag web service
*/
public abstract boolean compareSource();
public boolean cancelSubmission(Component parent) {
try {
if (this.getSubmissionID() != null) {
this.stub.cancelSubmission(this.submissionID);
return true;
}
return false;
} catch (RemoteException e) {
JPlagCreator.showError(parent,
Messages.getString("Client.JPlag_remote_exception"), //$NON-NLS-1$
e.getMessage());
e.printStackTrace();
return false;
} catch (JPlagException e) {
JPlagCreator.showError(parent,"JPlag exception", //$NON-NLS-1$
e.getDescription() + "\n" + e.getRepair()); //$NON-NLS-1$
return false;
}
}
/**
* @return the status of this client without invoking the RPC getStatus
*
*/
public Status get_getStatusResult() {
//this.stateInterpreter();
return this.status;
}
/**
* @return name of this clinet instance
*/
public String getClientName() {
return clientName;
}
public String getIndex_html() {
return index_html;
}
public String getEncodedIndex_html() {
return index_html_enc;
}
protected abstract JPlagTyp_Stub getJPlagStub();
protected boolean execGetResult() {
File tmp = null;
if (isForceStop())
return false;
setState(Messages.getString("Client.Loading_results"), //$NON-NLS-1$
"(0 kB / ? kB)", 0, Client.LOADING, true); //$NON-NLS-1$
try {
// Extract part
File resultdir = new File(atujplag.getResultLocation()
+ File.separator + this.clientName);
if (!resultdir.exists())
resultdir.mkdir();
else {
//overwrite
File[] files = resultdir.listFiles();
for (int i = 0; i < files.length; i++) {
ATUJPLAG.delete(files[i]);
}
}
tmp = new File(atujplag.getResultLocation()+ File.separator
+ this.clientName + ".zip"); //$NON-NLS-1$
FileOutputStream output = new FileOutputStream(tmp);
StartResultDownloadData srdd = stub.startResultDownload(
submissionID);
if(!isForceStop())
output.write(srdd.getData());
int filesize = srdd.getFilesize();
int loadedsize = srdd.getData().length;
setTransferProgress(loadedsize, filesize);
while(loadedsize<filesize && !isForceStop()) {
byte[] data = stub.continueResultDownload(0);
output.write(data);
loadedsize += data.length;
setTransferProgress(loadedsize, filesize);
}
output.close();
if(isForceStop()) {
System.gc();
tmp.delete();
return false;
}
// unzip part
File f = new File(atujplag.getResultLocation(), clientName);
ZipUtil.unzip(tmp, f);
System.gc();
tmp.delete(); // TODO: Why does this only work after a gc?
this.index_html = f.getPath() + File.separator + "index.html"; //$NON-NLS-1$
this.index_html_enc = ATUJPLAG.encodePathForURL(
atujplag.getResultLocation()) + File.separator
+ ATUJPLAG.encodeForURL(clientName) + File.separator
+ "index.html"; //$NON-NLS-1$
this.parserlog = f.getPath() + File.separator + "parser-log.txt"; //$NON-NLS-1$
setState(Messages.getString("Client.Operation_successful") //$NON-NLS-1$
+ "<br>" //$NON-NLS-1$
+ Messages.getString("Client.Result_location") //$NON-NLS-1$
+ ":<br><a href=\"" + this.index_html_enc //$NON-NLS-1$
+ "\">" + this.index_html + "</a>", //$NON-NLS-1$ //$NON-NLS-2$
"", 100, END, true); //$NON-NLS-1$
} catch (JPlagException e) {
Throwable cause = e.getCause();
setState(TagParser.parse(
Messages.getString("Client.Loading_results_error_{1_DESC}"), //$NON-NLS-1$
new String[] {e.getDescription() + "\n" + e.getRepair()}), //$NON-NLS-1$
TagParser.parse(
Messages.getString("Client.Caused_by_{1_CAUSE}"), //$NON-NLS-1$
new String[] {(cause!=null)?cause.toString():"unknown"}),
100, internalState, false);
return false;
} catch (Exception e) {
Throwable cause = e.getCause();
setState(TagParser.parse(
Messages.getString("Client.Loading_results_error_{1_DESC}"), //$NON-NLS-1$
new String[] {e.getMessage()}),
TagParser.parse(
Messages.getString("Client.Caused_by_{1_CAUSE}"), //$NON-NLS-1$
new String[] {(cause!=null)?cause.toString():"unknown"}),
100, internalState, false);
e.printStackTrace();
return false;
}
return true;
}
/**
* @return true if the operation was sucessfull
*/
public abstract boolean getResult();
/**
* @return name of the submitted file
*/
public String getSubmissionDirectory() {
return this.submissionDirectory;
}
/**
* client ask for the status of the current operation
*/
public boolean getStatus() {
return execGetStatus();
}
/**
* @return submission ID of the client instance ;
*/
public String getSubmissionID() {
return submissionID;
}
/**
* Author Moritz Kroll
*
*/
private void initSSL() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL"); //$NON-NLS-1$
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param clientName
* Client's name of the client
*/
public void setClientName(String clientName) {
this.options.setTitle(clientName);
this.clientName = clientName;
}
public String stateInterpreter() {
if (this.status != null) {
String war = ""; //$NON-NLS-1$
int tmp = this.status.getState();
if (tmp == SERVICE_UPLOADING) {
war = "Uploading... shouldn't be visible though...";
this.internalState = Client.SENDING;
} else if (tmp == SERVICE_WAITING_IN_QUEUE) {
war = TagParser.parse(Messages.getString(
"Client.Submission_is_waiting_in_queue_at_position_{1_POS}"), //$NON-NLS-1$
new String[] { (status.getProgress()+1)+"" });
this.internalState = Client.WAITING;
} else if (tmp == SERVICE_PARSING) {
war = Messages.getString("Client.Submission_is_being_parsed"); //$NON-NLS-1$
this.internalState = Client.PARSING;
} else if (tmp > SERVICE_PARSING && tmp < SERVICE_COMPARE_SOURCE_DONE) {
war = Messages.getString("Client.Submission_is_being_compared"); //$NON-NLS-1$
this.internalState = Client.COMPARING;
if(tmp>SERVICE_COMPARING) status.setProgress(100);
} else if (tmp == SERVICE_COMPARE_SOURCE_DONE) {
war = Messages.getString("Client.Comparing_source_done"); //$NON-NLS-1$
this.internalState = Client.LOADING;
} else if (tmp == SERVICE_ERROR) {
war = Messages.getString("Client.Error_occured") + ":<br>" //$NON-NLS-1$ //$NON-NLS-2$
+ this.status.getReport();
} else if (tmp == SERVICE_BAD_LANGUAGE_ERROR) {
war = Messages.getString("Client.Error") + ": " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Messages.getString("Client.Bad_language") + "<br>" //$NON-NLS-1$ //$NON-NLS-2$
+ this.status.getReport();
this.internalState = Client.PARSING;
} else if (tmp == SERVICE_BAD_PARAMETER) {
war = Messages.getString("Client.Error") + ": " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Messages.getString("Client.Bad_parameter") + "<br>" //$NON-NLS-1$ //$NON-NLS-2$
+ this.status.getReport();
this.internalState = Client.PARSING;
} else if (tmp == SERVICE_BAD_SENSITIVITY_OF_COMPARISON) {
war = Messages.getString("Client.Error") + ": " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Messages.getString("Client.Bad_sensitivity_of_comparison") //$NON-NLS-1$ //$NON-NLS-2$
+ "<br>" + this.status.getReport(); //$NON-NLS-1$
this.internalState = Client.PARSING;
} else if (tmp == SERVICE_NOT_ENOUGH_SUBMISSIONS_ERROR) {
war = Messages.getString("Client.Error") + ": " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Messages.getString("Client.Not_enough_submissions") //$NON-NLS-1$ //$NON-NLS-2$
+ "<br>" + this.status.getReport(); //$NON-NLS-1$
this.internalState = Client.PARSING;
}
return war;
}
return ""; //$NON-NLS-1$
}
public Option getOptions() {
return this.options;
}
public void setSubmissionDirectory(String sourceName) {
this.submissionDirectory = sourceName;
}
public String getParserlog() {
return this.parserlog;
}
public boolean isForceStop() {
return this.forceStop;
}
protected void setForceStop(boolean forceStop) {
this.forceStop = forceStop;
}
public void forceStop() {
forceStop = true;
}
public int getState() {
return this.state;
}
public void setState(int state) {
this.state = state;
}
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
public String getDetails() {
return this.details;
}
public void setTransferProgress(int transferred, int filesize) {
details = "(" + (transferred+1023)/1024 //$NON-NLS-1$
+ " kB / " + (filesize+1023)/1024 //$NON-NLS-1$
+ " kB)"; //$NON-NLS-1$
progress = transferred*100/filesize;
gui.invokeSetTextAndProgress(message, details, progress);
}
public int getProgress() {
return this.progress;
}
public void setProgress(int level) {
this.progress = level;
this.gui.invokeSetProgress(level);
}
public void setGui(InfoPanel gui) {
this.gui = gui;
}
public synchronized void setState(String message, String details,
int progress, int state, boolean noError) {
if(errorOccurred)
{
// TODO: Remove this
System.out.println("setState after error: message=\""+message+"\" details=\""+details+"\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return;
}
errorOccurred = !noError;
this.state = state;
this.details = details;
this.progress = progress;
this.message = message;
if(gui != null)
gui.updateStatus();
}
public boolean isErrorOccurred() {
return errorOccurred;
}
}