001: /*
002: * Created on Nov 25, 2005
003: */
004: package uk.org.ponder.rsf.view.support;
005:
006: import java.io.InputStream;
007: import java.util.ArrayList;
008: import java.util.HashMap;
009: import java.util.List;
010: import java.util.Map;
011:
012: import org.springframework.context.ApplicationContext;
013: import org.springframework.context.ApplicationContextAware;
014: import org.springframework.core.io.Resource;
015: import org.springframework.core.io.ResourceLoader;
016:
017: import uk.org.ponder.rsf.expander.TemplateExpander;
018: import uk.org.ponder.rsf.view.ViewResolver;
019: import uk.org.ponder.rsf.view.ViewRoot;
020: import uk.org.ponder.rsf.viewstate.ViewParamsReceiver;
021: import uk.org.ponder.saxalizer.XMLProvider;
022: import uk.org.ponder.springutil.CachingInputStreamSource;
023: import uk.org.ponder.stringutil.FilenameUtil;
024: import uk.org.ponder.stringutil.StringList;
025: import uk.org.ponder.util.Logger;
026: import uk.org.ponder.util.UniversalRuntimeException;
027:
028: /**
029: * A view resolver which will return a component producer specified in a static
030: * XML file. Will attempt to look up the supplied viewID, after prefixing and
031: * postfixing, as a Spring resource. This is an application scope bean.
032: *
033: * @author Antranig Basman (antranig@caret.cam.ac.uk)
034: *
035: */
036:
037: public class XMLViewResolver implements ViewResolver,
038: ApplicationContextAware {
039: public static final int NO_CACHE = -1;
040: public static final String DEFAULT_EXTENSION = ".xml";
041: public static final String BASEPATH_DEFAULT = new String("");
042: private StringList viewnames;
043: private String basepath = BASEPATH_DEFAULT;
044: private ResourceLoader resourceloader;
045: private Map views = new HashMap();
046: private String extension = DEFAULT_EXTENSION;
047: private List defaultviews = null;
048: private TemplateExpander templateexpander;
049: private XMLProvider xmlprovider;
050: private int cachesecs = NO_CACHE;
051: private ViewParamsReceiver vpreceiver;
052: private CachingInputStreamSource cachingiss;
053:
054: /**
055: * Sets the default extension (including period) that will be suffixed to a
056: * viewId in order to generate the resource path which will be loaded.
057: */
058: public void setDefaultExtension(String extension) {
059: this .extension = extension;
060: }
061:
062: /**
063: * Sets a collection of component producers which will execute for every view.
064: */
065: public void setDefaultViews(List defaults) {
066: this .defaultviews = defaults;
067: }
068:
069: /**
070: * Set the base directory in which component files will be sought. This must
071: * contain both trailing slash and leading slash. This may designate any
072: * Spring-resolvable resource path (will be handed to application context).
073: */
074:
075: public void setBasePath(String basepath) {
076: this .basepath = basepath;
077: }
078:
079: /**
080: * Sets a list of view names which this resolver will attempt to resolve. If
081: * this list is not set, resolver will attempt to resolve any view. If the
082: * list is set and a request is received for a view not listed in it,
083: * getProducers() will return null rather than throwing an exception, enabling
084: * chaining of resolvers.
085: */
086: public void setViewNames(StringList viewnames) {
087: this .viewnames = viewnames;
088: }
089:
090: public void setXMLProvider(XMLProvider xmlprovider) {
091: this .xmlprovider = xmlprovider;
092: }
093:
094: public void setTemplateExpander(TemplateExpander templateexpander) {
095: this .templateexpander = templateexpander;
096: }
097:
098: public void setResourceLoader(ResourceLoader resourceloader) {
099: this .resourceloader = resourceloader;
100: }
101:
102: public void setCacheSeconds(int cachesecs) {
103: this .cachesecs = cachesecs;
104: }
105:
106: public void setViewParamsReceiver(ViewParamsReceiver vpreceiver) {
107: this .vpreceiver = vpreceiver;
108: }
109:
110: private String getFullPath(String viewId) {
111: String fullpath = basepath + viewId + extension;
112: return fullpath;
113: }
114:
115: public void setApplicationContext(
116: ApplicationContext applicationContext) {
117: if (resourceloader == null) {
118: this .resourceloader = applicationContext;
119: }
120: cachingiss = new CachingInputStreamSource(resourceloader,
121: cachesecs);
122: if (basepath != BASEPATH_DEFAULT) {
123: // make an initial attempt to load ALL producers, both for validation and
124: // also to discover viewparameter types.
125: String allpath = basepath + "*" + extension;
126: Resource[] resources = null;
127: try {
128: resources = applicationContext.getResources(allpath);
129: if (resources == null)
130: resources = new Resource[0];
131: } catch (Exception e) {
132: throw UniversalRuntimeException.accumulate(e,
133: "Error getting resource list for pattern "
134: + allpath);
135: }
136: for (int i = 0; i < resources.length; ++i) {
137: String filename = resources[i].getFilename();
138: String viewid = FilenameUtil.getStem(filename);
139: String fullpath = getFullPath(viewid);
140: tryLoadProducer(fullpath, viewid);
141: }
142: }
143: }
144:
145: private XMLViewComponentProducer tryLoadProducer(String fullpath,
146: String viewId) {
147: XMLViewComponentProducer togo = null;
148: if (Logger.log.isInfoEnabled()) {
149: Logger.log.info("Loading view template from " + fullpath);
150: }
151: InputStream is = cachingiss.openStream(fullpath);
152: if (is != null && is != CachingInputStreamSource.UP_TO_DATE) {
153: try {
154: ViewRoot viewroot = (ViewRoot) xmlprovider.readXML(
155: ViewRoot.class, is);
156: vpreceiver.setViewParamsExemplar(viewId,
157: viewroot.viewParameters);
158: if (viewroot.defaultview) {
159: vpreceiver.setDefaultView(viewId);
160: }
161: togo = new XMLViewComponentProducer();
162: togo.setTemplateExpander(templateexpander);
163: togo.setViewID(viewId);
164: togo.setTemplateContainer(viewroot);
165: views.put(viewId, togo);
166: } catch (Exception e) {
167: throw UniversalRuntimeException.accumulate(e,
168: "Error loading view components from view with path "
169: + fullpath);
170: }
171: } else {
172: return (XMLViewComponentProducer) views.get(viewId);
173: }
174: return togo;
175: }
176:
177: public List getProducers(String viewId) {
178: XMLViewComponentProducer producer = (XMLViewComponentProducer) views
179: .get(viewId);
180: if (producer == null || cachesecs >= 0) {
181: if (viewnames == null || viewnames.contains(viewId)) {
182: String fullpath = basepath + viewId + extension;
183: producer = tryLoadProducer(fullpath, viewId);
184: }
185: }
186: if (producer != null) {
187: ArrayList togo = new ArrayList();
188: if (defaultviews != null) {
189: togo.addAll(defaultviews);
190: }
191: togo.add(producer);
192: return togo;
193: }
194: return null;
195: }
196:
197: }
|