/**
SpagoBI, the Open Source Business Intelligence suite
Copyright (C) 2012 Engineering Ingegneria Informatica S.p.A. - SpagoBI Competency Center
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file,
You can obtain one at http://mozilla.org/MPL/2.0/.
**/
package it.eng.spagobi.studio.core.services.datamartTemplate;
import it.eng.spagobi.meta.editor.business.dialogs.BusinessModelRelationshipsCheckWarningDialog;
import it.eng.spagobi.meta.editor.physical.dialogs.DeleteElementsWarningForUploadDialog;
import it.eng.spagobi.meta.initializer.BusinessModelInitializer;
import it.eng.spagobi.meta.initializer.PhysicalModelInitializer;
import it.eng.spagobi.meta.initializer.utils.Pair;
import it.eng.spagobi.meta.model.Model;
import it.eng.spagobi.meta.model.ModelObject;
import it.eng.spagobi.meta.model.business.BusinessModel;
import it.eng.spagobi.meta.model.business.BusinessRelationship;
import it.eng.spagobi.meta.model.serializer.EmfXmiSerializer;
import it.eng.spagobi.meta.querybuilder.model.ModelManager;
import it.eng.spagobi.studio.core.util.ComboSelectionDialog;
import it.eng.spagobi.studio.utils.bo.DataSource;
import it.eng.spagobi.studio.utils.bo.Document;
import it.eng.spagobi.studio.utils.bo.Domain;
import it.eng.spagobi.studio.utils.bo.Template;
import it.eng.spagobi.studio.utils.exceptions.NoActiveServerException;
import it.eng.spagobi.studio.utils.services.SpagoBIServerObjectsFactory;
import it.eng.spagobi.studio.utils.util.SpagoBIStudioConstants;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.util.ByteArrayDataSource;
import org.eclipse.core.internal.resources.File;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UploadDatamartTemplateService {
ISelection selection;
private static Logger logger = LoggerFactory.getLogger(UploadDatamartTemplateService.class);
String projectname = null;
String modelFileName = null;
DataSource[] dataSources = null;
Domain[] domains = null;
String userDataSource = null;
String userCategory = null;
String messageStatusDocument = "";
boolean documentAlreadyPresent = false;
boolean modelAlreadyPresent = false;
public static final String DATAMART_JAR = "datamart.jar";
public static final String CALCULATED_FIELD = "cfields_meta.xml";
public UploadDatamartTemplateService(ISelection _selection) {
selection = _selection;
}
public boolean datamartUpload() {
logger.debug("IN");
IStructuredSelection sel = (IStructuredSelection) selection;
// go on only if is selected a document
Object objSel = sel.toList().get(0);
File fileSel = (File) objSel;
projectname = fileSel.getProject().getName();
modelFileName = fileSel.getName();
logger.debug("get datamart.jar of model file name " + fileSel.getName());
// refresh metadata_model folder
refreshModelFolder(fileSel);
EmfXmiSerializer emfXmiSerializer = new EmfXmiSerializer();
Model root = null;
BusinessModel businessModel = null;
try {
root = emfXmiSerializer.deserialize(fileSel.getContents(true));
logger.debug("Model root is [{}] ", root);
businessModel = root.getBusinessModels().get(0);
logger.debug("model " + businessModel.getName());
} catch (Exception e) {
logger.error("error in retrieving business model; try refreshing model folder ", e);
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Warning",
"error in retrieving business model: try refreshing model folder");
return false;
}
// First, check if there are any physical model objects marked as deleted
PhysicalModelInitializer physicalModelInitializer = new PhysicalModelInitializer();
List<ModelObject> markedElements = physicalModelInitializer.getElementsMarkedAsDeleted(businessModel.getPhysicalModel());
if (!markedElements.isEmpty()) {
DeleteElementsWarningForUploadDialog warningDialog = new DeleteElementsWarningForUploadDialog(markedElements);
warningDialog.create();
warningDialog.setBlockOnOpen(true);
warningDialog.open();
}
if (markedElements.isEmpty()) {
// check the constraints for hibernate mappings
BusinessModelInitializer businessModelInitializer = new BusinessModelInitializer();
List<Pair<BusinessRelationship, Integer>> incorrectRelationships = businessModelInitializer.checkRelationshipsConstraints(businessModel);
int relationshipsWarningReturnCode = Window.CANCEL;
if (!incorrectRelationships.isEmpty()) {
BusinessModelRelationshipsCheckWarningDialog warningDialog = new BusinessModelRelationshipsCheckWarningDialog(incorrectRelationships);
warningDialog.create();
warningDialog.setBlockOnOpen(true);
relationshipsWarningReturnCode = warningDialog.open();
}
if (incorrectRelationships.isEmpty() || relationshipsWarningReturnCode == Window.OK) {
return generateJarAndUpload(businessModel, fileSel);
}
}
return false;
}
// ******* Runnable block for checking if dopcumetnAlready exists ***********
IRunnableWithProgress getMonitorCheckExistance(final BusinessModel businessModel, final SpagoBIServerObjectsFactory spagoBIServerObjects, final File fileSel) {
IRunnableWithProgress opCheck = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("check if there is already document with name " + businessModel.getName() + " ", IProgressMonitor.UNKNOWN);
String modelname = businessModel.getName();
logger.debug("is there documetn with llabel " + modelname);
try {
Document doc = spagoBIServerObjects.getServerDocuments().getDocumentByLabel(modelname);
Template templateModel = spagoBIServerObjects.getServerDocuments().downloadDatamartFile(modelname, fileSel.getName());
if (doc != null) {
documentAlreadyPresent = true;
messageStatusDocument = "Detail: QBEDocument with label " + modelname + " was not added because already present in server";
} else {
documentAlreadyPresent = false;
}
if (templateModel != null) {
modelAlreadyPresent = true;
messageStatusDocument += "\n Detail: Meta Model with label " + modelname + " was not added because already present in server";
} else {
modelAlreadyPresent = false;
}
} catch (RemoteException e2) {
logger.error("error in uploading datamart", e2);
throw new InvocationTargetException(e2);
}
}
};
return opCheck;
}
// ******* Runnable block for retrieving datasources ***********
IRunnableWithProgress getMonitorForDatasources(final BusinessModel businessModel, final SpagoBIServerObjectsFactory spagoBIServerObjects) {
IRunnableWithProgress opDs = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("Retrieving data sources for selection)", IProgressMonitor.UNKNOWN);
logger.debug("get Datasources defined");
try {
UploadDatamartTemplateService.this.dataSources = spagoBIServerObjects.getServerDataSources().getDataSourceList();
} catch (RemoteException e2) {
logger.error("error in getting datasource", e2);
throw new InvocationTargetException(e2);
}
}
};
return opDs;
}
// ******* Runnable block for retrieving Category ***********
IRunnableWithProgress getMonitorForCategory(final BusinessModel businessModel, final SpagoBIServerObjectsFactory spagoBIServerObjects) {
IRunnableWithProgress opDs = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("Retrieving categories for selection)", IProgressMonitor.UNKNOWN);
logger.debug("get categories defined");
try {
UploadDatamartTemplateService.this.domains = spagoBIServerObjects.getServerDomains().getDomainsListByDomainCd("BM_CATEGORY");
} catch (RemoteException e2) {
logger.error("error in getting categories", e2);
throw new InvocationTargetException(e2);
}
}
};
return opDs;
}
// ******* Runnable block for upload ***********
IRunnableWithProgress getMonitorForUpload(final BusinessModel businessModel, final SpagoBIServerObjectsFactory spagoBIServerObjects,
final java.io.File datamartFile, final File businessModelFile) {
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("Deploying model files (datamart.jar " + modelFileName + ")", IProgressMonitor.UNKNOWN);
Template datamartTemplate = new Template();
Template modelTemplate = new Template();
// no more passed as separate file
// Template xmlCalcFieldsTemplate = new Template();
// defines properties for datamart file
datamartTemplate.setFileName(datamartFile.getName());
datamartTemplate.setFolderName(businessModel.getName());
// create templates content
FileDataSource fileDataSource = new FileDataSource(datamartFile);
DataHandler dataHandler = new DataHandler(fileDataSource);
datamartTemplate.setContent(dataHandler);
logger.debug("built Datamart template with content data handler");
// defines properties for sbimodel file
modelTemplate.setFileName(modelFileName);
modelTemplate.setFolderName(businessModel.getName());
// defines properties for xml Calculated fields file
// if(xmlFile != null){
// xmlCalcFieldsTemplate.setFileName(xmlFile.getName());
// xmlCalcFieldsTemplate.setFolderName(businessModel.getName());
// // create templates content
// FileDataSource xmlDataSource=new FileDataSource(xmlFile);
// DataHandler xmlDataHandler=new DataHandler(xmlDataSource);
//
// xmlCalcFieldsTemplate.setContent(xmlDataHandler);
// logger.debug("built xml calculated fields with content data handler");
// }
// create templates content
try {
ByteArrayDataSource byteDataSource = new ByteArrayDataSource(businessModelFile.getContents(), "application/octet-stream");
dataHandler = new DataHandler(byteDataSource);
modelTemplate.setContent(dataHandler);
logger.debug("built Model template with content data handler");
} catch (Exception e) {
logger.error("error in getting model template", e);
throw new InvocationTargetException(e);
}
try {
spagoBIServerObjects.getServerDocuments().uploadDatamartTemplate(datamartTemplate, null, userDataSource, userCategory); // null stands for
// no more passed
// cfields.xml file
}
catch (RemoteException e2) {
logger.error("error in uploading datamart", e2);
throw new InvocationTargetException(e2);
}
try {
spagoBIServerObjects.getServerDocuments().uploadDatamartModel(modelTemplate);
} catch (RemoteException e3) {
logger.error("error in uploading model file", e3);
throw new InvocationTargetException(e3);
}
if (documentAlreadyPresent == false) {
messageStatusDocument = "Detail: QBE Document with label " + businessModel.getName() + " added to server";
}
monitor.done();
if (monitor.isCanceled())
logger.error("Operation not ended", new InterruptedException("The long running operation was cancelled"));
}
};
return op;
}
boolean generateJarAndUpload(BusinessModel businessModel, File fileSel) {
// generate the jar
// Create temp dir
long ll = System.currentTimeMillis();
String UUID = Long.valueOf(ll).toString();
String tempDirPath = System.getProperty("java.io.tmpdir");
logger.debug("Temp dir is: " + tempDirPath + " check if ends with " + java.io.File.pathSeparator);
if (!tempDirPath.endsWith(java.io.File.separator)) {
tempDirPath += java.io.File.separator;
}
String idFolderPath = businessModel.getName() + "_" + UUID;
String tempDirPathId = tempDirPath + idFolderPath;
logger.debug("create model in temporary folder " + tempDirPathId);
try {
ModelManager modelManager = new ModelManager(businessModel.getParentModel());
modelManager.setMappingsFolder(new java.io.File(tempDirPathId));
modelManager.setModelFile(fileSel);
modelManager.generateMapping(false);
} catch (Exception e) {
logger.error("Error in generating the datamart for model " + businessModel.getName(), e);
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", "Error in generating datamart.jar for model "
+ businessModel.getName());
return false;
}
logger.debug("model datamart.jar created in " + tempDirPathId);
// search for file datamart.jar, is rooted in the folder created
String pathToSearch = tempDirPathId + java.io.File.separator + businessModel.getName() + java.io.File.separator + "dist" + java.io.File.separator
+ DATAMART_JAR;
logger.debug("try reatrieving datamart.jar file " + pathToSearch);
Path tmppath = new Path(pathToSearch);
java.io.File datamart = tmppath.toFile();
if (datamart == null) {
logger.error("could not retrieve file " + pathToSearch);
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", "could not retrieve file " + pathToSearch);
return false;
} else {
logger.debug("found file " + businessModel.getName() + "/dist/datamart.jar");
}
// search for non mandatory file calculatedFields, rooted in the folder created too
// String pathToSearchXml = tempDirPathId + java.io.File.separator + businessModel.getName() + java.io.File.separator +
// "dist"+java.io.File.separator +CALCULATED_FIELD;
// logger.debug("try reatrieving calculatedFields xml file "+pathToSearch);
// Path tmppathXml = new Path(pathToSearchXml);
// java.io.File xmlFile = tmppathXml.toFile();
// if(xmlFile == null || !xmlFile.exists()){
// logger.warn("Xml file for calculate dields was not found in "+pathToSearchXml);
// xmlFile = null;
// }
// else{
// logger.debug("found file for calculate dfields in "+pathToSearchXml+"/dist/datamart.jar");
// }
SpagoBIServerObjectsFactory spagoBIServerObjects = null;
try {
spagoBIServerObjects = new SpagoBIServerObjectsFactory(projectname);
} catch (NoActiveServerException e) {
logger.error("No server is defined active");
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", "No server is defined active");
}
final NoActiveServerException noActiveServerException = new NoActiveServerException();
IRunnableWithProgress monitorCheckExistance = getMonitorCheckExistance(businessModel, spagoBIServerObjects, fileSel);
IRunnableWithProgress monitorForDatasources = getMonitorForDatasources(businessModel, spagoBIServerObjects);
IRunnableWithProgress monitorForCategory = getMonitorForCategory(businessModel, spagoBIServerObjects);
IRunnableWithProgress monitorForUpload = getMonitorForUpload(businessModel, spagoBIServerObjects, datamart, fileSel);
// Start monitor for upload operation
ProgressMonitorDialog dialog = new ProgressMonitorDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
try {
// the dataSource should be asked only if there is not already a documetn present with datamartnamein system
// check if document is already present
dialog.run(true, true, monitorCheckExistance);
if (!modelAlreadyPresent) {
// get datasources
dialog.run(true, true, monitorForCategory);
// ask datasource to user
if (domains != null) {
logger.debug("found " + (domains != null ? domains.length : "0") + " category domains: make user choose one");
String[] domOptionsArray = null;
if (domains != null) {
Map<String, Domain> mapLabelToDomain = new HashMap<String, Domain>();
int size = domains.length;
domOptionsArray = new String[size];
for (int i = 0; i < domains.length; i++) {
Domain dom = domains[i];
mapLabelToDomain.put(dom.getValueCd(), dom);
domOptionsArray[i] = dom.getValueCd();
}
}
final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
ComboSelectionDialog csd = new ComboSelectionDialog(shell);
csd = new ComboSelectionDialog(shell);
csd.setMessage("Select Category for model (optional)");
csd.setText("Category Selection");
csd.setOptions(domOptionsArray);
logger.debug("Open category selection dialog");
userCategory = csd.open();
logger.debug("user selected category " + userCategory);
}
}
if (!modelAlreadyPresent || !documentAlreadyPresent) {
// get datasources
dialog.run(true, true, monitorForDatasources);
// ask datasource to user
if (dataSources != null) {
logger.debug("found " + (dataSources != null ? dataSources.length : "0") + " datasources: make user choose one");
String[] dsOptionsArray = null;
if (dataSources != null) {
Map<String, DataSource> mapLabelToDatasource = new HashMap<String, DataSource>();
int size = dataSources.length;
dsOptionsArray = new String[size];
for (int i = 0; i < dataSources.length; i++) {
DataSource ds = dataSources[i];
mapLabelToDatasource.put(ds.getLabel(), ds);
dsOptionsArray[i] = ds.getLabel();
}
}
final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
ComboSelectionDialog csd = new ComboSelectionDialog(shell);
csd.setMessage("Select data source for QBE document (optional)");
csd.setText("Data source Selection");
csd.setOptions(dsOptionsArray);
logger.debug("Open datasource selection dialog");
userDataSource = csd.open();
logger.debug("user selected dataSource " + userDataSource);
}
}
// do the uploads
dialog.run(true, true, monitorForUpload);
} catch (InvocationTargetException e1) {
logger.error("error in uploading datamart", e1);
String detailMessage = e1.getTargetException() != null ? "\n\nDetail: " + e1.getTargetException().getMessage() : "";
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "error",
"Error in uploading datamart: check if the server definition is right, if the server is avaiable and the model file is not in use/locked on server."
+ detailMessage);
dialog.close();
return false;
} catch (Exception e1) {
logger.error("error in uploading datamart", e1);
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "error",
"error in uploading datamart: check if the server definition is right and the server is avaiable");
dialog.close();
return false;
}
dialog.close();
if (noActiveServerException.isNoServer()) {
logger.error("No server is defined active");
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", "No server is defined active");
return false;
}
// if here success
MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Upload succesfull",
"Succesfully uploaded to resources\n\n" + messageStatusDocument);
logger.debug("Uploaded to resources in " + businessModel.getName());
// delete the temporary file
try {
Path pathToDelete = new Path(tempDirPathId);
java.io.File toDelete = pathToDelete.toFile();
boolean deleted = toDelete.delete();
if (deleted) {
logger.warn("deleted folder " + tempDirPathId);
}
} catch (Exception e) {
logger.warn("could not delete folder " + tempDirPathId);
}
logger.debug("OUT");
return true;
}
void refreshModelFolder(File file) {
logger.debug("IN");
// search for "Metadata_Model" folder to refresh
// final String METADATA_MODEL_FOLDER = "Metadata_Model";
IContainer folder = file.getParent();
while (folder != null && !folder.getName().equals(SpagoBIStudioConstants.FOLDER_METADATA_MODEL)) {
folder = folder.getParent();
}
if (folder != null) {
try {
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
logger.error("Error in automatically refreshing model server, please do manual refresh on Metada_Model");
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error",
"Error in automatically refreshing model server, please do manual refresh on Metada_Model");
}
}
logger.debug("OUT");
}
public static byte[] getByteArrayFromInputStream(InputStream is) {
logger.debug("IN");
try {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(baos);
int c = 0;
byte[] b = new byte[1024];
while ((c = is.read(b)) != -1) {
if (c == 1024)
bos.write(b);
else
bos.write(b, 0, c);
}
bos.flush();
byte[] ret = baos.toByteArray();
bos.close();
return ret;
} catch (IOException ioe) {
logger.error("IOException", ioe);
return null;
} finally {
logger.debug("OUT");
}
}
}