1 16 package org.outerj.daisy.publisher.serverimpl.resolving; 17 18 import org.outerj.daisy.repository.Document; 19 import org.outerj.daisy.repository.Repository; 20 import org.outerj.daisy.repository.Version; 21 import org.outerj.daisy.repository.RepositoryException; 22 import org.outerj.daisy.publisher.PublisherException; 23 import org.outerj.daisy.publisher.serverimpl.CommonPublisher; 24 import org.outerj.daisy.publisher.serverimpl.requestmodel.PublisherRequest; 25 import org.outerj.daisy.xmlutil.LocalSAXParserFactory; 26 import org.apache.avalon.framework.logger.Logger; 27 import org.apache.xmlbeans.XmlOptions; 28 import org.outerx.daisy.x10Publisher.PublisherRequestDocument; 29 import org.xml.sax.SAXException ; 30 31 import java.util.Map ; 32 import java.io.*; 33 34 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 35 36 39 public class PublisherRequestResolver { 40 private File pubRequestsRoot; 41 private Repository repository; 42 private CommonPublisher commonPublisher; 43 private Logger logger; 44 private Map cache = new ConcurrentReaderHashMap(); 45 private final String resolveDefinitionMutex = "ResolveDefinitionMutex"; 46 private final String publisherRequestMutex = "PublisherRequestMutex"; 47 private ResolveDefinition defaultResolveDefinition; 48 private Map defaultPubReqs = new ConcurrentReaderHashMap(); 49 50 public PublisherRequestResolver(File pubRequestsRoot, Repository repository, CommonPublisher commonPublisher, Logger logger) { 51 this.pubRequestsRoot = pubRequestsRoot; 52 this.repository = repository; 53 this.commonPublisher = commonPublisher; 54 this.logger = logger; 55 } 56 57 60 public PublisherRequest lookupPublisherRequest(String pubReqSetName, Document document, Version version) 61 throws PublisherException, RepositoryException, SAXException { 62 ResolveDefinition resolveDefinition = getResolveDefinition(pubReqSetName); 63 String pubReqName = resolveDefinition.resolve(document, version); 64 if (pubReqName == null) 65 throw new PublisherException("No publisher request found in set \"" + pubReqSetName + "\" for document " + document.getVariantKey()); 66 67 if (pubReqSetName.equals("default")) { 68 return getDefaultPubReq(pubReqName); 69 } else { 70 File pubReqFile = new File(new File(pubRequestsRoot, pubReqSetName), pubReqName); 71 return getPublisherRequest(pubReqFile); 72 } 73 } 74 75 private ResolveDefinition getResolveDefinition(String pubReqSetName) throws PublisherException { 76 if (pubReqSetName.equals("default")) 77 return getDefaultResolveDefinition(); 78 79 ResolveDefinition resolveDefinition = (ResolveDefinition)getFromCache(pubReqSetName); 80 if (resolveDefinition == null) { 81 synchronized(resolveDefinitionMutex) { 82 resolveDefinition = (ResolveDefinition)getFromCache(pubReqSetName); 83 if (resolveDefinition == null) { 84 ResolveDefinitionBuilder builder = new ResolveDefinitionBuilder(repository, logger); 85 File mappingFile = new File(new File(pubRequestsRoot, pubReqSetName), "mapping.xml"); 86 long timestamp = mappingFile.lastModified(); 87 resolveDefinition = builder.build(mappingFile, pubReqSetName); 88 putInCache(pubReqSetName, timestamp, mappingFile, resolveDefinition); 89 } 90 } 91 } 92 return resolveDefinition; 93 } 94 95 private PublisherRequest getPublisherRequest(File pubReqFile) throws PublisherException, RepositoryException, SAXException { 96 String cacheKey = pubReqFile.getAbsolutePath(); 97 PublisherRequest publisherRequest = (PublisherRequest)getFromCache(cacheKey); 98 if (publisherRequest == null) { 99 synchronized(publisherRequestMutex) { 100 publisherRequest = (PublisherRequest)getFromCache(cacheKey); 101 if (publisherRequest == null) { 102 long timestamp = pubReqFile.lastModified(); 103 PublisherRequestDocument publisherRequestDocument; 104 try { 105 XmlOptions xmlOptions = new XmlOptions().setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader()); 106 publisherRequestDocument = PublisherRequestDocument.Factory.parse(pubReqFile, xmlOptions); 107 } catch (Exception e) { 108 throw new PublisherException("Error parsing publisher request from " + pubReqFile.getAbsolutePath(), e); 109 } 110 111 publisherRequest = commonPublisher.buildPublisherRequest(publisherRequestDocument); 112 putInCache(cacheKey, timestamp, pubReqFile, publisherRequest); 113 } 114 } 115 } 116 return publisherRequest; 117 } 118 119 private synchronized Object getFromCache(String cacheKey) { 120 CacheEntry cacheEntry = (CacheEntry)cache.get(cacheKey); 121 if (cacheEntry == null) { 122 return null; 123 } else if (cacheEntry.timestamp != cacheEntry.file.lastModified()) { 124 cache.remove(cacheKey); 125 return null; 126 } else { 127 return cacheEntry.object; 128 } 129 } 130 131 private synchronized void putInCache(String cacheKey, long timestamp, File file, Object object) { 132 CacheEntry cacheEntry = new CacheEntry(); 133 cacheEntry.timestamp = timestamp; 134 cacheEntry.file = file; 135 cacheEntry.object = object; 136 cache.put(cacheKey, cacheEntry); 137 } 138 139 private static class CacheEntry { 140 long timestamp; 141 File file; 142 Object object; 143 } 144 145 private ResolveDefinition getDefaultResolveDefinition() throws PublisherException { 146 if (this.defaultResolveDefinition != null) 147 return this.defaultResolveDefinition; 148 149 synchronized(this) { 150 if (this.defaultResolveDefinition != null) 151 return this.defaultResolveDefinition; 152 153 InputStream is = null; 154 try { 155 is = this.getClass().getClassLoader().getResourceAsStream("org/outerj/daisy/publisher/serverimpl/resolving/default/mapping.xml"); 156 ResolveDefinitionBuilder builder = new ResolveDefinitionBuilder(repository, logger); 157 this.defaultResolveDefinition = builder.build(is, "default"); 158 return this.defaultResolveDefinition; 159 } finally { 160 if (is != null) 161 try { is.close(); } catch (Exception e) { logger.error("Error closing InputStream in finally.", e); } 162 } 163 } 164 } 165 166 private PublisherRequest getDefaultPubReq(String name) throws PublisherException, RepositoryException, SAXException { 167 PublisherRequest publisherRequest = (PublisherRequest)defaultPubReqs.get(name); 168 if (publisherRequest != null) 169 return publisherRequest; 170 171 synchronized (this) { 172 publisherRequest = (PublisherRequest)defaultPubReqs.get(name); 173 if (publisherRequest != null) 174 return publisherRequest; 175 176 InputStream is = null; 177 try { 178 String path = "org/outerj/daisy/publisher/serverimpl/resolving/default/" + name; 179 is = this.getClass().getClassLoader().getResourceAsStream(path); 180 181 PublisherRequestDocument publisherRequestDocument; 182 try { 183 XmlOptions xmlOptions = new XmlOptions().setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader()); 184 publisherRequestDocument = PublisherRequestDocument.Factory.parse(is, xmlOptions); 185 } catch (Exception e) { 186 throw new PublisherException("Error parsing publisher request from resource " + path, e); 187 } 188 189 publisherRequest = commonPublisher.buildPublisherRequest(publisherRequestDocument); 190 defaultPubReqs.put(name, publisherRequest); 191 return publisherRequest; 192 } finally { 193 if (is != null) 194 try { is.close(); } catch (Exception e) { logger.error("Error closing InputStream in finally.", e); } 195 } 196 } 197 } 198 199 } 200 | Popular Tags |