Changeset 5382


Ignore:
Timestamp:
06/24/14 15:15:32 (10 years ago)
Author:
Oliver Schonefeld
Message:
  • major refactoring
  • bump version
Location:
CMDIValidator/trunk
Files:
4 added
5 deleted
5 edited
3 moved

Legend:

Unmodified
Added
Removed
  • CMDIValidator/trunk/cmdi-validator-core/pom.xml

    r5336 r5382  
    66        <groupId>eu.clarin.cmdi</groupId>
    77        <artifactId>cmdi-validator</artifactId>
    8         <version>0.0.4-SNAPSHOT</version>
     8        <version>0.0.5-SNAPSHOT</version>
    99    </parent>
    1010    <artifactId>cmdi-validator-core</artifactId>
  • CMDIValidator/trunk/cmdi-validator-core/src/main/java/eu/clarin/cmdi/validator/CMDISchemaLoader.java

    r5369 r5382  
    2525import org.slf4j.LoggerFactory;
    2626
    27 final class SchemaLoader {
    28     static final long DISABLE_CACHE_AGING = -1;
     27public final class CMDISchemaLoader {
     28    public static final long DISABLE_CACHE_AGING = -1;
    2929    private static final Logger logger =
    30             LoggerFactory.getLogger(SchemaLoader.class);
     30            LoggerFactory.getLogger(CMDISchemaLoader.class);
    3131    private static final String XML_XSD_RESSOURCE = "/xml.xsd";
    3232    private final File cacheDirectory;
     
    3535
    3636
    37     SchemaLoader(File cacheDirectory, long maxCacheAge) {
     37    public CMDISchemaLoader(File cacheDirectory, long maxCacheAge) {
    3838        if (cacheDirectory == null) {
    3939            throw new NullPointerException("cacheDirectory == null");
     
    4343        }
    4444        this.cacheDirectory = cacheDirectory;
    45         this.maxCacheAge = maxCacheAge;
    46         this.httpClient = new DefaultHttpClient();
     45        this.maxCacheAge    = maxCacheAge;
     46        this.httpClient     = new DefaultHttpClient();
    4747
    4848        final HttpParams params = this.httpClient.getParams();
     
    5555
    5656
     57    public CMDISchemaLoader(File cacheDirectory) {
     58        this(cacheDirectory, DISABLE_CACHE_AGING);
     59    }
     60
     61
    5762    public synchronized InputStream loadSchemaFile(String targetNamespace,
    5863            String schemaLocation) throws IOException {
     
    6469        }
    6570
    66         logger.debug("loading schema: targetNamespace={}, location={}",
     71        logger.trace("loading schema: targetNamespace={}, location={}",
    6772                targetNamespace, schemaLocation);
    6873        InputStream stream = null;
     
    7075            stream = this.getClass().getResourceAsStream(XML_XSD_RESSOURCE);
    7176            if (stream != null) {
    72                 logger.debug("using bundled schema for '{}'", schemaLocation);
     77                logger.trace("using bundled schema for '{}'", schemaLocation);
    7378                return stream;
    7479            }
     
    7782        }
    7883
    79         final String key = stripBadChars(schemaLocation);
    80 
    8184        // fall back to file cache ...
    82         final File cacheFile = makeCacheFile(key);
     85        final File cacheFile = makeCacheFile(schemaLocation);
    8386        if (cacheFile.exists()) {
    8487            final long age =
    8588                    System.currentTimeMillis() - cacheFile.lastModified();
    8689            if ((maxCacheAge != DISABLE_CACHE_AGING) && (age > maxCacheAge)) {
    87                 logger.debug("-> cached file '{}' expired", cacheFile);
     90                logger.trace("-> cached file '{}' expired", cacheFile);
    8891                cacheFile.delete();
    8992            } else {
    90                 logger.debug("-> from file cache");
     93                logger.trace("-> from file cache");
    9194                return new FileInputStream(cacheFile);
    9295            }
     
    9497
    9598        try {
    96             logger.debug("-> downloading schema from '{}'", schemaLocation);
     99            logger.debug("downloading schema from '{}'", schemaLocation);
    97100            final URI uri = new URI(schemaLocation);
    98101            final HttpResponse response = executeRequest(uri);
     
    134137
    135138
    136     private File makeCacheFile(String key) {
    137         return new File(cacheDirectory, key + ".xsd");
    138     }
    139 
    140 
    141     private static String stripBadChars(String uri) {
     139    private File makeCacheFile(String schemaLocation) {
    142140        final StringBuilder sb = new StringBuilder();
    143         for (int i = 0; i < uri.length(); i++) {
    144             final char c = uri.charAt(i);
     141        for (int i = 0; i < schemaLocation.length(); i++) {
     142            final char c = schemaLocation.charAt(i);
    145143            switch (c) {
     144            case '.':
     145                /* FALL-THROUGH */
    146146            case ':':
    147147                /* FALL-THROUGH */
     148            case ';':
     149                /* FALL-THROUGH */
     150            case '?':
     151                /* FALL-THROUGH */
     152            case '&':
     153                /* FALL-THROUGH */
     154            case '=':
     155                /* FALL-THROUGH */
     156            case '"':
     157                /* FALL-THROUGH */
     158            case '\'':
     159                /* FALL-THROUGH */
    148160            case '/':
    149                 /* FALL-THROUGH */
    150             case '?':
    151                 /* FALL-THROUGH */
    152             case '&':
    153                 /* FALL-THROUGH */
    154             case '=':
    155                 /* FALL-THROUGH */
    156             case '.':
    157                 /* FALL-THROUGH */
    158             case ';':
    159                 /* FALL-THROUGH */
    160             case '"':
    161                 /* FALL-THROUGH */
    162             case '\'':
    163161                /* FALL-THROUGH */
    164162            case '\\':
     
    168166                sb.append(c);
    169167            }
    170         }
    171         return sb.toString();
     168        } // for
     169        sb.append(".xsd");
     170        return new File(cacheDirectory, sb.toString());
    172171    }
    173172
     
    177176        HttpResponse response = null;
    178177        try {
    179             logger.debug("submitting HTTP request: {}", uri.toString());
     178            logger.trace("submitting HTTP request: {}", uri.toString());
    180179            request = new HttpGet(uri);
    181180            response = httpClient.execute(request);
     
    212211    }
    213212
    214 } // class SchemaLoader
     213} // class CMDISchemaLoader
  • CMDIValidator/trunk/cmdi-validator-core/src/main/java/eu/clarin/cmdi/validator/CMDIValidator.java

    r5370 r5382  
    22
    33import java.io.File;
     4import java.io.FileFilter;
    45import java.io.IOException;
    56import java.io.InputStream;
     7import java.net.MalformedURLException;
     8import java.net.URL;
     9import java.util.Collections;
    610import java.util.LinkedHashSet;
     11import java.util.LinkedList;
    712import java.util.List;
    813import java.util.Map;
    914import java.util.Set;
     15import java.util.concurrent.ConcurrentHashMap;
     16import java.util.concurrent.atomic.AtomicInteger;
    1017
    1118import javax.xml.XMLConstants;
    1219import javax.xml.transform.dom.DOMSource;
    13 
     20import javax.xml.transform.stream.StreamSource;
     21
     22import net.java.truevfs.access.TFile;
     23import net.java.truevfs.access.TFileInputStream;
    1424import net.sf.saxon.s9api.Axis;
    1525import net.sf.saxon.s9api.DocumentBuilder;
     
    2535import net.sf.saxon.s9api.XdmNode;
    2636import net.sf.saxon.s9api.XdmSequenceIterator;
     37import net.sf.saxon.s9api.XsltCompiler;
    2738import net.sf.saxon.s9api.XsltExecutable;
    2839import net.sf.saxon.s9api.XsltTransformer;
    2940
     41import org.apache.commons.lang3.SystemUtils;
    3042import org.apache.xerces.impl.xs.XMLSchemaLoader;
    3143import org.apache.xerces.impl.xs.XSDDescription;
     
    5365
    5466public final class CMDIValidator {
     67    public enum Result {
     68        OK, ABORTED, ERROR
     69    }
    5570    private static final Logger logger =
    5671            LoggerFactory.getLogger(CMDIValidator.class);
     72    private static final String SCHEMATATRON_STAGE_1 =
     73            "/schematron/iso_dsdl_include.xsl";
     74    private static final String SCHEMATATRON_STAGE_2 =
     75            "/schematron/iso_abstract_expand.xsl";
     76    private static final String SCHEMATATRON_STAGE_3 =
     77            "/schematron/iso_svrl_for_xslt2.xsl";
     78    private static final String DEFAULT_SCHEMATRON_SCHEMA =
     79            "/default.sch";
    5780    private static final String XML_SCHEMA_LOCATION =
    5881            "http://www.w3.org/2001/xml.xsd";
     
    7295            "http://apache.org/xml/features/honour-all-schemaLocations";
    7396    private static final int INITAL_SYMBOL_TABLE_SIZE = 16141;
    74     private static final String SVRL_NAMESPACE_URI = "http://purl.oclc.org/dsdl/svrl";
    75     private static final String SVRL_NAMESPACE_PREFIX = "svrl";
     97    private static final String SVRL_NAMESPACE_URI =
     98            "http://purl.oclc.org/dsdl/svrl";
     99    private static final String SVRL_NAMESPACE_PREFIX =
     100            "svrl";
    76101    private static final QName SVRL_TEXT =
    77102            new QName(SVRL_NAMESPACE_URI, "text");
     
    79104            new QName(SVRL_NAMESPACE_URI, "failed-assert");
    80105    private final Processor processor;
     106    private final CMDISchemaLoader schemaLoader;
     107    private final XsltExecutable schematronValidatorExecutable;
    81108    private final XPathExecutable xpath1;
    82109    private final XPathExecutable xpath2;
    83     private final XsltTransformer schematronValidator;
    84     private final XML11Configuration config;
    85     private final DocumentBuilder builder;
    86110    private final List<CMDIValidatorExtension> extensions;
    87     private final CMDIValidatorResultImpl result;
    88 
    89 
    90     CMDIValidator(final Processor processor,
    91             final SchemaLoader schemaLoader,
    92             XsltExecutable schematronExecutable,
    93             List<CMDIValidatorExtension> extensions)
     111    private final FileEnumerator files;
     112    private final CMDIValidatorHandler handler;
     113    private final Map<Thread, ThreadContext> contexts =
     114            new ConcurrentHashMap<Thread, ThreadContext>();
     115    private final AtomicInteger threadsProcessing = new AtomicInteger();
     116    private State state = State.INIT;
     117    private Result result = null;
     118
     119
     120    public CMDIValidator(final CMDIValidatorConfig config)
    94121            throws CMDIValidatorInitException {
    95         if (processor == null) {
    96             throw new NullPointerException("processor == null");
    97         }
    98         this.processor = processor;
    99         if (schematronExecutable != null) {
     122        if (config == null) {
     123            throw new NullPointerException("config == null");
     124        }
     125
     126        /*
     127         * initialize custom schema loader
     128         */
     129        if (config.getSchemaLoader() != null) {
     130            logger.debug("using supplied schema loader ...");
     131            this.schemaLoader = config.getSchemaLoader();
     132        } else {
     133            logger.debug("initializing schema loader ...");
     134            this.schemaLoader = initSchemaLoader(config);
     135        }
     136
     137        /*
     138         * initialize Saxon processor
     139         */
     140        logger.debug("initializing Saxon ...");
     141        this.processor = new Processor(true);
     142
     143        /*
     144         * initialize Schematron validator
     145         */
     146        if (!config.isSchematronDisabled()) {
     147            this.schematronValidatorExecutable =
     148                    initSchematronValidator(config, processor);
    100149            try {
    101150                final XPathCompiler compiler = processor.newXPathCompiler();
     
    103152                this.xpath1 = compiler.compile("//(svrl:failed-assert|svrl:successful-report)");
    104153                this.xpath2 = compiler.compile("preceding-sibling::svrl:fired-rule/@role");
    105                 this.schematronValidator = schematronExecutable.load();
    106154            } catch (SaxonApiException e) {
    107155                throw new CMDIValidatorInitException(
    108                         "error initializing validator", e);
    109             }
     156                        "error initializing schematron validator", e);
     157            }
     158            logger.debug("Schematron validator successfully initialized");
    110159        } else {
    111             this.xpath1              = null;
    112             this.xpath2              = null;
    113             this.schematronValidator = null;
    114         }
    115 
     160            this.schematronValidatorExecutable = null;
     161            this.xpath1                        = null;
     162            this.xpath2                        = null;
     163        }
     164
     165        /*
     166         * initialize extensions
     167         */
     168        final List<CMDIValidatorExtension> exts = config.getExtensions();
     169        if (exts != null) {
     170            this.extensions = new LinkedList<CMDIValidatorExtension>();
     171            for (CMDIValidatorExtension extension : exts) {
     172                extension.initalize(processor);
     173                extensions.add(extension);
     174            }
     175        } else {
     176            this.extensions = null;
     177        }
     178
     179        /*
     180         * other stuff
     181         */
     182        final TFile root = new TFile(config.getRoot());
     183        this.files       = new FileEnumerator(root, config.getFileFilter());
     184        if (config.getHandler() == null) {
     185            throw new NullPointerException("handler == null");
     186        }
     187        this.handler = config.getHandler();
     188    }
     189
     190
     191    public CMDIValidatorHandler getHandler() {
     192        return handler;
     193    }
     194
     195
     196    public void abort() {
     197        synchronized (this) {
     198            if ((state == State.INIT) || (state == State.RUN)) {
     199                state = State.DONE;
     200                files.flush();
     201                if (result == null) {
     202                    result = Result.ABORTED;
     203                }
     204            }
     205        } // synchronized (this)
     206    }
     207
     208
     209    boolean processOneFile() throws CMDIValidatorException {
    116210        try {
     211            TFile file = null;
     212            boolean done;
     213
     214            threadsProcessing.incrementAndGet();
     215
     216            synchronized (this) {
     217                switch (state) {
     218                case INIT:
     219                    try {
     220                        state = State.RUN;
     221                        handler.onJobStarted();
     222                    } catch (CMDIValidatorException e) {
     223                        state = State.DONE;
     224                        throw e;
     225                    }
     226                    /* FALL-THROUGH */
     227                case RUN:
     228                    file = files.nextFile();
     229                    if (files.isEmpty() && (state == State.RUN)) {
     230                        state = State.DONE;
     231                    }
     232                    break;
     233                default:
     234                    // ignore
     235                }
     236
     237                done = (state == State.DONE);
     238            } // synchronized (this)
     239
     240            if (file != null) {
     241                ThreadContext context = contexts.get(Thread.currentThread());
     242                if (context == null) {
     243                    context = new ThreadContext();
     244                    contexts.put(Thread.currentThread(), context);
     245                }
     246                context.validate(file);
     247            }
     248
     249            return done;
     250        } catch (CMDIValidatorException e) {
     251            synchronized (this) {
     252                state = State.DONE;
     253                if (result == null) {
     254                    result = Result.ERROR;
     255                }
     256            } // synchronized (this)
     257            throw e;
     258        } finally {
     259            if (threadsProcessing.decrementAndGet() <= 0) {
     260                synchronized (this) {
     261                    if (state == State.DONE) {
     262                        state = State.FINI;
     263                        if (result == null) {
     264                            result = Result.OK;
     265                        }
     266
     267                        // notify handler
     268                        handler.onJobFinished(result);
     269                    }
     270                } // synchronized (this)
     271            }
     272        }
     273    }
     274
     275
     276    private static CMDISchemaLoader initSchemaLoader(
     277            final CMDIValidatorConfig config) throws CMDIValidatorInitException {
     278        File cacheDirectory = config.getSchemaCacheDirectory();
     279        if (cacheDirectory == null) {
     280            if (SystemUtils.IS_OS_WINDOWS &&
     281                    (SystemUtils.JAVA_IO_TMPDIR != null)) {
     282                cacheDirectory =
     283                        new File(SystemUtils.JAVA_IO_TMPDIR, "cmdi-validator");
     284            } else if (SystemUtils.IS_OS_UNIX &&
     285                    (SystemUtils.USER_HOME != null)) {
     286                cacheDirectory =
     287                        new File(SystemUtils.USER_HOME, ".cmdi-validator");
     288            }
     289            if (cacheDirectory != null) {
     290                if (!cacheDirectory.exists()) {
     291                    if (!cacheDirectory.mkdir()) {
     292                        throw new CMDIValidatorInitException(
     293                                "cannot create cache directory: " +
     294                                        cacheDirectory);
     295                    }
     296                }
     297            } else {
     298                if (SystemUtils.JAVA_IO_TMPDIR == null) {
     299                    throw new CMDIValidatorInitException(
     300                            "cannot determine temporary directory");
     301                }
     302                cacheDirectory = new File(SystemUtils.JAVA_IO_TMPDIR);
     303            }
     304        } else {
     305            if (!cacheDirectory.isDirectory()) {
     306                throw new CMDIValidatorInitException(
     307                        "supplied cache dircetory '" +
     308                                cacheDirectory.getAbsolutePath() +
     309                                "' is not a directory");
     310            }
     311            if (!cacheDirectory.canWrite()) {
     312                throw new CMDIValidatorInitException("cache dircetory '" +
     313                        cacheDirectory.getAbsolutePath() + "' is not writable");
     314            }
     315        }
     316        return new CMDISchemaLoader(cacheDirectory, CMDISchemaLoader.DISABLE_CACHE_AGING);
     317    }
     318
     319
     320    private static XsltExecutable initSchematronValidator(
     321            final CMDIValidatorConfig config, final Processor processor)
     322            throws CMDIValidatorInitException {
     323        URL schema = null;
     324        File schematronSchemaFile = config.getSchematronSchemaFile();
     325        if (schematronSchemaFile != null) {
     326            if (!schematronSchemaFile.exists()) {
     327                throw new CMDIValidatorInitException("file '" +
     328                        schematronSchemaFile.getAbsolutePath() +
     329                        "' does not exist");
     330            }
     331            if (!schematronSchemaFile.isFile()) {
     332                throw new CMDIValidatorInitException("file '" +
     333                        schematronSchemaFile.getAbsolutePath() +
     334                        "' is not a regular file");
     335            }
     336            if (!schematronSchemaFile.canRead()) {
     337                throw new CMDIValidatorInitException("file '" +
     338                        schematronSchemaFile.getAbsolutePath() +
     339                        "' cannot be read");
     340            }
     341            try {
     342                schema = schematronSchemaFile.toURI().toURL();
     343            } catch (MalformedURLException e) {
     344                throw new CMDIValidatorInitException("internal error", e);
     345            }
     346        } else {
     347            schema = CMDIValidator.class.getResource(DEFAULT_SCHEMATRON_SCHEMA);
     348            if (schema == null) {
     349                throw new CMDIValidatorInitException(
     350                        "cannot locate bundled Schematron schema: " +
     351                                DEFAULT_SCHEMATRON_SCHEMA);
     352            }
     353        }
     354        final XsltCompiler compiler = processor.newXsltCompiler();
     355        XsltTransformer stage1 =
     356                loadStylesheet(processor, compiler, SCHEMATATRON_STAGE_1);
     357        XsltTransformer stage2 =
     358                loadStylesheet(processor, compiler, SCHEMATATRON_STAGE_2);
     359        XsltTransformer stage3 =
     360                loadStylesheet(processor, compiler, SCHEMATATRON_STAGE_3);
     361        try {
     362            XdmDestination destination = new XdmDestination();
     363            stage1.setSource(new StreamSource(schema.toExternalForm()));
     364            stage1.setDestination(stage2);
     365            stage2.setDestination(stage3);
     366            stage3.setDestination(destination);
     367            stage1.transform();
     368            return compiler.compile(destination.getXdmNode().asSource());
     369        } catch (SaxonApiException e) {
     370            throw new CMDIValidatorInitException(
     371                    "error compiling schematron rules", e);
     372        }
     373    }
     374
     375
     376    private static XsltTransformer loadStylesheet(final Processor processor,
     377            final XsltCompiler compiler, final String name)
     378            throws CMDIValidatorInitException {
     379        try {
     380            logger.debug("loading stylesheet '{}'", name);
     381            final URL uri = CMDIValidator.class.getResource(name);
     382            if (uri != null) {
     383                DocumentBuilder builder = processor.newDocumentBuilder();
     384                XdmNode source =
     385                        builder.build(new StreamSource(uri.toExternalForm()));
     386                XsltExecutable stylesheet = compiler.compile(source.asSource());
     387                return stylesheet.load();
     388            } else {
     389                throw new CMDIValidatorInitException("cannot find resource '" +
     390                        name + "'");
     391            }
     392        } catch (SaxonApiException e) {
     393            throw new CMDIValidatorInitException(
     394                    "error loading schematron stylesheet '" + name + "'", e);
     395        }
     396    }
     397
     398
     399    private enum State {
     400        INIT, RUN, DONE, FINI;
     401    }
     402
     403
     404    private final class ThreadContext {
     405        private final XML11Configuration xercesConfig;
     406        private final XsltTransformer schematronValidator;
     407        private final DocumentBuilder builder;
     408        private final ResultImpl result = new ResultImpl();
     409
     410
     411        private ThreadContext() {
    117412            /*
    118413             * initialize Xerces
    119414             */
    120             XMLEntityResolver resolver = new XMLEntityResolver() {
     415            final XMLEntityResolver resolver = new XMLEntityResolver() {
    121416                @Override
    122417                public XMLInputSource resolveEntity(
     
    125420                    final String uri = identifier.getExpandedSystemId();
    126421                    if (uri == null) {
    127                         throw new IOException("bad schema location for namespace '" +
     422                        throw new IOException(
     423                                "bad schema location for namespace '" +
    128424                                        identifier.getNamespace() + "': " +
    129425                                        identifier.getLiteralSystemId());
     
    148444                }
    149445
     446
    150447                @Override
    151448                public void error(String domain, String key, XMLParseException e)
     
    154451                }
    155452
     453
    156454                @Override
    157455                public void fatalError(String domain, String key,
     
    161459            });
    162460
    163             InputStream stream = null;
    164461            try {
    165                 stream = schemaLoader.loadSchemaFile(XMLConstants.XML_NS_URI,
    166                         XML_SCHEMA_LOCATION);
    167                 Grammar grammar = xsdLoader.loadGrammar(
    168                         new XMLInputSource(XMLConstants.XML_NS_URI,
    169                                 XML_SCHEMA_LOCATION, null, stream, null));
    170                 if (grammar != null) {
    171                     pool.cacheGrammars(XML_SCHEMA_GRAMMAR_TYPE,
    172                             new Grammar[] { grammar });
    173                 }
    174                 pool.lockPool();
    175             } finally {
    176                 if (stream != null) {
    177                     stream.close();
    178                 }
    179             }
    180 
    181             config = new XML11Configuration(symbols, pool);
    182             config.setFeature(NAMESPACES_FEATURE_ID, true);
    183             config.setFeature(VALIDATION_FEATURE_ID, true);
    184             config.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
    185             config.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
    186             config.setFeature(HONOUR_ALL_SCHEMA_LOCATIONS_ID, true);
    187             config.setEntityResolver(resolver);
    188             config.setErrorHandler(new XMLErrorHandler() {
     462                InputStream stream = null;
     463                try {
     464                    stream = schemaLoader.loadSchemaFile(
     465                            XMLConstants.XML_NS_URI, XML_SCHEMA_LOCATION);
     466                    Grammar grammar = xsdLoader.loadGrammar(new XMLInputSource(
     467                            XMLConstants.XML_NS_URI, XML_SCHEMA_LOCATION, null,
     468                            stream, null));
     469                    if (grammar != null) {
     470                        pool.cacheGrammars(XML_SCHEMA_GRAMMAR_TYPE,
     471                                new Grammar[] { grammar });
     472                    }
     473                    pool.lockPool();
     474                } finally {
     475                    if (stream != null) {
     476                        stream.close();
     477                    }
     478                }
     479            } catch (IOException e) {
     480                /*
     481                 * Should never happen
     482                 */
     483                logger.error("error initaliting thread context", e);
     484            }
     485
     486            xercesConfig = new XML11Configuration(symbols, pool);
     487            xercesConfig.setFeature(NAMESPACES_FEATURE_ID, true);
     488            xercesConfig.setFeature(VALIDATION_FEATURE_ID, true);
     489            xercesConfig.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
     490            xercesConfig.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
     491            xercesConfig.setFeature(HONOUR_ALL_SCHEMA_LOCATIONS_ID, true);
     492            xercesConfig.setEntityResolver(resolver);
     493            xercesConfig.setErrorHandler(new XMLErrorHandler() {
    189494                @Override
    190495                public void warning(String domain, String key,
    191496                        XMLParseException e) throws XNIException {
    192                     reportWarning(e.getLineNumber(), e.getColumnNumber(),
     497                    reportWarning(e.getLineNumber(),
     498                            e.getColumnNumber(),
    193499                            e.getMessage(), e);
    194500                }
    195501
     502
    196503                @Override
    197                 public void error(String domain, String key, XMLParseException e)
    198                         throws XNIException {
    199                     reportError(e.getLineNumber(), e.getColumnNumber(),
     504                public void error(String domain, String key,
     505                        XMLParseException e) throws XNIException {
     506                    reportError(e.getLineNumber(),
     507                            e.getColumnNumber(),
    200508                            e.getMessage(), e);
    201509                    throw e;
    202510                }
     511
    203512
    204513                @Override
    205514                public void fatalError(String domain, String key,
    206515                        XMLParseException e) throws XNIException {
    207                     reportError(e.getLineNumber(), e.getColumnNumber(),
     516                    reportError(e.getLineNumber(),
     517                            e.getColumnNumber(),
    208518                            e.getMessage(), e);
    209519                    throw e;
     
    214524             * initialize Saxon document builder
    215525             */
    216             this.builder = this.processor.newDocumentBuilder();
     526            this.builder = processor.newDocumentBuilder();
    217527            this.builder.setWhitespaceStrippingPolicy(
    218528                    WhitespaceStrippingPolicy.IGNORABLE);
    219529
    220530            /*
    221              * extensions
     531             * initialize schematron
    222532             */
    223             this.extensions = extensions;
    224 
    225             /*
    226              * initialize other stuff
    227              */
    228             this.result =  new CMDIValidatorResultImpl();
    229         } catch (IOException e) {
    230             throw new CMDIValidatorInitException("initialization failed", e);
     533            if (schematronValidatorExecutable != null) {
     534                this.schematronValidator = schematronValidatorExecutable.load();
     535            } else {
     536                this.schematronValidator = null;
     537            }
     538        }
     539
     540
     541        private void validate(final TFile file) throws CMDIValidatorException {
     542            TFileInputStream stream = null;
     543            try {
     544                /*
     545                 * step 0: prepare
     546                 */
     547                logger.debug("validating file '{}' ({} bytes)",
     548                        file, file.length());
     549                result.setFile(file);
     550                stream = new TFileInputStream(file);
     551
     552                /*
     553                 * step 1: parse document and perform schema validation
     554                 */
     555                final XdmNode document = parseInstance(stream);
     556
     557                if (document != null) {
     558                    /*
     559                     * step 2: perform Schematron validation
     560                     */
     561                    if (schematronValidator != null) {
     562                        validateSchematron(document);
     563                    }
     564
     565                    /*
     566                     * step 3: run extensions, if any
     567                     */
     568                    if (extensions != null) {
     569                        for (CMDIValidatorExtension extension : extensions) {
     570                            extension.validate(document, result);
     571                        }
     572                    }
     573                }
     574            } catch (IOException e) {
     575                throw new CMDIValidatorException(
     576                        "error reading file '" + file + "'", e);
     577            } catch (CMDIValidatorException e) {
     578                throw e;
     579            } finally {
     580                try {
     581                    if (stream != null) {
     582                        stream.close();
     583                    }
     584                } catch (IOException e) {
     585                    throw new CMDIValidatorException(
     586                            "error closing file '" + file + "'", e);
     587                } finally {
     588                    if (handler != null) {
     589                        if (result.isHighestSeverity(Severity.ERROR)) {
     590                            handler.onValidationFailure(result);
     591                        } else {
     592                            handler.onValidationSuccess(result);
     593                        }
     594                    }
     595                    result.reset();
     596                }
     597            }
     598        }
     599
     600
     601        private XdmNode parseInstance(InputStream stream)
     602                throws CMDIValidatorException {
     603            try {
     604                final DOMParser parser = new DOMParser(xercesConfig);
     605                try {
     606                    parser.parse(new InputSource(stream));
     607                    stream.close();
     608
     609                    final Document dom = parser.getDocument();
     610                    if (dom == null) {
     611                        throw new CMDIValidatorException(
     612                                "parser returned no return result");
     613                    }
     614                    return builder.build(new DOMSource(dom));
     615                } finally {
     616                    parser.reset();
     617                }
     618            } catch (SAXException e) {
     619                logger.trace("error parsing instance", e);
     620                return null;
     621            } catch (SaxonApiException e) {
     622                logger.trace("error parsing instance", e);
     623                return null;
     624            } catch (IOException e) {
     625                final String message = (e.getMessage() != null)
     626                        ? e.getMessage()
     627                        : "input/output error";
     628                throw new CMDIValidatorException(message, e);
     629            } finally {
     630                /* really make sure, stream is closed */
     631                try {
     632                    stream.close();
     633                } catch (IOException e) {
     634                    /* IGNORE */
     635                }
     636            }
     637        }
     638
     639
     640        private void validateSchematron(XdmNode document)
     641                throws CMDIValidatorException {
     642            try {
     643                logger.trace("performing schematron validation ...");
     644                schematronValidator.setSource(document.asSource());
     645                final XdmDestination destination = new XdmDestination();
     646                schematronValidator.setDestination(destination);
     647                schematronValidator.transform();
     648
     649                final XPathSelector selector = xpath1.load();
     650                selector.setContextItem(destination.getXdmNode());
     651                for (XdmItem item : selector) {
     652                    final XdmNode node = (XdmNode) item;
     653                    final XdmNode text = getFirstChild(node, SVRL_TEXT);
     654                    String msg = (text != null)
     655                            ? text.getStringValue().trim()
     656                            : null;
     657                    if (SVRL_FAILED_ASSERT.equals(node.getNodeName())) {
     658                        final XPathSelector selector2 = xpath2.load();
     659                        String role = null;
     660                        selector2.setContextItem(node);
     661                        XdmItem evaluateSingle = selector2.evaluateSingle();
     662                        if (evaluateSingle != null) {
     663                            role = evaluateSingle.getStringValue().trim();
     664                        }
     665                        if ("warning".equalsIgnoreCase(role)) {
     666                            result.reportWarning(-1, -1, msg);
     667                        } else {
     668                            result.reportError(-1, -1, msg);
     669                        }
     670                    } else {
     671                        result.reportInfo(-1, -1, msg);
     672                    }
     673                }
     674            } catch (SaxonApiException e) {
     675                throw new CMDIValidatorException(
     676                        "error performing schematron validation", e);
     677            }
     678        }
     679
     680
     681        private XdmNode getFirstChild(XdmNode parent, QName name) {
     682            XdmSequenceIterator i = parent.axisIterator(Axis.CHILD, name);
     683            if (i.hasNext()) {
     684                return (XdmNode) i.next();
     685            } else {
     686                return null;
     687            }
     688        }
     689
     690
     691        private void reportWarning(int line, int col, String message,
     692                Throwable cause) {
     693            logger.debug("reporting warning: [{}:{}]: {}", line, col, message);
     694            if (result != null) {
     695                result.reportWarning(line, col, message, cause);
     696            }
     697        }
     698
     699
     700        private void reportError(int line, int col, String message,
     701                Throwable cause) {
     702            logger.debug("reporting error: [{}:{}]: {}", line, col, message);
     703            if (result != null) {
     704                result.reportError(line, col, message, cause);
     705            }
    231706        }
    232707    }
    233708
    234709
    235     public void validate(InputStream stream, File file,
    236             CMDIValidatorJobHandler handler) throws CMDIValidatorException {
    237         if (stream == null) {
    238             throw new NullPointerException("stream == null");
    239         }
    240 
    241         try {
    242             result.setFile(file);
    243 
    244             /*
    245              * step 1: parse document and perform schema validation
    246              */
    247             final XdmNode document = parseInstance(stream);
    248 
    249             if (document != null) {
    250                 /*
    251                  * step 2: perform Schematron validation
    252                  */
    253                 if (schematronValidator != null) {
    254                     validateSchematron(document);
    255                 }
    256 
    257                 /*
    258                  * step 3: run extensions, if any
    259                  */
    260                 if (extensions != null) {
    261                     for (CMDIValidatorExtension extension : extensions) {
    262                         extension.validate(document, result);
    263                     }
    264                 }
     710    private static final class FileEnumerator {
     711        private final class FileList {
     712            private final TFile[] fileList;
     713            private int idx = 0;
     714
     715
     716            private FileList(TFile[] fileList) {
     717                this.fileList = fileList;
     718            }
     719
     720
     721            private TFile nextFile() {
     722                while (idx < fileList.length) {
     723                    final TFile file = fileList[idx++];
     724                    if (file.isDirectory()) {
     725                        return file;
     726                    }
     727                    if ((filter != null) && !filter.accept(file)) {
     728                        continue;
     729                    }
     730                    return file;
     731                } // while
     732                return null;
     733            }
     734
     735            private int size() {
     736                return (fileList.length - idx);
     737            }
     738        }
     739        private final FileFilter filter;
     740        private final LinkedList<FileList> stack =
     741                new LinkedList<FileList>();
     742
     743
     744        FileEnumerator(TFile root, FileFilter filter) {
     745            if (root == null) {
     746                throw new NullPointerException("root == null");
     747            }
     748            if (root.isDirectory()) {
     749                pushDirectory(root);
    265750            } else {
    266                 logger.debug("parseInstance() returned no result");
    267             }
    268         } catch (CMDIValidatorException e) {
    269             throw e;
    270         } finally {
    271             if (handler != null) {
    272                 if (result.isHighestSeverity(Severity.ERROR)) {
    273                     handler.onValidationFailure(result);
    274                 } else {
    275                     handler.onValidationSuccess(result);
    276                 }
    277             }
    278             result.reset();
    279         }
    280     }
    281 
    282 
    283     private XdmNode parseInstance(InputStream stream)
    284             throws CMDIValidatorException {
    285         try {
    286             final DOMParser parser = new DOMParser(config);
    287             try {
    288                 parser.parse(new InputSource(stream));
    289                 stream.close();
    290 
    291                 final Document dom = parser.getDocument();
    292                 if (dom == null) {
    293                     throw new CMDIValidatorException(
    294                             "parser returned no return result");
    295                 }
    296                 return builder.build(new DOMSource(dom));
    297             } finally {
    298                 parser.reset();
    299             }
    300         } catch (XNIException e) {
    301             throw new CMDIValidatorException(e.getMessage(), e);
    302         } catch (SaxonApiException e) {
    303             throw new CMDIValidatorException(e.getMessage(), e);
    304         } catch (SAXException e) {
    305             throw new CMDIValidatorException(e.getMessage(), e);
    306         } catch (IOException e) {
    307             throw new CMDIValidatorException(e.getMessage(), e);
    308         } finally {
    309             /* make sure, steam is closed */
    310             try {
    311                 stream.close();
    312             } catch (IOException e) {
    313                 /* IGNORE */
    314             }
    315         }
    316     }
    317 
    318 
    319     private void validateSchematron(XdmNode document)
    320             throws CMDIValidatorException {
    321         try {
    322             logger.debug("performing schematron validation ...");
    323             schematronValidator.setSource(document.asSource());
    324             final XdmDestination destination = new XdmDestination();
    325             schematronValidator.setDestination(destination);
    326             schematronValidator.transform();
    327 
    328 
    329             XPathSelector selector = xpath1.load();
    330             selector.setContextItem(destination.getXdmNode());
    331             for (XdmItem item : selector) {
    332                 final XdmNode node = (XdmNode) item;
    333                 final XdmNode text = getFirstChild(node, SVRL_TEXT);
    334                 String msg = (text != null) ? text.getStringValue().trim() : null;
    335                 if (SVRL_FAILED_ASSERT.equals(node.getNodeName())) {
    336                     XPathSelector selector2 = xpath2.load();
    337                     String role = null;
    338                     selector2.setContextItem(node);
    339                     XdmItem evaluateSingle = selector2.evaluateSingle();
    340                     if (evaluateSingle != null) {
    341                         role = evaluateSingle.getStringValue().trim();
    342                     }
    343                     if ("warning".equalsIgnoreCase(role)) {
    344                         result.reportWarning(-1, -1, msg);
    345                     } else {
    346                         result.reportError(-1, -1, msg);
    347                     }
    348                 } else {
    349                     result.reportInfo(-1, -1, msg);
    350                 }
    351             }
    352         } catch (SaxonApiException e) {
    353             throw new CMDIValidatorException(
    354                     "error performing schematron validation", e);
    355         }
    356     }
    357 
    358 
    359     private static XdmNode getFirstChild(XdmNode parent, QName name) {
    360         XdmSequenceIterator i = parent.axisIterator(Axis.CHILD, name);
    361         if (i.hasNext()) {
    362             return (XdmNode) i.next();
    363         } else {
     751                stack.add(new FileList(new TFile[] { root }));
     752            }
     753            this.filter = filter;
     754        }
     755
     756
     757        boolean isEmpty() {
     758            return stack.isEmpty();
     759        }
     760
     761
     762        TFile nextFile() {
     763            for (;;) {
     764                if (stack.isEmpty()) {
     765                    break;
     766                }
     767                final FileList list = stack.peek();
     768                final TFile file = list.nextFile();
     769                if ((list.size() == 0) || (file == null)) {
     770                    stack.pop();
     771                    if (file == null) {
     772                        continue;
     773                    }
     774                }
     775                if (file.isDirectory()) {
     776                    pushDirectory(file);
     777                    continue;
     778                }
     779                return file;
     780            }
    364781            return null;
    365782        }
    366     }
    367 
    368 
    369     private void reportWarning(int line, int col, String message, Throwable cause) {
    370         logger.debug("reporting warning: [{}:{}]: {}", line, col, message);
    371         if (result != null) {
    372             result.reportWarning(line, col, message, cause);
    373         }
    374     }
    375 
    376 
    377     private void reportError(int line, int col, String message, Throwable cause) {
    378         logger.debug("reporting error: [{}:{}]: {}", line, col, message);
    379         if (result != null) {
    380             result.reportError(line, col, message, cause);
    381         }
    382     }
    383 
    384 
    385     private static class ShadowCacheXMLGrammarPool implements XMLGrammarPool {
     783
     784
     785        void flush() {
     786            stack.clear();
     787        }
     788
     789
     790        private void pushDirectory(TFile directory) {
     791            final TFile[] files = directory.listFiles();
     792            if ((files != null) && (files.length > 0)) {
     793                stack.push(new FileList(files));
     794            }
     795        }
     796
     797    } // class FileEnumerator
     798
     799
     800    private static final class ShadowCacheXMLGrammarPool implements
     801            XMLGrammarPool {
    386802        private final Set<Grammar> cache =
    387803                new LinkedHashSet<Grammar>();
     
    409825        @Override
    410826        public Grammar retrieveGrammar(XMLGrammarDescription d) {
    411             logger.debug("search for grammar: {} / {} / {} / {}",
     827            logger.trace("search for grammar: {} / {} / {} / {}",
    412828                    d.getNamespace(),
    413829                    d.getLiteralSystemId(),
     
    415831                    d.getBaseSystemId());
    416832            if ((d.getNamespace() == null) || !(d instanceof XSDDescription)) {
    417                 logger.debug("-> miss (invalid arguments supplied by caller)");
     833                logger.trace("-> miss (invalid arguments supplied by caller)");
    418834                return null;
    419835            }
     
    423839            Grammar result = findGrammerFromCache(desc);
    424840            if (result != null) {
    425                 logger.debug("-> match from cache: {} -> {} / {}",
     841                logger.trace("-> match from cache: {} -> {} / {}",
    426842                        namespace,
    427843                        desc.getNamespace(),
     
    436852                    locationHint = h[0];
    437853                }
    438                 logger.debug("-> hint: {}", locationHint);
     854                logger.trace("-> hint: {}", locationHint);
    439855            } else if (desc.getLiteralSystemId() != null) {
    440856                locationHint = desc.getLiteralSystemId();
     
    444860                Grammar grammar = shadowCache.get(locationHint);
    445861                if (grammar != null) {
    446                     logger.debug("-> match from shadow cache: {} -> {}",
     862                    logger.trace("-> match from shadow cache: {} -> {}",
    447863                            grammar.getGrammarDescription().getNamespace(),
    448864                            locationHint);
     
    450866                }
    451867            }
    452             logger.debug("-> miss");
     868            logger.trace("-> miss");
    453869            return null;
    454870        }
     
    485901                    if (findGrammerFromCache(gd) == null) {
    486902                        if (!locked) {
    487                             logger.debug("cached grammar: {} / {}",
     903                            logger.trace("cached grammar: {} / {}",
    488904                                    gd.getNamespace(),
    489905                                    gd.getLiteralSystemId());
     
    493909                                        gd.getLiteralSystemId();
    494910                            if (!shadowCache.containsKey(literalSystemId)) {
    495                                 logger.debug("shadow cached grammar: {} / {}",
     911                                logger.trace("shadow cached grammar: {} / {}",
    496912                                        gd.getNamespace(),
    497913                                        gd.getLiteralSystemId());
     
    519935    }  // class ShadowCacheGrammarPool
    520936
     937
     938    private static final class ResultImpl implements
     939            CMDIValidatorWriteableResult {
     940        private final List<Message> messages = new LinkedList<Message>();
     941        private File file;
     942        private Severity highestSeverity;
     943
     944
     945        private ResultImpl() {
     946            reset();
     947        }
     948
     949
     950        @Override
     951        public File getFile() {
     952            return file;
     953        }
     954
     955
     956        @Override
     957        public Severity getHighestSeverity() {
     958            return highestSeverity;
     959        }
     960
     961
     962        @Override
     963        public boolean isHighestSeverity(Severity severity) {
     964            if (severity == null) {
     965                throw new NullPointerException("severity == null");
     966            }
     967            return this.highestSeverity.equals(severity);
     968        }
     969
     970
     971        @Override
     972        public List<Message> getMessages() {
     973            if (messages.isEmpty()) {
     974                return Collections.emptyList();
     975            } else {
     976                return Collections.unmodifiableList(messages);
     977            }
     978        }
     979
     980
     981        @Override
     982        public Message getFirstMessage() {
     983            return messages.isEmpty() ? null : messages.get(0);
     984        }
     985
     986
     987        @Override
     988        public Message getFirstMessage(Severity severity) {
     989            if (severity == null) {
     990                throw new NullPointerException("severity == null");
     991            }
     992
     993            if (!messages.isEmpty()) {
     994                for (Message msg : messages) {
     995                    if (severity.equals(msg.getSeverity())) {
     996                        return msg;
     997                    }
     998                }
     999            }
     1000            return null;
     1001        }
     1002
     1003
     1004        @Override
     1005        public int getMessageCount() {
     1006            return messages.size();
     1007        }
     1008
     1009
     1010        @Override
     1011        public int getMessageCount(Severity severity) {
     1012            if (severity == null) {
     1013                throw new NullPointerException("severity == null");
     1014            }
     1015
     1016            int count = 0;
     1017            if (!messages.isEmpty()) {
     1018                for (Message msg : messages) {
     1019                    if (severity.equals(msg.getSeverity())) {
     1020                        count++;
     1021                    }
     1022                }
     1023            }
     1024            return count;
     1025        }
     1026
     1027
     1028        @Override
     1029        public void reportInfo(int line, int col, String message) {
     1030            reportInfo(line, col, message, null);
     1031        }
     1032
     1033
     1034        @Override
     1035        public void reportInfo(int line, int col, String message,
     1036                Throwable cause) {
     1037            messages.add(new MessageImpl(Severity.INFO, line, col, message,
     1038                    cause));
     1039        }
     1040
     1041
     1042        @Override
     1043        public void reportWarning(int line, int col, String message) {
     1044            reportWarning(line, col, message, null);
     1045        }
     1046
     1047
     1048        @Override
     1049        public void reportWarning(int line, int col, String message,
     1050                Throwable cause) {
     1051            switch (highestSeverity) {
     1052            case WARNING:
     1053                /* FALL-THROUGH */
     1054            case ERROR:
     1055                break;
     1056            default:
     1057                highestSeverity = Severity.WARNING;
     1058            }
     1059            messages.add(new MessageImpl(Severity.WARNING, line, col, message,
     1060                    cause));
     1061        }
     1062
     1063
     1064        @Override
     1065        public void reportError(int line, int col, String message) {
     1066            reportError(line, col, message, null);
     1067        }
     1068
     1069
     1070        @Override
     1071        public void reportError(int line, int col, String message,
     1072                Throwable cause) {
     1073            switch (highestSeverity) {
     1074            case ERROR:
     1075                break;
     1076            default:
     1077                highestSeverity = Severity.ERROR;
     1078            }
     1079            messages.add(new MessageImpl(Severity.ERROR, line, col, message,
     1080                    cause));
     1081        }
     1082
     1083
     1084        private void setFile(File file) {
     1085            this.file = file;
     1086        }
     1087
     1088
     1089        private void reset() {
     1090            this.messages.clear();
     1091            this.file = null;
     1092            this.highestSeverity = Severity.INFO;
     1093        }
     1094    } // class ResultImpl
     1095
     1096
     1097    private static final class MessageImpl implements
     1098            CMDIValidatorResult.Message {
     1099        private final Severity severity;
     1100        private final int line;
     1101        private final int col;
     1102        private final String message;
     1103        private final Throwable cause;
     1104
     1105
     1106        private MessageImpl(Severity severity, int line, int col,
     1107                String message, Throwable cause) {
     1108            this.severity = severity;
     1109            this.line     = line;
     1110            this.col      = col;
     1111            this.message  = message;
     1112            this.cause    = cause;
     1113        }
     1114
     1115
     1116        @Override
     1117        public Severity getSeverity() {
     1118            return severity;
     1119        }
     1120
     1121
     1122        @Override
     1123        public int getLineNumber() {
     1124            return line;
     1125        }
     1126
     1127
     1128        @Override
     1129        public int getColumnNumber() {
     1130            return col;
     1131        }
     1132
     1133
     1134        @Override
     1135        public String getMessage() {
     1136            return message;
     1137        }
     1138
     1139
     1140        @Override
     1141        public Throwable getCause() {
     1142            return cause;
     1143        }
     1144    } // class MessageImpl
     1145
    5211146} // class CMDIValidator
  • CMDIValidator/trunk/cmdi-validator-core/src/main/java/eu/clarin/cmdi/validator/CMDIValidatorHandler.java

    r5369 r5382  
    22
    33
    4 public interface CMDIValidatorJobHandler {
     4public interface CMDIValidatorHandler {
    55
    66    public void onJobStarted()
     
    88
    99
    10     public void onJobFinished(boolean wasCanceled)
     10    public void onJobFinished(final CMDIValidator.Result result)
    1111            throws CMDIValidatorException;
    1212
    1313
    14     public void onValidationSuccess(CMDIValidatorResult result)
     14    public void onValidationSuccess(final CMDIValidatorResult result)
    1515            throws CMDIValidatorException;
    1616
    1717
    18     public void onValidationFailure(CMDIValidatorResult result)
     18    public void onValidationFailure(final CMDIValidatorResult result)
    1919            throws CMDIValidatorException;
    2020
  • CMDIValidator/trunk/cmdi-validator-core/src/main/java/eu/clarin/cmdi/validator/CMDIValidatorHandlerAdapter.java

    r5369 r5382  
    22
    33
    4 public class CMDIValidatorJobHandlerAdapter implements CMDIValidatorJobHandler {
     4public class CMDIValidatorHandlerAdapter implements CMDIValidatorHandler {
    55
    66    @Override
     
    1010
    1111    @Override
    12     public void onJobFinished(boolean wasCanceled)
     12    public void onJobFinished(final CMDIValidator.Result result)
    1313            throws CMDIValidatorException {
    1414    }
  • CMDIValidator/trunk/cmdi-validator-tool/pom.xml

    r5337 r5382  
    66        <groupId>eu.clarin.cmdi</groupId>
    77        <artifactId>cmdi-validator</artifactId>
    8         <version>0.0.4-SNAPSHOT</version>
     8        <version>0.0.5-SNAPSHOT</version>
    99    </parent>
    1010    <artifactId>cmdi-validator-tool</artifactId>
  • CMDIValidator/trunk/cmdi-validator-tool/src/main/java/eu/clarin/cmdi/validator/tool/CMDIValidatorTool.java

    r5371 r5382  
    77import java.util.Locale;
    88import java.util.concurrent.TimeUnit;
    9 
    109import net.java.truevfs.access.TFile;
    1110import net.java.truevfs.access.TVFS;
     
    2322import org.slf4j.LoggerFactory;
    2423
     24import eu.clarin.cmdi.validator.ThreadedCMDIValidatorProcessor;
    2525import eu.clarin.cmdi.validator.CMDIValidator;
    26 import eu.clarin.cmdi.validator.CMDIValidatorEngine;
     26import eu.clarin.cmdi.validator.CMDIValidatorConfig;
    2727import eu.clarin.cmdi.validator.CMDIValidatorException;
    28 import eu.clarin.cmdi.validator.CMDIValidatorFactory;
    29 import eu.clarin.cmdi.validator.CMDIValidatorFactoryConfig;
    3028import eu.clarin.cmdi.validator.CMDIValidatorInitException;
    31 import eu.clarin.cmdi.validator.CMDIValidatorJob;
    32 import eu.clarin.cmdi.validator.CMDIValidatorJobHandlerAdapter;
     29import eu.clarin.cmdi.validator.CMDIValidatorHandlerAdapter;
    3330import eu.clarin.cmdi.validator.CMDIValidatorResult;
    3431import eu.clarin.cmdi.validator.CMDIValidatorResult.Message;
     
    169166            TFile archive = null;
    170167            try {
    171                 /*
    172                  * initialize CMDIValidatorFactory
    173                  */
    174168                if (schemaCacheDir != null) {
    175169                    logger.info("using schema cache directory: {}", schemaCacheDir);
     
    178172                    logger.info("using Schematron schema from file: {}", schematronFile);
    179173                }
    180 
    181                 final CMDIValidatorFactoryConfig config =
    182                         new CMDIValidatorFactoryConfig.Builder()
    183                         .schemaCacheDirectory(schemaCacheDir)
    184                         .schematronSchemaFile(schematronFile)
    185                         .schematronDisabled(disableSchematron)
    186                         .build();
    187                 final CMDIValidatorFactory factory =
    188                         CMDIValidatorFactory.newInstance(config);
    189 
    190                 if (checkPids) {
    191                     logger.info("performing PID checking");
    192                     factory.registerExtension(
    193                             new CheckHandlesExtension(threadCount, true));
    194                 }
    195 
    196174
    197175                /*
     
    199177                 */
    200178                archive = new TFile(remaining[0]);
    201 
    202179                if (archive.exists()) {
    203180                    if (archive.isArchive()) {
     
    217194                    }
    218195
    219                     final CMDIValidatorEngine engine =
    220                             new CMDIValidatorEngine(factory, threadCount);
    221                     final JobHandler handler = new JobHandler(verbose);
     196
     197                    final ValidationHandler handler = new ValidationHandler(verbose);
     198
     199                    final CMDIValidatorConfig.Builder builder =
     200                            new CMDIValidatorConfig.Builder(archive, handler);
     201                    if (schemaCacheDir != null) {
     202                        builder.schemaCacheDirectory(schemaCacheDir);
     203                    }
     204                    if (schematronFile != null) {
     205                        builder.schematronSchemaFile(schematronFile);
     206                    }
     207                    if (disableSchematron) {
     208                        builder.disableSchematron();
     209                    }
     210                    if (checkPids) {
     211                        logger.info("performing PID checking");
     212                        builder.extension(
     213                                new CheckHandlesExtension(threadCount, true));
     214                    }
     215
     216                    final ThreadedCMDIValidatorProcessor processor =
     217                            new ThreadedCMDIValidatorProcessor(threadCount);
     218                    processor.start();
    222219                    try {
    223                         final CMDIValidatorJob job =
    224                                 new CMDIValidatorJob(archive, handler);
    225 
    226                         engine.start();
    227                         logger.debug("submitting batch validation job ...");
    228                         engine.submit(job);
     220                        final CMDIValidator validator =
     221                                new CMDIValidator(builder.build());
     222                        processor.process(validator);
    229223
    230224                        /*
     
    272266                        } // for (;;)
    273267                    } finally {
    274                         engine.shutdown();
     268                        processor.shutdown();
    275269                    }
    276270
     
    412406
    413407
    414     private static class JobHandler extends CMDIValidatorJobHandlerAdapter {
     408    private static class ValidationHandler extends CMDIValidatorHandlerAdapter {
    415409        private final boolean verbose;
    416410        private long started     = System.currentTimeMillis();
     
    423417
    424418
    425         private JobHandler(boolean verbose) {
     419        private ValidationHandler(boolean verbose) {
    426420            this.verbose = verbose;
    427421        }
     
    483477
    484478        @Override
    485         public void onJobFinished(boolean wasCancled) {
     479        public void onJobStarted() throws CMDIValidatorException {
     480            logger.debug("validation process started");
     481        }
     482
     483
     484        @Override
     485        public void onJobFinished(final CMDIValidator.Result result)
     486                throws CMDIValidatorException {
    486487            finished = System.currentTimeMillis();
     488            switch (result) {
     489            case OK:
     490                logger.debug("validation process finished successfully");
     491                break;
     492            case ABORTED:
     493                logger.info("processing was aborted");
     494                break;
     495            case ERROR:
     496                logger.debug("validation process yielded an error");
     497                break;
     498            default:
     499                logger.debug("unknown result: " + result);
     500            } // switch
     501
    487502            synchronized (waiter) {
    488503                isCompleted = true;
    489504                waiter.notifyAll();
    490505            } // synchronized (waiter)
    491             if (wasCancled) {
    492                 logger.info("processing was canceled ...");
    493             }
    494506        }
    495507
    496508
    497509        @Override
    498         public void onValidationSuccess(CMDIValidatorResult result) {
     510        public void onValidationSuccess(final CMDIValidatorResult result)
     511                throws CMDIValidatorException {
    499512            final File file = result.getFile();
    500513            synchronized (this) {
     
    534547                }
    535548            } else {
    536                 logger.debug("file '{}' is valid", file, result.getFile());
     549                logger.debug("file '{}' is valid", file);
    537550            }
    538551        }
     
    540553
    541554        @Override
    542         public void onValidationFailure(CMDIValidatorResult result) {
     555        public void onValidationFailure(final CMDIValidatorResult result) {
    543556            final File file = result.getFile();
    544557            synchronized (this) {
  • CMDIValidator/trunk/pom.xml

    r5336 r5382  
    55    <groupId>eu.clarin.cmdi</groupId>
    66    <artifactId>cmdi-validator</artifactId>
    7     <version>0.0.4-SNAPSHOT</version>
     7    <version>0.0.5-SNAPSHOT</version>
    88    <packaging>pom</packaging>
    99
Note: See TracChangeset for help on using the changeset viewer.