/*******************************************************************************
* Copyright 2012 University of Southern California
*
******************************************************************************/
package edu.isi.karma.controller.command.publish;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.isi.karma.controller.command.Command;
import edu.isi.karma.controller.command.CommandException;
import edu.isi.karma.controller.update.AbstractUpdate;
import edu.isi.karma.controller.update.ErrorUpdate;
import edu.isi.karma.controller.update.UpdateContainer;
import edu.isi.karma.geospatial.WorksheetToFeatureCollection;
import edu.isi.karma.modeling.ontology.OntologyManager;
import edu.isi.karma.modeling.semantictypes.SemanticTypeUtil;
import edu.isi.karma.rep.Worksheet;
import edu.isi.karma.rep.Workspace;
import edu.isi.karma.rep.metadata.TagsContainer.TagName;
import edu.isi.karma.util.RandomGUID;
import edu.isi.karma.view.VWorkspace;
public class PublishKMLLayerCommand extends Command {
private final String vWorksheetId;
private String publicKMLAddress;
private String kMLTransferServiceURL;
private enum JsonKeys {
updateType, fileName, localFileName, transferSuccessful
}
private static Logger logger = LoggerFactory
.getLogger(PublishKMLLayerCommand.class);
protected PublishKMLLayerCommand(String id, String vWorksheetId,
String ipAddress, String kMLTransferServiceURL) {
super(id);
this.vWorksheetId = vWorksheetId;
this.publicKMLAddress = ipAddress;
this.kMLTransferServiceURL = kMLTransferServiceURL;
}
@Override
public String getCommandName() {
return this.getClass().getSimpleName();
}
@Override
public String getTitle() {
return "Publish KML Layer";
}
@Override
public String getDescription() {
return null;
}
@Override
public CommandType getCommandType() {
return CommandType.notInHistory;
}
@Override
public UpdateContainer doIt(VWorkspace vWorkspace) throws CommandException {
Worksheet worksheet = vWorkspace.getViewFactory()
.getVWorksheet(vWorksheetId).getWorksheet();
Workspace ws = vWorkspace.getWorkspace();
if (worksheet.getSemanticTypes().getListOfTypes().size() == 0) {
SemanticTypeUtil.populateSemanticTypesUsingCRF(worksheet, ws
.getTagsContainer().getTag(TagName.Outlier), ws
.getCrfModelHandler(), ws.getOntologyManager());
}
OntologyManager om= ws.getOntologyManager();
WorksheetToFeatureCollection geo = new WorksheetToFeatureCollection(worksheet,om);//ying
//WorksheetToFeatureCollections geo = new WorksheetToFeatureCollections(worksheet);
// Send an error update if no geospatial data found!
if (geo.hasNoGeospatialData()) {
return new UpdateContainer(new ErrorUpdate(
"No geospatial data found in the worksheet!"));
}
try {
//final File file = geo.SaveSpatialData();
// Transfer the file to a public server
final String kmlFileName = geo.SaveSpatialDataAndReturnKMLString();//new RandomGUID().toString(); // save this line for using networkLink in GE plugin (see geospatial.js)
final String zippedSpatialDataPath = geo.getZippedSpatialDataPath();
final boolean transfer = true;//transferFileToPublicServer(kmlFileName,file); // save this line for using networkLink in GE plugin (see geospatial.js)
//if (!transfer) { // save this line for using networkLink in GE plugin (see geospatial.js)
// logger.error("Published KML file could not be moved to a public server to display on Google Maps!");
//}
return new UpdateContainer(new AbstractUpdate() {
@Override
public void generateJson(String prefix, PrintWriter pw,
VWorkspace vWorkspace) {
JSONObject outputObject = new JSONObject();
try {
outputObject.put(JsonKeys.updateType.name(),
"PublishKMLUpdate");
outputObject.put(JsonKeys.fileName.name(),
kmlFileName);
//publicKMLAddress + kmlFileName+".kml"); // save this line for using networkLink in GE plugin (see geospatial.js)
outputObject.put(JsonKeys.transferSuccessful.name(),
transfer);
outputObject.put(JsonKeys.localFileName.name(),
"publish/SpatialData/" + zippedSpatialDataPath);
pw.println(outputObject.toString(4));
} catch (JSONException e) {
logger.error("Error occured while generating JSON!");
}
}
});
} catch (FileNotFoundException e) {
logger.error("KML File not found!", e);
return new UpdateContainer(new ErrorUpdate(
"Error occurred while publishing KML layer!"));
} catch (Exception shapfileException) {
// TODO Auto-generated catch block
shapfileException.printStackTrace();
return new UpdateContainer(new ErrorUpdate(
"Error occurred while saving Shapefile!"));
}
}
@SuppressWarnings("deprecation")
private boolean transferFileToPublicServer(String kmlFileName,File file) {
try {
logger.info("Starting transfer of the published KML file to a public server to view it on Google Maps ...");
HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
// Request the client
FileInputStream fileInputStream = new FileInputStream(file);
URL url = new URL(kMLTransferServiceURL);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"upload\";"
+ " filename=\"" + kmlFileName + ".kml\"" + lineEnd);
dos.writeBytes(lineEnd);
// Creating a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Write the file into the form
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// Attach the necessary multipart form data after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Close streams
fileInputStream.close();
dos.flush();
dos.close();
// Get the response from the server to check if the file was copied
inStream = new DataInputStream(conn.getInputStream());
String str;
while ((str = inStream.readLine()) != null) {
if (str.equalsIgnoreCase("done")) {
logger.info("Transfer complete.");
inStream.close();
return true;
} else
return false;
}
inStream.close();
return false;
} catch (IOException e) {
logger.error("Error occured while transferring the KML file!", e);
return false;
}
}
@Override
public UpdateContainer undoIt(VWorkspace vWorkspace) {
// TODO Auto-generated method stub
return null;
}
}