<commit_before>/* $Id: SVNModelServiceImpl.java 58143 2017-10-03 15:50:34Z zis $ */

package org.activiti.app.service.editor;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import org.activiti.app.domain.editor.AbstractModel;
import org.activiti.app.domain.editor.AppDefinition;
import org.activiti.app.domain.editor.AppModelDefinition;
import org.activiti.app.domain.editor.Model;
import org.activiti.app.domain.editor.ModelHistory;
import org.activiti.app.model.editor.ReviveModelResultRepresentation;
import org.activiti.app.model.editor.ReviveModelResultRepresentation.UnresolveModelRepresentation;
import org.activiti.app.security.SecurityUtils;
import org.activiti.app.service.exception.InternalServerErrorException;
import org.activiti.engine.identity.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * A file model service that uses SVN to get history and commit models.
 */
public class SVNModelServiceImpl extends FileSystemModelServiceImpl {

	static final Logger LOGGER = Logger.getLogger(SVNModelServiceImpl.class);

	private static SAXParserFactory parserFactory = SAXParserFactory.newInstance();

	/**
	 * @param pSvnRootDir
	 */
	public SVNModelServiceImpl(File pSvnRootDir) {
		super(pSvnRootDir);
	}

	@Override
	public List<ModelHistory> getModelHistory(Model pModel) {
		try {
			return svnLog(SecurityUtils.getCurrentUserObject(), pModel.getModelType(), pModel.getKey(), null);
		}
		catch (IOException e) {
			LOGGER.error("Could not list history for " + pModel.getId(), e); //$NON-NLS-1$
			throw new InternalServerErrorException("Could not list history for " + pModel.getId(), e); //$NON-NLS-1$
		}
	}

	@Override
	public ModelHistory getModelHistory(String pModelHistoryId) {
		return getHistory(pModelHistoryId);
	}

	@Override
	public ModelHistory getModelHistory(String pModelId, String pModelHistoryId) {
		return getHistory(pModelHistoryId);
	}

	@Override
	public List<ModelHistory> getModelHistoryForUser(User pUser, Integer pModelType) {
		try {
			return svnLog(pUser, pModelType, null, null);
		}
		catch (IOException e) {
			LOGGER.error("Could not list history for " + pModelType, e); //$NON-NLS-1$
			throw new InternalServerErrorException("Could not list history for " + pModelType, e); //$NON-NLS-1$
		}
	}

	@Override
	public ReviveModelResultRepresentation reviveProcessModelHistory(ModelHistory pModelHistory, User pUser, String pNewVersionComment) {
		Model latestModel = getModel(pModelHistory.getModelId());
		latestModel.setModelEditorJson(pModelHistory.getModelEditorJson());
		persistModel(latestModel, true, pNewVersionComment, pUser);
		ReviveModelResultRepresentation result = new ReviveModelResultRepresentation();

		// For apps, we need to make sure the referenced processes exist as models.
		// It could be the user has deleted the process model in the meantime. We
		// give back that info to the user.
		if (latestModel.getModelType().intValue() == AbstractModel.MODEL_TYPE_APP) {
			if (StringUtils.isNotEmpty(latestModel.getModelEditorJson())) {
				try {
					AppDefinition appDefinition = objectMapper.readValue(latestModel.getModelEditorJson(), AppDefinition.class);
					for (AppModelDefinition appModelDefinition : appDefinition.getModels()) {
						if (!getFile(appModelDefinition.getId()).exists()) {
							result.getUnresolvedModels().add(new UnresolveModelRepresentation(appModelDefinition.getId(), appModelDefinition.getName(), appModelDefinition.getLastUpdatedBy()));
						}
					}
				}
				catch (Exception e) {
					LOGGER.error("Could not deserialize app model json (id = " + latestModel.getId() + ")", e); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		}
		return result;
	}

	@Override
	protected void deleteFile(User pUser, File pFile, String pComment) throws IOException {
		svnDelete(pFile);
		svnCommit(pUser, pFile, pComment);
	}

	@Override
	protected ModelHistory getVersion(File pFile) {
		String log = null;
		try {
			SVNLogHandler handler = new SVNLogHandler(null, null, null);
			log = svnExecute(null, "info", pFile, "--xml"); //$NON-NLS-1$ //$NON-NLS-2$
			if (log != null && log.startsWith("<?xml")) { //$NON-NLS-1$
				parse(log, handler);
				handler.version.setVersion(handler.version.getVersion() + 1);
				return handler.version;
			}
		}
		catch (IOException e) {
			LOGGER.error(e.getMessage()); 
		}
		return super.getVersion(pFile);
	}

	@Override
	protected void persistModel(Model pModel, boolean pNewVersion, String pComment, User pUpdatedBy) {
		try {
			super.persistModel(pModel, pNewVersion, pComment, pUpdatedBy);
			if (pNewVersion) {
				File file = getFile(pModel.getId());
				File toCommit = svnAdd(file);
				if (toCommit == null) {
					toCommit = file;
				}
				// Commit it
				svnCommit(pUpdatedBy, toCommit, pComment);
			}
		}
		catch (IOException e) {
			LOGGER.error("Could not commit model file", e); //$NON-NLS-1$
			throw new InternalServerErrorException("Could not commit model file", e); //$NON-NLS-1$
		}
	}
<commit_msg>Fix NPE on empty svn log<commit_after>/* $Id: SVNModelServiceImpl.java 58143 2017-10-03 15:50:34Z zis $ */

package org.activiti.app.service.editor;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import org.activiti.app.domain.editor.AbstractModel;
import org.activiti.app.domain.editor.AppDefinition;
import org.activiti.app.domain.editor.AppModelDefinition;
import org.activiti.app.domain.editor.Model;
import org.activiti.app.domain.editor.ModelHistory;
import org.activiti.app.model.editor.ReviveModelResultRepresentation;
import org.activiti.app.model.editor.ReviveModelResultRepresentation.UnresolveModelRepresentation;
import org.activiti.app.security.SecurityUtils;
import org.activiti.app.service.exception.InternalServerErrorException;
import org.activiti.engine.identity.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * A file model service that uses SVN to get history and commit models.
 */
public class SVNModelServiceImpl extends FileSystemModelServiceImpl {

	static final Logger LOGGER = Logger.getLogger(SVNModelServiceImpl.class);

	private static SAXParserFactory parserFactory = SAXParserFactory.newInstance();

	/**
	 * @param pSvnRootDir
	 */
	public SVNModelServiceImpl(File pSvnRootDir) {
		super(pSvnRootDir);
	}

	@Override
	public List<ModelHistory> getModelHistory(Model pModel) {
		try {
			return svnLog(SecurityUtils.getCurrentUserObject(), pModel.getModelType(), pModel.getKey(), null);
		}
		catch (IOException e) {
			LOGGER.error("Could not list history for " + pModel.getId(), e); //$NON-NLS-1$
			throw new InternalServerErrorException("Could not list history for " + pModel.getId(), e); //$NON-NLS-1$
		}
	}

	@Override
	public ModelHistory getModelHistory(String pModelHistoryId) {
		return getHistory(pModelHistoryId);
	}

	@Override
	public ModelHistory getModelHistory(String pModelId, String pModelHistoryId) {
		return getHistory(pModelHistoryId);
	}

	@Override
	public List<ModelHistory> getModelHistoryForUser(User pUser, Integer pModelType) {
		try {
			return svnLog(pUser, pModelType, null, null);
		}
		catch (IOException e) {
			LOGGER.error("Could not list history for " + pModelType, e); //$NON-NLS-1$
			throw new InternalServerErrorException("Could not list history for " + pModelType, e); //$NON-NLS-1$
		}
	}

	@Override
	public ReviveModelResultRepresentation reviveProcessModelHistory(ModelHistory pModelHistory, User pUser, String pNewVersionComment) {
		Model latestModel = getModel(pModelHistory.getModelId());
		latestModel.setModelEditorJson(pModelHistory.getModelEditorJson());
		persistModel(latestModel, true, pNewVersionComment, pUser);
		ReviveModelResultRepresentation result = new ReviveModelResultRepresentation();

		// For apps, we need to make sure the referenced processes exist as models.
		// It could be the user has deleted the process model in the meantime. We
		// give back that info to the user.
		if (latestModel.getModelType().intValue() == AbstractModel.MODEL_TYPE_APP) {
			if (StringUtils.isNotEmpty(latestModel.getModelEditorJson())) {
				try {
					AppDefinition appDefinition = objectMapper.readValue(latestModel.getModelEditorJson(), AppDefinition.class);
					for (AppModelDefinition appModelDefinition : appDefinition.getModels()) {
						if (!getFile(appModelDefinition.getId()).exists()) {
							result.getUnresolvedModels().add(new UnresolveModelRepresentation(appModelDefinition.getId(), appModelDefinition.getName(), appModelDefinition.getLastUpdatedBy()));
						}
					}
				}
				catch (Exception e) {
					LOGGER.error("Could not deserialize app model json (id = " + latestModel.getId() + ")", e); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		}
		return result;
	}

	@Override
	protected void deleteFile(User pUser, File pFile, String pComment) throws IOException {
		svnDelete(pFile);
		svnCommit(pUser, pFile, pComment);
	}

	@Override
	protected ModelHistory getVersion(File pFile) {
		String log = null;
		try {
			SVNLogHandler handler = new SVNLogHandler(null, null, null);
			log = svnExecute(null, "info", pFile, "--xml"); //$NON-NLS-1$ //$NON-NLS-2$
			if (log != null && log.startsWith("<?xml")) { //$NON-NLS-1$
				parse(log, handler);
				if(handler.version != null){
					handler.version.setVersion(handler.version.getVersion() + 1);
					return handler.version;
				}
			}
		}
		catch (IOException e) {
			LOGGER.error(e.getMessage()); 
		}
		return super.getVersion(pFile);
	}

	@Override
	protected void persistModel(Model pModel, boolean pNewVersion, String pComment, User pUpdatedBy) {
		try {
			super.persistModel(pModel, pNewVersion, pComment, pUpdatedBy);
			if (pNewVersion) {
				File file = getFile(pModel.getId());
				File toCommit = svnAdd(file);
				if (toCommit == null) {
					toCommit = file;
				}
				// Commit it
				svnCommit(pUpdatedBy, toCommit, pComment);
			}
		}
		catch (IOException e) {
			LOGGER.error("Could not commit model file", e); //$NON-NLS-1$
			throw new InternalServerErrorException("Could not commit model file", e); //$NON-NLS-1$
		}
	}

{'fraction_non_alphanumeric': 0.11646550171140335, 'fraction_numerical': 0.005944874797333814, 'mean_word_length': 4.708483290488432, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 20}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1122419', 'n_tokens_mistral': 3815, 'n_tokens_neox': 3500, 'n_words': 773}