KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joseki > server > Configuration


1 /*
2  * (c) Copyright 2003, 2004 Hewlett-Packard Development Company, LP
3  * [See end of file]
4  */

5
6 package org.joseki.server;
7
8 import java.util.* ;
9 import org.apache.commons.logging.* ;
10
11 import org.joseki.* ;
12 import org.joseki.util.* ;
13 import org.joseki.server.source.* ;
14 import org.joseki.vocabulary.*;
15 import org.joseki.server.module.*;
16
17 import com.hp.hpl.jena.rdf.model.* ;
18
19 import com.hp.hpl.jena.ontology.* ;
20 import com.hp.hpl.jena.shared.* ;
21 import com.hp.hpl.jena.vocabulary.* ;
22 //import com.hp.hpl.jena.reasoner.* ;
23
//import com.hp.hpl.jena.reasoner.rulesys.*;
24

25
26 /**
27  * Parse and process a Joseki configuration file
28  *
29  * @author Andy Seaborne
30  * @version $Id: Configuration.java,v 1.26 2004/04/30 14:13:13 andy_seaborne Exp $
31  */

32
33
34 public class Configuration
35 {
36     private static Log log = LogFactory.getLog(Configuration.class.getName());
37     
38     // List of old namespace URIs
39
public static final String JavaDoc oldNS[] = {"http://joseki.org/2002/06/configuration#"} ;
40     
41     Model configurationModel = ModelFactory.createDefaultModel() ;
42     ClassLoader JavaDoc classLoader = null ;
43     Loader moduleLoader = new Loader() ;
44     FileManager fileManager = FileManager.getInstance() ;
45     
46     /** Create an empty ModelSet */
47     public Configuration()
48     {
49         classLoader = chooseClassLoader() ;
50     }
51  
52     public Model getConfigurationModel() { return configurationModel ; }
53     
54     /** Load a file
55      */

56     public void load(ModelSet modelSet, String JavaDoc configFile)
57     {
58         log.info("Load configuration: "+configFile) ;
59         
60         Set filesRead = new HashSet() ;
61         
62         readConfFile(configurationModel, configFile, filesRead) ;
63         
64         processConfigurationModel(modelSet) ;
65     }
66
67     private void readConfFile(Model confModel, String JavaDoc fileName, Set filesDone)
68     {
69         try
70         {
71             // Read into this empty model to find all the "alsoIncludes"
72
// Not necessary (could do in the main model) but convenient
73
// as it bounds any read errors.
74

75             Model m = ModelFactory.createDefaultModel() ;
76             m = fileManager.readModel(m, fileName) ;
77             if ( m == null )
78             {
79                 log.warn("No configuration model: "+fileName) ;
80                 throw new ConfigurationErrorException("Configuration file not found: "+fileName) ;
81                 //return false ;
82
}
83             
84             log.info("Read: "+fileName) ;
85             filesDone.add(fileName) ;
86         
87             Set filesToDo = new HashSet() ;
88             
89             ResIterator rIter = m.listSubjectsWithProperty(RDF.type, JosekiVocab.JosekiServer) ;
90             for ( ; rIter.hasNext() ; )
91             {
92                 Resource r = rIter.nextResource() ;
93                 StmtIterator sIter = r.listProperties(JosekiVocab.alsoInclude) ;
94                 for ( ; sIter.hasNext() ; )
95                 {
96                     Resource fileName2 = sIter.nextStatement().getResource() ;
97                     if ( fileName2.isAnon() )
98                         continue ;
99                     String JavaDoc fullname = fileName2.getURI() ;
100                     if ( ! filesDone.contains(fullname) )
101                         filesToDo.add(fullname) ;
102                 }
103                 sIter.close() ;
104             }
105             rIter.close() ;
106             confModel.add(m) ;
107             for ( Iterator iter = filesToDo.iterator() ; iter.hasNext() ; )
108             {
109                 readConfFile(confModel, (String JavaDoc)iter.next(), filesDone) ;
110             }
111             
112         } catch (RDFException rdfEx)
113         {
114             log.warn(fileName+": RDF Exception: "+rdfEx.getMessage()) ;
115             throw new ConfigurationErrorException("RDF Exception: "+rdfEx.getMessage(), rdfEx) ;
116             //return false ;
117
}
118     }
119
120     // ------------------------------------------------
121
// Main function to process the configuration model
122

123     private void processConfigurationModel(ModelSet modelSet)
124     {
125         // -------- Checks
126

127         NsIterator nsIter = configurationModel.listNameSpaces() ;
128         for ( ; nsIter.hasNext() ;)
129         {
130             String JavaDoc ns = nsIter.nextNs() ;
131             for ( int i = 0 ; i < oldNS.length ; i++)
132             {
133                 if ( oldNS[i].equals(ns) )
134                 {
135                     log.error("Found out of date configuration information found") ;
136                     log.error(" Configuration URI for this codebase is "+JosekiVocab.NS) ;
137                     throw new ConfigurationErrorException("Out of date configuration information") ;
138                 }
139             }
140         }
141         // -------- Do server information
142
processServerConfiguration() ;
143
144         processSources(modelSet) ;
145     }
146
147
148     private void processServerConfiguration()
149     {
150         try
151         {
152             log.trace("Start server configuration") ;
153             // Find the server: merge multiple nodes.
154
ResIterator rIter = configurationModel.listSubjectsWithProperty(RDF.type, JosekiVocab.JosekiServer) ;
155             for ( ; rIter.hasNext() ; )
156             {
157                 Resource r = rIter.nextResource() ;
158                 
159                 if ( r.hasProperty(JosekiVocab.serverDebug) )
160                 {
161                     Joseki.serverDebug =
162                         r.getRequiredProperty(JosekiVocab.serverDebug).getString().equals("true") ;
163                 }
164                 
165                 if ( r.hasProperty(JosekiVocab.useContentType) )
166                 {
167                     String JavaDoc contentType = r.getRequiredProperty(JosekiVocab.useContentType).getString() ;
168
169                     if ( contentType.equals(Joseki.contentTypeN3) ||
170                          contentType.equals(Joseki.contentTypeRDFXML) ||
171                          contentType.equals(Joseki.contentTypeNTriples) )
172                     {
173                         log.debug("Content type: "+contentType) ;
174                         Joseki.serverContentType = contentType ;
175                     }
176                     else
177                     {
178                         log.warn("Unknown content-type: "+contentType) ;
179                     }
180                 }
181
182                 Property oldFeature = r.getModel().createProperty(JosekiVocab.NS, "loadJavaClass") ;
183                 if ( r.hasProperty(oldFeature) )
184                     log.warn("Old style 'joseki:javaLoadClass' found : use joseki:dbDriver on attached model") ;
185             }
186             rIter.close();
187             
188         } catch (RDFException rdfEx)
189         {
190             log.warn("Error in configuration file (server section)", rdfEx) ;
191             throw new ConfigurationErrorException("Error in configuration file (server section)", rdfEx) ;
192         }
193         
194         if ( Joseki.serverDebug )
195             log.info("Server debug on") ;
196
197         log.trace("Finish server configuration") ;
198     }
199
200
201     private void processSources(ModelSet modelSet)
202     {
203         String JavaDoc loggingIndicator = "<<unset>>" ;
204         try
205         {
206             // Find all models. Find all things with an ModelSource property.
207
ResIterator rIter =
208                 configurationModel.listSubjectsWithProperty(JosekiVocab.attachedModel);
209             if ( ! rIter.hasNext() )
210                 log.warn("No models to attach") ;
211
212             for (; rIter.hasNext();)
213             {
214                 Resource modelSource = rIter.nextResource();
215                 if ( modelSource.isAnon() )
216                 {
217                     log.warn("Attached model is a bNode - need a URI") ;
218                     continue ;
219                 }
220                 String JavaDoc serverURI = ModelSet.resource2serverURI(modelSource) ;
221
222                 loggingIndicator = serverURI ;
223                 ModelSource srcModel = null ;
224                 try {
225                     srcModel = processModel(modelSource, serverURI) ;
226                 } catch (JenaException ex)
227                 {
228                     log.warn("Error in configuration file. Model:"+loggingIndicator) ;
229                     ex.printStackTrace(System.out) ;
230                     continue ;
231                 }
232                 if ( srcModel == null )
233                     continue ;
234                 modelSet.addModel(serverURI, srcModel) ;
235             }
236             rIter.close() ;
237         }
238         catch (RDFException rdfEx)
239         {
240             log.warn("Error in configuration file (model section): "+loggingIndicator) ;
241             throw new ConfigurationErrorException("Error in configuration file (model section): "+loggingIndicator) ;
242         }
243     }
244     
245     
246     private ModelSource processModel(Resource modelSource, String JavaDoc serverURI)
247     {
248         if ( modelSource.isAnon() )
249         {
250             log.warn("Anonymous node for external resource!") ;
251             return null ;
252         }
253         
254         Statement sourceStmt = modelSource.getProperty(JosekiVocab.attachedModel) ;
255         if ( sourceStmt == null )
256         {
257             log.warn("Model: "+serverURI + " : No internal Jena model specified") ;
258             return null ;
259         }
260         
261         String JavaDoc internalURI = null ;
262         try {
263             internalURI = sourceStmt.getResource().getURI() ;
264             log.info("Model: "+serverURI + " ==> " + internalURI) ;
265         } catch (RDFException ex)
266         {
267             log.warn("No internal resource URI for "+serverURI) ;
268             return null ;
269         }
270         
271         ModelSource src = buildModelSource(modelSource, internalURI, serverURI) ;
272
273         if ( src == null )
274         {
275             log.warn("Failed to attach "+internalURI) ;
276             return null ;
277         }
278         
279         log.trace("Base model built") ;
280         
281         if ( modelSource.hasProperty(JosekiVocab.modelSpec) )
282         {
283             log.warn("Description by ModelSpec: Not implemented (yet)") ;
284             return null ;
285         }
286         else
287         {
288             if ( modelSource.hasProperty(JosekiVocab.vocabulary) ||
289                  modelSource.hasProperty(JosekiVocab.ontology) )
290             {
291                 src = buildOntModelSource(modelSource, serverURI, src) ;
292                 if ( src == null )
293                     // Error in OWL/RDFS model set up.
294
return null ;
295             }
296         }
297         
298         if ( modelSource.hasProperty(JosekiVocab.isImmutable) )
299         {
300             String JavaDoc tmp = modelSource.getProperty(JosekiVocab.isImmutable).getString() ;
301             if ( tmp.equalsIgnoreCase("true") )
302             {
303                 log.debug(" Immutable model") ;
304                 src.setIsImmutable(true) ;
305             }
306         }
307         
308         // Add functionalities
309
buildQueryProcs(modelSource, src) ;
310         buildOtherProcs(modelSource, src) ;
311         
312         assignNamespaces(modelSource, src) ;
313         return src ;
314     }
315
316     
317     
318     // Process any RDFS or OWL ontologies associated with the model.
319
private ModelSource buildOntModelSource(Resource modelSource, String JavaDoc serverURI, ModelSource src)
320     {
321         final boolean hasRDFS = modelSource.hasProperty(JosekiVocab.vocabulary) ;
322         final boolean hasOWL = modelSource.hasProperty(JosekiVocab.ontology) ;
323         
324         if ( ! hasRDFS && ! hasOWL )
325             return src ;
326
327         if ( hasRDFS && hasOWL )
328         {
329             log.warn("Can't have both an OWL ontology and an RDFS vocabulary") ;
330             return null ;
331         }
332         
333         if ( ! (src instanceof ModelSourceJena) )
334         {
335             log.warn("Jena inference subsystem only works with Jena models") ;
336             return null ;
337         }
338         
339         Model aBox = ((ModelSourceJena)src).getModel() ;
340         Model newModel = null ;
341
342         if ( hasRDFS )
343         {
344             Resource vocabulary = modelSource
345                                     .getProperty(JosekiVocab.vocabulary)
346                                     .getResource() ;
347             log.info(" Applying RDFS: "+vocabulary) ;
348             
349             Model vocabularyModel = fileManager.loadModel(vocabulary.getURI()) ;
350             newModel = ModelFactory.createRDFSModel(vocabularyModel, aBox) ;
351         }
352
353         if ( hasOWL )
354         {
355             Resource ontology = modelSource.getProperty(JosekiVocab.vocabulary)
356                                            .getResource() ;
357             Model tBox = fileManager.loadModel(ontology.getURI()) ;
358             log.info(" Applying OWL: "+ontology) ;
359             
360             Model ontDocMgr = null ;
361             if ( modelSource.hasProperty(JosekiVocab.ontDocumentManager))
362             {
363                 Resource r = modelSource.getProperty(JosekiVocab.ontDocumentManager).getResource() ;
364                 String JavaDoc ontDocMgrURI = r.getURI() ;
365                 log.info(" Ontology document manager: "+ontDocMgrURI) ;
366                 ontDocMgr = fileManager.loadModel(ontDocMgrURI) ;
367             }
368
369             OntModelSpec s = new OntModelSpec( OntModelSpec.OWL_LITE_MEM_RULES_INF );
370             if ( ontDocMgr != null )
371                 s.setDocumentManager( new OntDocumentManager(ontDocMgr)) ;
372             s.getReasoner().bindSchema(tBox) ;
373             newModel = ModelFactory.createOntologyModel( s, aBox );
374         }
375         
376         newModel.setNsPrefixes(aBox) ;
377         // Create a permanent ModelSource. No (system) resource control.
378
SourceController sCtl = new SourceControllerPermanent(newModel) ;
379         src = sCtl.createSourceModel(null, serverURI) ;
380         return src ;
381     }
382
383     private ModelSource buildModelSource(Resource sourceDesc, String JavaDoc modelURI, String JavaDoc serverURI)
384     {
385         Resource module = null ;
386         
387         if ( sourceDesc.hasProperty(JosekiVocab.sourceController) )
388         {
389             module = sourceDesc.getProperty(JosekiVocab.sourceController).getResource() ;
390             log.debug(" Custom source controller: "+PrintUtils.fmt(module)) ;
391         }
392         else
393         {
394             // Not given : try for a built-in
395

396             if ( modelURI.toLowerCase().startsWith("file:") )
397             {
398                 log.trace(" File source") ;
399                 module = sourceDesc.getModel().getResource(JosekiVocab.sourceControllerFile) ;
400             }
401                 
402             if ( modelURI.toLowerCase().startsWith("jdbc:") )
403             {
404                 log.trace(" JDBC source") ;
405                 module = sourceDesc.getModel().getResource(JosekiVocab.sourceControllerRDB) ;
406             }
407         }
408                 
409         if ( module == null )
410         {
411             log.warn("Can't find module for source controller for "+serverURI+" : not named, not a file and not a database") ;
412             return null ;
413         }
414
415         SourceController srcCtl = (SourceController)moduleLoader.loadAndInstantiate(module, SourceController.class) ;
416
417         if ( srcCtl == null )
418         {
419             log.warn("Can't load find source controller for "+serverURI) ;
420             return null ;
421         }
422         
423         ModelSource a = srcCtl.createSourceModel(sourceDesc, serverURI) ;
424         log.trace("Built model source controller") ;
425         return a ;
426     }
427
428     // Do query processors
429
private void buildQueryProcs(Resource modelSource, ModelSource src)
430     {
431         StmtIterator queryBindings = modelSource.listProperties(JosekiVocab.hasQueryOperation);
432         for (; queryBindings.hasNext();)
433         {
434             Resource binding = queryBindings.nextStatement().getResource();
435             QueryProcessor qProc = (QueryProcessor)moduleLoader.loadAndInstantiate(binding, QueryProcessor.class) ;
436             
437             if ( qProc == null )
438                 continue ;
439                 
440             // Several names for the same query processor
441
// Can be a URI or a string.
442
StmtIterator langNameIter = binding.listProperties(JosekiVocab.queryOperationName);
443             for (; langNameIter.hasNext();)
444             {
445                 Statement s = langNameIter.nextStatement();
446                 String JavaDoc langName = null ;
447                 if ( s.getObject() instanceof Literal )
448                     langName = s.getString();
449                 else
450                 {
451                     if ( s.getResource().isAnon() )
452                     {
453                         log.warn("Query langauge name must be a literal or a URI") ;
454                         continue ;
455                     }
456                     langName = s.getResource().getURI() ;
457                 }
458                 log.info(" Query Language: " + langName);
459                 if ( src.getProcessorRegistry().hasQueryProcessor(langName) )
460                     log.warn(" Query language '"+langName+"' already assigned") ;
461                 src.getProcessorRegistry().registerQueryProcessor(langName, qProc);
462             }
463             langNameIter.close() ;
464         }
465     }
466
467     // Do other operation processors
468
private void buildOtherProcs(Resource modelSource, ModelSource src)
469     {
470         StmtIterator operationBindings = modelSource.listProperties(JosekiVocab.hasOperation);
471         for (; operationBindings.hasNext();)
472         {
473             Resource binding = operationBindings.nextStatement().getResource();
474             Processor proc = (Processor)moduleLoader.loadAndInstantiate(binding, Processor.class) ;
475             
476             if (proc == null)
477                 continue;
478                 
479             StmtIterator opNameIter = binding.listProperties(JosekiVocab.operationName) ;
480             for ( ; opNameIter.hasNext() ;)
481             {
482                 Statement s = opNameIter.nextStatement();
483                 if ( s.getPredicate().equals(JosekiVocab.queryOperationName))
484                     continue ;
485                 String JavaDoc opName = null ;
486                 if ( s.getObject() instanceof Literal )
487                     opName = s.getString();
488                 else
489                 {
490                     if ( s.getResource().isAnon() )
491                     {
492                         log.warn("Operation name must be a literal or a URI") ;
493                         continue ;
494                     }
495                     opName = s.getResource().getURI() ;
496                 }
497                 log.info(" Operation: " + opName);
498                 if ( src.getProcessorRegistry().hasProcessor(opName) )
499                     log.warn(" Operation '"+opName+"' already assigned") ;
500
501                 src.getProcessorRegistry().registerProcessor(opName, proc);
502             }
503             opNameIter.close() ;
504         }
505     }
506
507       
508     private void assignNamespaces(Resource modelSource, ModelSource src)
509     {
510         // Find the namespace prefixes.
511
StmtIterator prefixIter = modelSource.listProperties(JosekiVocab.namespacePrefix);
512         for (; prefixIter.hasNext();)
513         {
514             Statement s = prefixIter.nextStatement();
515             if (!(s.getObject() instanceof Resource))
516             {
517                 log.warn("Error in configuration file: " + modelSource + " has non-resource namespace prefix");
518                 break;
519             }
520             try
521             {
522                 String JavaDoc prefix = s.getResource().getRequiredProperty(JosekiVocab.prefix).getString();
523                 String JavaDoc nsURI = s.getResource().getRequiredProperty(JosekiVocab.nsURI).getResource().getURI();
524                 log.debug(" Namespace: " + prefix + " <=> " + nsURI);
525                 src.setPrefix(prefix, nsURI);
526             }
527             catch (RDFException rdfEx)
528             {
529                 log.warn("Error in configuration file: " + modelSource + " has ill-formed prefix declaration");
530                 break;
531             }
532         }
533     }
534
535     private ClassLoader JavaDoc chooseClassLoader()
536     {
537         ClassLoader JavaDoc classLoader = null ;
538     
539         if ( classLoader == null )
540         {
541             // Find our classloader - one that uses the /WEB-INF/lib and classes directory.
542
classLoader = Thread.currentThread().getContextClassLoader();
543             if ( classLoader != null )
544                 log.trace("Using thread classloader") ;
545         }
546         
547         if (classLoader == null)
548         {
549             classLoader = this.getClass().getClassLoader();
550             if ( classLoader != null )
551                 log.trace("Using 'this' classloader") ;
552         }
553         
554         if ( classLoader == null )
555         {
556             classLoader = ClassLoader.getSystemClassLoader() ;
557             if ( classLoader != null )
558                 log.trace("Using system classloader") ;
559         }
560         
561         if ( classLoader == null )
562             log.warn("Failed to find a classloader") ;
563         return classLoader ;
564     }
565     
566 // static public void main(String argv[])
567
// {
568
// try {
569
// ModelSet mm = new ModelSet() ;
570
// mm.load(RDFServer.defaultConfigFile) ;
571
// } catch (Exception ex)
572
// {
573
// logger.error("Unhandled: "+ex);
574
// }
575
// }
576
}
577
578 /*
579  * (c) Copyright 2003, 2004 Hewlett-Packard Development Company, LP
580  * All rights reserved.
581  *
582  * Redistribution and use in source and binary forms, with or without
583  * modification, are permitted provided that the following conditions
584  * are met:
585  * 1. Redistributions of source code must retain the above copyright
586  * notice, this list of conditions and the following disclaimer.
587  * 2. Redistributions in binary form must reproduce the above copyright
588  * notice, this list of conditions and the following disclaimer in the
589  * documentation and/or other materials provided with the distribution.
590  * 3. The name of the author may not be used to endorse or promote products
591  * derived from this software without specific prior written permission.
592  *
593  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
594  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
595  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
596  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
597  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
598  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
599  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
600  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
601  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
602  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
603  */

604
Popular Tags