/**
*
*/
package net.conselldemallorca.helium.integracio.plugins.gesdoc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.activation.MimetypesFileTypeMap;
import net.conselldemallorca.helium.core.util.GlobalProperties;
import org.alfresco.webservice.authentication.AuthenticationFault;
import org.alfresco.webservice.content.Content;
import org.alfresco.webservice.content.ContentFault;
import org.alfresco.webservice.content.ContentServiceSoapBindingStub;
import org.alfresco.webservice.repository.QueryResult;
import org.alfresco.webservice.repository.RepositoryFault;
import org.alfresco.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.webservice.repository.UpdateResult;
import org.alfresco.webservice.types.CML;
import org.alfresco.webservice.types.CMLCreate;
import org.alfresco.webservice.types.CMLDelete;
import org.alfresco.webservice.types.ContentFormat;
import org.alfresco.webservice.types.NamedValue;
import org.alfresco.webservice.types.ParentReference;
import org.alfresco.webservice.types.Predicate;
import org.alfresco.webservice.types.Reference;
import org.alfresco.webservice.types.ResultSet;
import org.alfresco.webservice.types.Store;
import org.alfresco.webservice.util.AuthenticationUtils;
import org.alfresco.webservice.util.Constants;
import org.alfresco.webservice.util.ContentUtils;
import org.alfresco.webservice.util.Utils;
import org.alfresco.webservice.util.WebServiceFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementació del plugin de gestió documental amb Alfresco
*
* @author Limit Tecnologies <limit@limit.es>
*/
public class GestioDocumentalPluginAlfrescoCaib implements GestioDocumentalPlugin {
public String createDocument(
String expedientNumero,
String expedientTipus,
String documentCodi,
String documentDescripcio,
Date documentData,
String documentArxiuNom,
byte[] documentArxiuContingut) throws GestioDocumentalPluginException {
try {
startAlfrescoSession();
Reference ref = getAlfrescoDocumentPath(
getPathDocument(
expedientNumero,
expedientTipus,
documentCodi,
documentData),
true);
return createContent(
ref,
documentCodi,
documentDescripcio,
"Nom arxiu: " + documentArxiuNom + "\nData document: " + new SimpleDateFormat("dd/MM/yyyy").format(documentData),
documentArxiuContingut);
} catch (Exception ex) {
logger.error("Error al guardar l'arxiu dins el gestor documental", ex);
throw new GestioDocumentalPluginException("Error al guardar l'arxiu dins el gestor documental", ex);
} finally {
endAlfrescoSession();
}
}
public byte[] retrieveDocument(String documentId) throws GestioDocumentalPluginException {
try {
startAlfrescoSession();
return retrieveContent(new Reference(ALFRESCO_STORE, documentId, null));
} catch (Exception ex) {
logger.error("Error al llegir l'arxiu del gestor documental", ex);
throw new GestioDocumentalPluginException("Error al llegir l'arxiu del gestor documental", ex);
} finally {
endAlfrescoSession();
}
}
public void deleteDocument(String documentId) throws GestioDocumentalPluginException {
try {
startAlfrescoSession();
Reference ref = new Reference(ALFRESCO_STORE, documentId, null);
deleteContent(getParent(ref));
} catch (Exception ex) {
logger.error("Error al esborrar l'arxiu del gestor documental", ex);
throw new GestioDocumentalPluginException("Error al esborrar l'arxiu del gestor documental", ex);
} finally {
endAlfrescoSession();
}
}
private Reference getAlfrescoDocumentPath(String[] path, boolean create) throws RepositoryFault, RemoteException {
String baseDir = GlobalProperties.getInstance().getProperty("app.gesdoc.plugin.basedir");
if (baseDir == null || baseDir.length() == 0)
baseDir = GlobalProperties.getInstance().getProperty("app.docstore.alfresco.basedir");
String[] baseDirParts;
if (baseDir.startsWith("/"))
baseDirParts = baseDir.substring(1).split("/");
else
baseDirParts = baseDir.split("/");
String[] totalPath = new String[path.length + baseDirParts.length];
for (int i = 0; i < baseDirParts.length; i++)
totalPath[i] = replaceForbiddenChars(baseDirParts[i]);
for (int i = 0; i < path.length; i++)
totalPath[baseDirParts.length + i] = replaceForbiddenChars(path[i]);
Reference ref = retrieveOrCreateSpace(totalPath[0], create);
for (int i = 1; i < totalPath.length; i++)
ref = retrieveOrCreateSpace(ref, totalPath[i], create);
return ref;
}
private String createContent(
Reference ref,
String name,
String title,
String description,
byte[] data) throws RemoteException, ContentFault {
ParentReference parent = getReferenceToParent(ref);
parent.setChildName(Constants.createQNameString(
Constants.NAMESPACE_CONTENT_MODEL,
normalizeNodeName(name)));
NamedValue[] properties = new NamedValue[]{
Utils.createNamedValue(Constants.PROP_NAME, name),
Utils.createNamedValue(Constants.PROP_TITLE, title),
Utils.createNamedValue(Constants.PROP_DESCRIPTION, description)};
CMLCreate create = new CMLCreate("1", parent, null, null, null, Constants.TYPE_CONTENT, properties);
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
UpdateResult[] result = getAlfrescoRepositoryService().update(cml);
Reference newContentNode = result[0].getDestination();
Content content = getAlfrescoContentService().write(
newContentNode,
Constants.PROP_CONTENT,
data,
new ContentFormat(new MimetypesFileTypeMap().getContentType(name), null));
return content.getNode().getUuid();
}
private byte[] retrieveContent(Reference ref) throws IOException {
Content[] readResult = getAlfrescoContentService().read(
new Predicate(new Reference[]{ref}, ALFRESCO_STORE, null),
Constants.PROP_CONTENT);
InputStream is = ContentUtils.getContentAsInputStream(readResult[0]);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int nread = 0;
byte[] buffer = new byte[4096];
while ((nread = is.read(buffer)) > 0)
baos.write(buffer, 0, nread);
return baos.toByteArray();
}
private void deleteContent(Reference ref) throws RepositoryFault, RemoteException {
CMLDelete delete = new CMLDelete(new Predicate(new Reference[]{ref}, ALFRESCO_STORE, null));
CML cml = new CML();
cml.setDelete(new CMLDelete[]{delete});
getAlfrescoRepositoryService().update(cml);
}
private Reference getParent(Reference space) throws RepositoryFault, RemoteException {
QueryResult result = getAlfrescoRepositoryService().queryParents(space);
ResultSet resultset = result.getResultSet();
String first_parent_id = resultset.getRows(0).getNode().getId();
Reference parent = new Reference(ALFRESCO_STORE, first_parent_id, null);
return parent;
}
private ParentReference getCompanyHome() {
ParentReference companyHomeParent = new ParentReference(ALFRESCO_STORE, null, "/app:company_home", Constants.ASSOC_CONTAINS, null);
return companyHomeParent;
}
private Reference retrieveOrCreateSpace(String spaceName, boolean create) throws RepositoryFault, RemoteException {
return retrieveOrCreateSpace(null, spaceName, create);
}
private Reference retrieveOrCreateSpace(Reference parentref, String spaceName, boolean create) throws RepositoryFault, RemoteException {
Reference space = null;
ParentReference parent;
if (parentref != null)
parent = getReferenceToParent(parentref);
else
parent = getCompanyHome();
// Create the space if it is not already existent
try {
// Therefore a reference to the maybe not existent space is required
space = new Reference(ALFRESCO_STORE, null, parent.getPath() + "/cm:" + normalizeNodeName(spaceName));
getAlfrescoRepositoryService().get(new Predicate(new Reference[]{space}, ALFRESCO_STORE, null));
} catch (Exception notFound) {
if (create) {
// Set parent as the parent space
parent.setChildName(Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, spaceName));
//Set the space's property name
NamedValue[] properties = new NamedValue[]{Utils.createNamedValue(Constants.PROP_NAME, spaceName)};
// Create the space using CML (Content Manipulation Language)
CMLCreate cmlcreate = new CMLCreate("1", parent, null, null, null, Constants.TYPE_FOLDER, properties);
CML cml = new CML();
cml.setCreate(new CMLCreate[]{cmlcreate});
// Execute the CML create statement
getAlfrescoRepositoryService().update(cml);
}
}
return space;
}
private ParentReference getReferenceToParent(Reference spaceref) {
ParentReference parent = new ParentReference();
parent.setStore(ALFRESCO_STORE);
parent.setPath(spaceref.getPath());
parent.setUuid(spaceref.getUuid());
parent.setAssociationType(Constants.ASSOC_CONTAINS);
return parent;
}
private String normalizeNodeName(String src) {
// Conversió a ISO9075
Pattern pattern = Pattern.compile("^\\d");
Matcher matcher = pattern.matcher(src);
String resultat = src;
if (matcher.find())
resultat = "_x003" + src.substring(0, 1) + "_" + src.substring(1);
return resultat.replace(" ", "_x0020_").replace(",", "_x002c_");
}
private String replaceForbiddenChars(String src) {
String s = src;
for (char c: forbidden)
s = s.replace(c, '_');
return s;
}
private String[] getPathDocument(
String expedientNumero,
String expedientTipus,
String documentCodi,
Date documentData) {
// entorn/tipus/numero
String[] parts = expedientTipus.split("#");
String entornCodi = parts[0];
String expedientTipusCodi = parts[1];
return new String[] {
entornCodi,
expedientTipusCodi,
expedientNumero};
}
private RepositoryServiceSoapBindingStub getAlfrescoRepositoryService() {
configureAlfrescoRepository();
return WebServiceFactory.getRepositoryService();
}
private ContentServiceSoapBindingStub getAlfrescoContentService() {
configureAlfrescoRepository();
return WebServiceFactory.getContentService();
}
private String startAlfrescoSession() throws AuthenticationFault {
configureAlfrescoRepository();
String alfrescoUser = GlobalProperties.getInstance().getProperty("app.gesdoc.plugin.user");
if (alfrescoUser == null || alfrescoUser.length() == 0)
alfrescoUser = GlobalProperties.getInstance().getProperty("app.docstore.alfresco.user");
String alfrescoPass = GlobalProperties.getInstance().getProperty("app.gesdoc.plugin.pass");
if (alfrescoPass == null || alfrescoPass.length() == 0)
alfrescoPass = GlobalProperties.getInstance().getProperty("app.docstore.alfresco.pass");
AuthenticationUtils.startSession(alfrescoUser, alfrescoPass);
return AuthenticationUtils.getAuthenticationDetails().getTicket();
}
private void endAlfrescoSession() {
configureAlfrescoRepository();
AuthenticationUtils.endSession();
}
private boolean repoConfigured = false;
private void configureAlfrescoRepository() {
String alfrescoApiurl = GlobalProperties.getInstance().getProperty("app.gesdoc.plugin.apiurl");
if (alfrescoApiurl == null || alfrescoApiurl.length() == 0)
alfrescoApiurl = GlobalProperties.getInstance().getProperty("app.docstore.alfresco.apiurl");
if (!repoConfigured) {
WebServiceFactory.setEndpointAddress(alfrescoApiurl);
repoConfigured = true;
}
}
private static char[] forbidden = {
'/', ':', '*', '?',
'\"', '<', '>', '|',
';', '&', '%', '+',
'\\'};
private static final Store ALFRESCO_STORE = new Store(Constants.WORKSPACE_STORE, "SpacesStore");
private static final Log logger = LogFactory.getLog(GestioDocumentalPluginAlfresco.class);
}