/******************************************************************************* * Copyright (c) Jun 28, 2011 Zend Technologies Ltd. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.zend.sdklib.mapping.validator; import static org.zend.sdklib.mapping.IMappingModel.APPDIR; import static org.zend.sdklib.mapping.IMappingModel.LIBRARY; import static org.zend.sdklib.mapping.IMappingModel.SCRIPTSDIR; import static org.zend.sdklib.mapping.PropertiesBasedMappingLoader.EXCLUDES; import static org.zend.sdklib.mapping.PropertiesBasedMappingLoader.GLOBAL; import static org.zend.sdklib.mapping.PropertiesBasedMappingLoader.INCLUDES; import static org.zend.sdklib.mapping.PropertiesBasedMappingLoader.SEPARATOR; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.zend.sdklib.SdkException; import org.zend.sdklib.internal.mapping.LibraryMapping; import org.zend.sdklib.mapping.IVariableResolver; /** * Default implementation of {@link IMappingValidator}. * * @author Wojciech Galanciak, 2011 * */ public class MappingValidator implements IMappingValidator { private static final String KEY_VALUE_SEPARATOR = "="; private static final String LINE_SEPARATOR = "\\"; private static final String KEY_SEPARATOR = "\\."; private File container; private boolean hasAppdir; private int buffer; private IVariableResolver variableResolver; public MappingValidator(File container) { super(); this.container = container; } /* * (non-Javadoc) * * @see * org.zend.sdklib.mapping.validator.IMappingValidator#parse(java.io.InputStream * ) */ @Override public boolean parse(InputStream stream) throws MappingParseException { List<MappingParseStatus> result = new ArrayList<MappingParseStatus>(); BufferedReader reader = new BufferedReader( new InputStreamReader(stream)); String line = null; String previousLastChar = null; int i = 0; String lastKey = null; try { while ((line = reader.readLine()) != null) { i++; String[] parts = line.split(KEY_VALUE_SEPARATOR); if (parts.length == 2) { MappingParseStatus keyStatus = checkValidKey(parts[0], i, line); if (keyStatus != null) { result.add(keyStatus); } lastKey = parts[0].trim(); List<MappingParseStatus> valueStatus = checkValidValues( parts[1], i, line, lastKey); if (!valueStatus.isEmpty()) { result.addAll(valueStatus); } } else { if (!line.trim().isEmpty()) { if (LINE_SEPARATOR.equals(previousLastChar)) { String entry = line.trim(); if (entry.endsWith(LINE_SEPARATOR)) { entry = entry.substring(0, line.trim().length() - 1); } List<MappingParseStatus> valueStatus = checkValidValues( entry, i, line, lastKey); if (!valueStatus.isEmpty()) { result.addAll(valueStatus); } } else { int start = buffer + line.indexOf(line.trim()); int end = start + line.trim().length(); result.add(new MappingParseStatus(i, start, end, MappingParseMessage.INVALID_LINE)); } } } buffer += line.length() + 1; previousLastChar = line.trim().isEmpty() ? null : line.trim() .substring(line.trim().length() - 1); } if (i == 0) { result.add(new MappingParseStatus(0, 0, 0, MappingParseMessage.EMPTY_FILE)); } else if (!hasAppdir) { result.add(new MappingParseStatus(0, 0, 0, MappingParseMessage.NO_APPDIR)); } stream.close(); } catch (IOException e) { result.add(new MappingParseStatus(0, 0, 0, MappingParseMessage.CANNOT_READ)); } if (result.isEmpty()) { return true; } else { throw new MappingParseException(result); } } public void setVariableResolver(IVariableResolver variableResolver) { this.variableResolver = variableResolver; } private List<MappingParseStatus> checkValidValues(String value, int lineNo, String line, String lastKey) { List<MappingParseStatus> result = new ArrayList<MappingParseStatus>(); String[] values = value.split(SEPARATOR); if (values.length == 0 || value.trim().length() == 0) { int offset = line.length() - value.length(); result.add(new MappingParseStatus(lineNo, offset, offset + 1, MappingParseMessage.EMPTY_MAPPING)); return result; } for (String entry : values) { entry = entry.trim(); if (entry.isEmpty() || entry.equals(LINE_SEPARATOR)) { continue; } if ((LIBRARY + INCLUDES).equals(lastKey)) { if (lastKey != null) { String keyName = lastKey.substring(0, lastKey.indexOf('.')); LibraryMapping mapping = LibraryMapping.create(keyName, entry); if (mapping == null) { int offset = line.indexOf(entry); result.add(new MappingParseStatus(lineNo, offset + buffer, offset + entry.length() + buffer, MappingParseMessage.INVALID_LIBRARY)); } else { String lib = mapping.getLibraryPath(); File libraryFile = resolveVariables(lib); if (!libraryFile.isAbsolute()) { libraryFile = new File(container, lib); } if (!libraryFile.exists()) { int offset = line.indexOf(entry); result.add(new MappingParseStatus(lineNo, offset + buffer, offset + entry.length() + buffer, MappingParseMessage.NOT_EXIST)); } } } } else { boolean isGlobal = entry.startsWith(GLOBAL); if (isGlobal) { entry = entry.substring(GLOBAL.length()); } else { File file = resolveVariables(entry); if (!file.isAbsolute()) { file = new File(container, entry); } if (!file.exists()) { int offset = line.indexOf(entry); result.add(new MappingParseStatus(lineNo, offset + buffer, offset + entry.length() + buffer, MappingParseMessage.NOT_EXIST)); } } } } return result; } private File resolveVariables(String lib) { File file = new File(lib); try { if (variableResolver != null) { String path = variableResolver.resolve(lib); file = new File(path); } } catch (SdkException e) { return new File(lib); } return file; } private MappingParseStatus checkValidKey(String key, int lineNo, String line) { key = key.trim(); if (key.equals(APPDIR + INCLUDES)) { hasAppdir = true; return null; } else if (key.equals(APPDIR + EXCLUDES) || key.equals(SCRIPTSDIR + INCLUDES) || key.equals(SCRIPTSDIR + EXCLUDES) || key.equals(LIBRARY + INCLUDES)) { return null; } else { String[] parts = key.split(KEY_SEPARATOR); if (parts.length != 2 || parts[0].isEmpty() || parts[1].isEmpty()) { int start = line.indexOf(key) + buffer; int end = start + key.length(); return new MappingParseStatus(lineNo, start, end, MappingParseMessage.INVALID_KEY); } String folder = parts[0]; if (APPDIR.equals(folder) || SCRIPTSDIR.equals(folder)) { String suffix = parts[1]; if (INCLUDES.equals(suffix) || EXCLUDES.equals(suffix)) { return null; } else { int start = line.indexOf(key) + folder.length() + buffer + 1; int end = line.indexOf(key) + key.length() + buffer; return new MappingParseStatus(lineNo, start, end, MappingParseMessage.INVALID_SUFFIX); } } else { int start = line.indexOf(key) + buffer; int end = start + folder.length(); return new MappingParseStatus(lineNo, start, end, MappingParseMessage.INVALID_FOLDER); } } } }