package fr.acxio.tools.agia.cmis; /* * Copyright 2014 Acxio * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.alfresco.webservice.util.ISO9075; import org.alfresco.webservice.util.Constants; import org.apache.chemistry.opencmis.client.api.CmisObject; import org.apache.chemistry.opencmis.client.api.OperationContext; import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.data.ContentStream; import org.apache.chemistry.opencmis.commons.enums.VersioningState; import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemStreamException; import org.springframework.batch.item.ItemStreamWriter; import fr.acxio.tools.agia.alfresco.domain.Document; import fr.acxio.tools.agia.alfresco.domain.Folder; import fr.acxio.tools.agia.alfresco.domain.Node; import fr.acxio.tools.agia.alfresco.domain.NodeList; import fr.acxio.tools.agia.alfresco.domain.Property; public class CmisWriter implements ItemStreamWriter<NodeList> { private CmisService cmisService; private OperationContext operationContext; private Set<String> existingPaths = new HashSet<String>(); public void setCmisService(CmisService sCmisService) { cmisService = sCmisService; } public void setOperationContext(OperationContext sOperationContext) { operationContext = sOperationContext; } @Override public void open(ExecutionContext sExecutionContext) throws ItemStreamException { cmisService.startSession(); } @Override public void update(ExecutionContext sExecutionContext) throws ItemStreamException { // TODO Auto-generated method stub } @Override public void close() throws ItemStreamException { cmisService.endSession(); existingPaths.clear(); } @Override public void write(List<? extends NodeList> sItems) throws Exception { if (!sItems.isEmpty()) { String aCurrentNodePath; for (NodeList aNodeList : sItems) { for (Node aNode : aNodeList) { aCurrentNodePath = ISO9075.decode(aNode.getPath().replaceAll("[^:/]*:", "")); // Strip // namespaces if (!existingPaths.contains(aCurrentNodePath)) { createOrUpdateNode(aCurrentNodePath, aNode); existingPaths.add(aCurrentNodePath); } } } } } private void createOrUpdateNode(String sCurrentNodePath, Node sNode) throws IOException { CmisObject aExistingObject = null; try { aExistingObject = cmisService.getSession().getObjectByPath(sCurrentNodePath, operationContext); } catch (CmisObjectNotFoundException e) { aExistingObject = null; } if (aExistingObject != null) { updateNode(aExistingObject, sCurrentNodePath, sNode); } else { createNewNode(sCurrentNodePath, sNode); } } private void updateNode(CmisObject sExistingObject, String sCurrentNodePath, Node sNode) throws IOException { Map<String, Object> aProperties = getProperties(sNode); if (sNode instanceof Document) { sExistingObject.updateProperties(aProperties); ContentStream contentStream = createStreamForNode((Document) sNode); ((org.apache.chemistry.opencmis.client.api.Document) sExistingObject).setContentStream(contentStream, true); ((ContentStreamImpl) contentStream).getStream().close(); } } private void createNewNode(String sCurrentNodePath, Node sNode) throws IOException { org.apache.chemistry.opencmis.client.api.Folder aParent = getParent(sCurrentNodePath); Map<String, Object> aProperties = getProperties(sNode); if (sNode instanceof Document) { ContentStream contentStream = createStreamForNode((Document) sNode); aParent.createDocument(aProperties, contentStream, VersioningState.MAJOR); ((ContentStreamImpl) contentStream).getStream().close(); } else if (sNode instanceof Folder) { aParent.createFolder(aProperties); } } private org.apache.chemistry.opencmis.client.api.Folder getParent(String sNodePath) { String aParentPath = sNodePath.substring(0, sNodePath.lastIndexOf("/")); org.apache.chemistry.opencmis.client.api.Folder aParent = (org.apache.chemistry.opencmis.client.api.Folder) cmisService.getSession().getObjectByPath( aParentPath, operationContext); if (aParent == null) { aParent = cmisService.getSession().getRootFolder(); } return aParent; } private Map<String, Object> getProperties(Node sNode) { Map<String, Object> aResult = new HashMap<String, Object>(); List<Property> aProperties = sNode.getProperties(); String aNodeType = (sNode.getType() == null) ? ((sNode instanceof Document) ? "cmis:document" : "cmis:folder") : sNode.getType().toString(); if (Constants.TYPE_CONTENT.equals(aNodeType)) { aNodeType = "cmis:document"; } else if (Constants.TYPE_FOLDER.equals(aNodeType)) { aNodeType = "cmis:folder"; } else { aNodeType = sNode.getType().getLocalName(); } aResult.put(PropertyIds.OBJECT_TYPE_ID, aNodeType); List<String> aPropValues; String aPropName; for (Property aProperty : aProperties) { aPropValues = aProperty.getValues(); aPropName = aProperty.getName().getShortName(); if (Constants.PROP_NAME.equals(aProperty.getName().toString())) { aPropName = "cmis:name"; } if (aPropValues.size() > 1) { aResult.put(aPropName, scanValues(aPropValues)); } else if (aPropValues.size() == 1) { aResult.put(aPropName, scanValue(aPropValues.get(0))); } } return aResult; } private ContentStream createStreamForNode(Document sDocument) throws IOException { ContentStream aResult = null; if ((sDocument.getContentPath() != null) && (sDocument.getContentPath().length() > 0)) { File aFile = new File(sDocument.getContentPath()); if (aFile.exists() && aFile.isFile()) { FileInputStream aInputStream = new FileInputStream(aFile); aResult = new ContentStreamImpl(aFile.getName(), BigInteger.valueOf(aFile.length()), sDocument.getMimeType(), aInputStream); } else { throw new IOException("Cannot find content file: " + sDocument.getContentPath()); } } return aResult; } private Object scanValue(String sValue) { Object aResult = sValue; if (sValue.startsWith("%")) { String aFormatString = sValue.substring(1, sValue.indexOf("%", 1)); String aValue = sValue.substring(2 + aFormatString.length()); if ("B".equals(aFormatString)) { aResult = Boolean.valueOf(aValue); } else if ("D".equals(aFormatString)) { aResult = Long.valueOf(aValue); } else if ("F".equals(aFormatString)) { aResult = Double.valueOf(aValue); } else if (aFormatString.startsWith("T")) { DateTimeFormatter aFormatter = DateTimeFormat.forPattern(aFormatString.substring(1)); aResult = aFormatter.parseDateTime(aValue).toDate(); } } return aResult; } private List<Object> scanValues(List<String> sValues) { List<Object> aResult = null; if (sValues != null) { aResult = new ArrayList<Object>(sValues.size()); for (String aValue : sValues) { aResult.add(scanValue(aValue)); } } return aResult; } }