package org.openflexo.builders.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipException;
import org.apache.commons.io.IOUtils;
import org.openflexo.builders.FlexoExternalMain;
import org.openflexo.foundation.FlexoEditor;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.FlexoProject.FlexoProjectReferenceLoader;
import org.openflexo.foundation.rm.FlexoProjectReference;
import org.openflexo.foundation.utils.ProjectInitializerException;
import org.openflexo.foundation.utils.ProjectLoadingCancelledException;
import org.openflexo.module.ProjectLoader;
import org.openflexo.toolbox.FileUtils;
import org.openflexo.toolbox.ZipUtils;
public class FlexoBuilderProjectReferenceLoader implements FlexoProjectReferenceLoader {
private String serverURL;
private String login;
private String password;
private final FlexoExternalMain externalMain;
private final ProjectLoader projectLoader;
public FlexoBuilderProjectReferenceLoader(FlexoExternalMain externalMain, ProjectLoader projectLoader, String serverURL, String login,
String password) {
super();
this.externalMain = externalMain;
this.projectLoader = projectLoader;
this.serverURL = serverURL;
this.login = login;
this.password = password;
}
@Override
public FlexoProject loadProject(FlexoProjectReference reference, boolean silentlyOnly) {
FlexoEditor editor = projectLoader.editorForProjectURIAndRevision(reference.getURI(), reference.getRevision());
if (editor != null) {
return editor.getProject();
}
if (silentlyOnly) {
return null;
}
if (serverURL != null && login != null && password != null) {
Map<String, String> param = new HashMap<String, String>();
param.put("login", login);
param.put("password", password);
param.put("uri", reference.getURI());
param.put("revision", String.valueOf(reference.getRevision()));
param.put("greaterOrEqual", "true");
StringBuilder paramsAsString = new StringBuilder();
if (param != null && param.size() > 0) {
boolean first = true;
for (Entry<String, String> e : param.entrySet()) {
paramsAsString.append(first ? "" : "&");
try {
paramsAsString.append(URLEncoder.encode(e.getKey(), "UTF-8")).append("=")
.append(URLEncoder.encode(e.getValue(), "UTF-8"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
first = false;
}
}
// Create a URL for the desired page
URL url;
try {
url = new URL(serverURL);
} catch (MalformedURLException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because server URL seems misconfigured: '" + serverURL + "'" + ".\n(" + e.getMessage() + ")");
return null;
}
HttpURLConnection conn;
try {
conn = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker cannot access server URL '" + url.toString() + "'" + ".\n(" + e.getMessage() + ")");
return null;
}
try {
conn.setRequestMethod("POST");
} catch (ProtocolException e) {
e.printStackTrace();
// Should never happen
}
conn.setDoOutput(true);
OutputStreamWriter wr;
try {
wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(paramsAsString.toString());
wr.flush();
} catch (IOException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker cannot open server URL '" + url.toString() + "'" + ".\n(" + e.getMessage() + ")");
return null;
}
// Read all the text returned by the server
int httpStatus;
try {
httpStatus = conn.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker could not read HTTP response code for server URL '" + url.toString() + "'.\n(" + e.getMessage()
+ ")");
return null;
}
InputStream inputStream;
if (httpStatus < 400) {
try {
inputStream = conn.getInputStream();
} catch (IOException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker could not read data for server URL '" + url.toString() + "'.\n(" + e.getMessage() + ")"
+ "\nStatus: " + httpStatus);
return null;
}
String base = "Projects/" + reference.getName() + "_" + reference.getVersion();
File file = new File(externalMain.getWorkingDir(), base + ".zip");
int i = 0;
while (file.exists()) {
file = new File(externalMain.getWorkingDir(), base + "-" + i++ + ".zip");
}
file.getParentFile().mkdirs();
try {
FileUtils.saveToFile(file, inputStream);
} catch (IOException e) {
e.printStackTrace();
}
base = "ExtractedProjects/" + reference.getName() + "_" + reference.getVersion();
File extractionDirectory = new File(externalMain.getWorkingDir(), base);
i = 0;
while (extractionDirectory.exists()) {
extractionDirectory = new File(externalMain.getWorkingDir(), base + "-" + i++);
}
extractionDirectory.mkdirs();
try {
ZipUtils.unzip(file, extractionDirectory);
} catch (ZipException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker could not read the zip file returned by server URL '" + url.toString() + "'.\n("
+ e.getMessage() + ")");
return null;
} catch (IOException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker could not extract the zip file returned by server URL '" + url.toString()
+ "' to the directory " + extractionDirectory.getAbsolutePath() + ".\n(" + e.getMessage() + ")");
return null;
}
File projectDirectory = FlexoExternalMain.searchProjectDirectory(extractionDirectory);
if (projectDirectory == null) {
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because worker could not find a project in the directory " + extractionDirectory.getAbsolutePath() + ".");
return null;
}
try {
editor = projectLoader.loadProject(projectDirectory, true);
} catch (ProjectLoadingCancelledException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because project loading was cancelled for directory " + projectDirectory.getAbsolutePath() + ".\n("
+ e.getMessage() + ")");
return null;
} catch (ProjectInitializerException e) {
e.printStackTrace();
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because project loading failed for directory " + projectDirectory.getAbsolutePath() + ".\n("
+ e.getMessage() + ")");
return null;
}
if (editor != null) {
return editor.getProject();
} else {
externalMain.reportMessage("Unable to load project " + reference.getName() + " " + reference.getVersion()
+ " located at " + projectDirectory.getAbsolutePath() + ".");
return null;
}
} else {
inputStream = conn.getErrorStream();
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
String str;
StringBuilder reply = new StringBuilder();
try {
while ((str = in.readLine()) != null) {
reply.append(str).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(wr);
IOUtils.closeQuietly(in);
}
if (httpStatus == 404) {
externalMain.reportMessage("Unable to find " + reference.getName() + " " + reference.getVersion() + "(Revision: "
+ reference.getRevision() + "). Make sure that you have uploaded that project with that revision");
return null;
} else {
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because an error occured for server URL '" + url.toString() + "'" + ".\nStatus: " + httpStatus + "\n"
+ reply.toString());
return null;
}
}
} else {
externalMain.reportMessage("Unable to load " + reference.getName() + " " + reference.getVersion()
+ " because information and credentials are incomplete (server URL=" + serverURL + " login="
+ (login != null ? "OK" : "null") + " password=" + (password != null ? "OK" : "null"));
return null;
}
}
}