/*
* Copyright (C) 2005-2012 BetaCONCEPT Limited
*
* This file is part of Astroboa.
*
* Astroboa is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Astroboa is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Astroboa. If not, see <http://www.gnu.org/licenses/>.
*/
package org.betaconceptframework.astroboa.engine.definition.xsom;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.util.CmsConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Used to resolve imports from definition xsd files
* and mainly to provide the right xsd definition file
* when validating definition files.
*
* This resolver must have all definitions inside a map.
*
*
* @author Gregory Chomatas (gchomatas@betaconcept.com)
* @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
*
*/
public class CmsEntityResolverForValidation implements EntityResolver{
private final Logger logger = LoggerFactory.getLogger(getClass());
private Map<String, String> definitionSources = new HashMap<String, String>();
private List<InputStream> openStreams = new ArrayList<InputStream>();
private EntityResolverForBuiltInSchemas entityResolverForBuiltInSchemas;
@Override
/**
* According to XSOM library
* By setting EntityResolver to XSOMParser, you can redirect <xs:include>s and <xs:import>s to different resources.
* For imports, the namespace URI of the target schema is passed as the public ID,
* and the absolutized value of the schemaLocation attribute will be passed as the system ID.
*/
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if (systemId != null){
try {
String schemaFilename = systemId;
//We are only interested in file name
if (schemaFilename.contains(File.separator)){
schemaFilename = StringUtils.substringAfterLast(systemId, File.separator);
}
else if (! File.separator.equals(schemaFilename.contains(CmsConstants.FORWARD_SLASH)) && schemaFilename.contains(CmsConstants.FORWARD_SLASH)){
//Perform the extra check in case File.separator is not '/' and it
//does not exist in the schema filename.
//This case usually appears in a windows environment.
schemaFilename = StringUtils.substringAfterLast(systemId, CmsConstants.FORWARD_SLASH);
}
if (definitionSources.containsKey(schemaFilename)){
InputStream inputStream = IOUtils.toInputStream(definitionSources.get(schemaFilename), "UTF-8");
openStreams.add(inputStream);
InputSource inputSource = new InputSource(inputStream);
inputSource.setPublicId(publicId);
inputSource.setSystemId(schemaFilename);
return inputSource;
}
return entityResolverForBuiltInSchemas.resolveEntity(publicId, systemId);
} catch (Exception e) {
throw new IOException(e);
}
}
//Returning null allow XSD Parser to continue with default behavior
//and will try to resolve entity using its own implementation
return null;
}
public void clearDefinitions(){
if (! openStreams.isEmpty()){
for (InputStream openStream : openStreams){
IOUtils.closeQuietly(openStream);
}
}
definitionSources.clear();
openStreams.clear();
}
public void addExternalDefinition(File definitionFile) throws IOException {
if (definitionFile != null){
definitionSources.put(definitionFile.getName(), FileUtils.readFileToString(definitionFile, "UTF-8"));
}
}
public void addDefinition(String definitionName,
String definition) throws IOException {
if (definitionName != null && definition != null){
if (definitionName.contains(CmsConstants.FORWARD_SLASH)){
definitionSources.put(StringUtils.substringAfterLast(definitionName, CmsConstants.FORWARD_SLASH), definition);
}
else{
definitionSources.put(definitionName, definition);
}
}
}
public Map<String,String> getDefinitionSources(){
return definitionSources;
}
public void setBuiltInEntityResolver(
EntityResolverForBuiltInSchemas entityResolverForBuiltInSchemas) {
this.entityResolverForBuiltInSchemas = entityResolverForBuiltInSchemas;
}
}