/* * 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/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.beans; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.impl.cmd.CreateAttachmentCmd; import org.activiti.engine.impl.context.Context; import org.activiti.engine.task.Attachment; import org.apache.commons.lang.StringUtils; import org.apache.tika.mime.MimeTypes; import ru.codeinside.gses.activiti.Activiti; import ru.codeinside.gses.activiti.ftarchive.AttachmentFFT; import ru.codeinside.gses.activiti.history.ExecutionId; import ru.codeinside.gses.activiti.history.HistoricDbSqlSession; import ru.codeinside.gws.api.Enclosure; import ru.codeinside.gws.api.ReceiptContext; import ru.codeinside.gws.api.Signature; import java.io.ByteArrayInputStream; import java.security.cert.CertificateEncodingException; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; //TODO переместить в другой пакет public class ActivitiReceiptContext implements ReceiptContext { final static String VAR_PREFIX = "result_"; final static int VAR_PREFIX_LENGTH = VAR_PREFIX.length(); final Logger logger = Logger.getLogger(getClass().getName()); final Map<String, Enclosure> nameToEnclosure = new LinkedHashMap<String, Enclosure>(); final Map<Enclosure, String> enclosureToId = new IdentityHashMap<Enclosure, String>(); final DelegateExecution execution; final long bid; private enum VarType { PROPERTY, ATTACHMENT } // ---- API ---- public ActivitiReceiptContext(DelegateExecution execution, long bid) { this.execution = execution; this.bid = bid; } @Override public Object getVariable(String name) { return ComplexValue.get(execution, VAR_PREFIX + name).getValue(); } @Override public Object getVariableByFullName(String name) { return ComplexValue.get(execution, name).getValue(); } @Override public Set<String> getPropertyNames() { return getVariableNames(VarType.PROPERTY); } @Override public Set<String> getAllPropertyNames() { return getAllVariablesNames(VarType.PROPERTY); } @Override public Set<String> getEnclosureNames() { return getVariableNames(VarType.ATTACHMENT); } @Override public Set<String> getAllEnclosureNames() { return getAllVariablesNames(VarType.ATTACHMENT); } @Override public Enclosure getEnclosure(String shortName) { return getAndCacheEnclosure(VAR_PREFIX + shortName); } @Override public Enclosure getEnclosureByFullName(String name) { return getAndCacheEnclosure(name); } @Override public void setEnclosure(String name, Enclosure enclosure) { if (name == null || enclosure == null || enclosure.content == null) { logger.info("invalid enclosure " + name + " = " + enclosure); return; } if (nameToEnclosure.get(name) != enclosure) { nameToEnclosure.put(name, enclosure); if (enclosureToId.containsKey(enclosure)) { execution.setVariable(name, enclosureToId.get(enclosure) + AttachmentFFT.SUFFIX); } else { Attachment attachment = createAttachment(name, enclosure); enclosureToId.put(enclosure, attachment.getId()); execution.setVariable(name, enclosureToId.get(enclosure) + AttachmentFFT.SUFFIX); addSignature(name, enclosure.signature); } } } @Override public void setVariable(String name, Object value) { if (value instanceof Enclosure) { setEnclosure(name, (Enclosure) value); } else { nameToEnclosure.remove(name); execution.setVariable(name, value); } } @Override public String getBid() { return Long.toString(bid); } public Map<Enclosure, String[]> getUsedEnclosures() { ImmutableMap.Builder<Enclosure, String[]> builder = ImmutableMap.builder(); for (Enclosure enclosure : enclosureToId.keySet()) { String id = enclosureToId.get(enclosure); for (String name : nameToEnclosure.keySet()) { if (nameToEnclosure.get(name) == enclosure) { builder.put(enclosure, new String[]{id, name}); break; } } } return builder.build(); } // ---- Internals ---- private Set<String> getVariableNames(VarType varType) { ImmutableSet.Builder<String> builder = ImmutableSet.builder(); for (String varName : getAllVariablesNames(varType)) { if (varName.startsWith(VAR_PREFIX)) { builder.add(varName.substring(VAR_PREFIX_LENGTH)); } } return builder.build(); } private Set<String> getAllVariablesNames(VarType varType) { ImmutableSet.Builder<String> builder = ImmutableSet.builder(); for (String varName : execution.getVariableNames()) { ComplexValue value = ComplexValue.get(execution, varName); VarType valueType = value.isAttachmentId() ? VarType.ATTACHMENT : VarType.PROPERTY; if (valueType == varType) { builder.add(varName); } } return builder.build(); } private Enclosure getAndCacheEnclosure(String name) { if (!nameToEnclosure.containsKey(name)) { ComplexValue value = ComplexValue.get(execution, name); if (value.isAttachmentId()) { Enclosure enclosure = Activiti.createEnclosureInCommandContext(value.getAttachmentId(), execution.getId(), name); if (enclosure != null) { nameToEnclosure.put(name, enclosure); enclosureToId.put(enclosure, value.getAttachmentId()); } } } return nameToEnclosure.get(name); } private Attachment createAttachment(String name, Enclosure enclosure) { String mimeType = StringUtils.trimToNull(enclosure.mimeType); if (mimeType == null) { mimeType = new MimeTypes().getMimeType(enclosure.content).getName(); } return new CreateAttachmentCmd( mimeType, execution.getId(), execution.getProcessInstanceId(), Activiti.getAttachmentName(enclosure, name), name, new ByteArrayInputStream(enclosure.content), null ).execute(Context.getCommandContext()); } private void addSignature(String name, Signature signature) { if (signature != null && signature.certificate != null && signature.sign != null && signature.valid) { try { byte[] certificate = signature.certificate.getEncoded(); byte[] sign = signature.sign; HistoricDbSqlSession session = (HistoricDbSqlSession) Context.getCommandContext().getDbSqlSession(); ExecutionId executionId = new ExecutionId(execution.getProcessInstanceId(), execution.getId(), execution.getId()); session.addSignature(executionId, name, certificate, sign, true); } catch (CertificateEncodingException e) { logger.log(Level.WARNING, "encode certificate fail", e); } } } }