/**
* EasySOA Registry
* Copyright 2011-2013 Open Wide
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact : easysoa-dev@googlegroups.com
*/
package org.easysoa.registry.dbb;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.GregorianCalendar;
import org.easysoa.registry.types.ResourceDownloadInfo;
import org.easysoa.registry.types.listeners.EventListenerBase;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.event.Event;
import org.nuxeo.ecm.core.event.EventProducer;
import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
import org.nuxeo.ecm.platform.ui.web.util.files.FileUtils;
import org.nuxeo.runtime.api.Framework;
/**
* Impl of Resource Update Service that downloads Resource synchronously
* and then triggers its parsing through (a priori synchronous) event
*
* @author jguillemotte
*/
public abstract class ResourceUpdateServiceImpl implements ResourceUpdateService {
/** triggers parsing */
public static final String RESOURCE_DOWNLOADED_EVENT = "resourceDownloaded";
@Override
public boolean isNewResourceRetrieval(DocumentModel newRdi, DocumentModel oldRdi) throws ClientException {
if (oldRdi == null) {
return true;
}
// Check if the rdi.timestamp is not null and doesn't differ ??
//String url = (String) newRdi.getProperty(ResourceDownloadInfo.XPATH_ACTUAL_URL);
// NB. if url differs, timestamp should change
GregorianCalendar newTimestamp = (GregorianCalendar) newRdi.getPropertyValue(ResourceDownloadInfo.XPATH_TIMESTAMP);
GregorianCalendar oldTimestamp = (GregorianCalendar) oldRdi.getPropertyValue(ResourceDownloadInfo.XPATH_TIMESTAMP);
if(newTimestamp != null && oldTimestamp != null
&& newTimestamp.equals(oldTimestamp)) { // no date parsing but checking it is not "dumb"
return false;
}
return true;
}
/**
* To be called by implementations
* @param newRdi
* @param oldRdi
* @param documentToUpdate
* @param resourceDownloadService
* @throws ClientException
*/
protected void doUpdateResourceAndFireEvent(DocumentModel newRdi, DocumentModel oldRdi,
DocumentModel documentToUpdate) throws ClientException {
documentToUpdate = this.doUpdateResource(newRdi, oldRdi, documentToUpdate);
this.fireResourceDownloadedEvent(documentToUpdate); // firing on persisted document (else no SQLBlob so no digest)
}
@Override
public void fireResourceDownloadedEvent(DocumentModel document) throws ClientException {
// Trigger a resourceDownloaded event
EventProducer eventProducer;
try {
eventProducer = Framework.getService(EventProducer.class);
} catch (Exception ex) {
throw new ClientException("Cannot get EventProducer", ex);
}
DocumentEventContext ctx = new DocumentEventContext(document.getCoreSession(),
document.getCoreSession().getPrincipal(), document);
Event event = ctx.newEvent(RESOURCE_DOWNLOADED_EVENT);
try {
eventProducer.fireEvent(event);
} catch (ClientException ex) {
throw new ClientException("Cannot fire event", ex);
}
}
protected DocumentModel doUpdateResource(DocumentModel newRdi, DocumentModel oldRdi,
DocumentModel documentToUpdate) throws ClientException {
// Check if update is needed
if (!isNewResourceRetrieval(newRdi, oldRdi)) {
return documentToUpdate;
}
ResourceDownloadService resourceDownloadService = this.getProbeResourceDownloadService(newRdi);
CoreSession coreSession = documentToUpdate.getCoreSession();
// Get the new resource
String newUrl = (String) newRdi.getPropertyValue(ResourceDownloadInfo.XPATH_URL);
if(newUrl == null || newUrl.length() == 0){
// No URL, happens on document without RDI (yet) but with static
// RDI facet (ex. iserv/endpoint) (TODO should have been done in resourceListener),
// or maybe none known yet (??)
// For test only, to remove
//newUrl = "http://footballpool.dataaccess.eu/data/info.wso?WSDL";
return documentToUpdate;
}
ResourceDownloadInfo newRdiBean = new ResourceDownloadInfoImpl();
newRdiBean.setUrl(newUrl);
// TODO set other props
// TODO LATER rather as adapter ?
InputStream file;
try {
newRdiBean = resourceDownloadService.get(newRdiBean);
file = new FileInputStream(newRdiBean.getFile());
} catch (MalformedURLException ex) {
throw new ClientException("Bad URL : " + newUrl, ex);
} catch (Exception ex) {
throw new ClientException("Error downloading " + newUrl, ex);
}
// Update registry with new resource
Blob resourceBlob = FileUtils.createSerializableBlob(file, getWsdlFileName(newUrl), null);
documentToUpdate.setPropertyValue("file:content", (Serializable) resourceBlob);
documentToUpdate.setPropertyValue(ResourceDownloadInfo.XPATH_TIMESTAMP,
newRdiBean.getTimestamp()); // NB. nuxeo auto-converts it to GregorianCalendar (xs:dateTime)
// saving :
// first disabling events (the only one to be triggered is resourceDownloaded event,
// but it's fired explicitly below)
EventListenerBase.disableListeners(documentToUpdate);
documentToUpdate = coreSession.saveDocument(documentToUpdate); // updates (& triggers events),
// else Blob stays a StreamingBlob instead of becoming an SQLBlob and can't compute the new digest
EventListenerBase.enableListeners(documentToUpdate); // reenabling them for resourceDownloaded event
// NB. coreSession.save() is not required (and should not since when async save is done transactionnaly in Work)
return documentToUpdate; // returning persisted document
}
/**
* Build a file name for WSDL file from the URL
* @param url The url
* @return The file name
*/
public String getWsdlFileName(String url){
String fileName = url.substring(url.lastIndexOf("/")+1).replace("?", ".");
if(!fileName.toLowerCase().endsWith(".wsdl")){
fileName = fileName.concat(".wsdl");
}
return fileName;
}
@Override
public ResourceDownloadService getProbeResourceDownloadService(DocumentModel newRdi) throws ClientException {
// Get & use probe conf
String probeType = (String) newRdi.getPropertyValue(ResourceDownloadInfo.XPATH_PROBE_TYPE);//TODO
String probeInstanceId = (String) newRdi.getPropertyValue(ResourceDownloadInfo.XPATH_PROBE_INSTANCEID);//TODO
ResourceDownloadService probeResourceDownloadService = ProbeConfUtil.getResourceDownloadService(probeType, probeInstanceId);
return probeResourceDownloadService;
}
}