001: /*
002: * Copyright 2004-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: */
017:
018: package org.jpublish.page.xml;
019:
020: import java.io.File;
021: import java.io.InputStream;
022: import java.io.FileNotFoundException;
023: import java.util.Map;
024: import java.util.List;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.ArrayList;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031:
032: import com.anthonyeden.lib.config.Configuration;
033: import com.anthonyeden.lib.config.XMLConfiguration;
034: import com.anthonyeden.lib.config.ConfigurationException;
035: import com.anthonyeden.lib.resource.ResourceRecipient;
036: import com.anthonyeden.lib.resource.FileResourceLoader;
037:
038: import org.jpublish.page.PageInstance;
039: import org.jpublish.page.PageDefinition;
040: import org.jpublish.page.AbstractPageManager;
041: import org.jpublish.util.PathUtilities;
042: import org.jpublish.util.vfs.VFSFile;
043:
044: /** Implementation of the PageManager interface which pulls all page
045: definitions from a single XML file. A default page can be specified
046: as a failover in case a page is not defined.
047:
048: <p><b>Note:</b> The XMLPageManager does not support writing. Any method
049: which would modify pages in the page manager will throw an
050: UnsupportedOperationException.</p>
051:
052: @author Anthony Eden
053: */
054:
055: public class XMLPageManager extends AbstractPageManager implements
056: ResourceRecipient {
057:
058: /** The default file name for the configuration file (pages.xml). */
059: public static final String DEFAULT_FILE_NAME = "pages.xml";
060:
061: private static final Log log = LogFactory
062: .getLog(XMLPageManager.class);
063:
064: protected File file;
065: protected List paths;
066: protected Map pageDefinitions;
067: protected PageDefinition defaultPageDefinition;
068:
069: private FileResourceLoader fileResourceLoader;
070:
071: /** Construct a new XMLPageManager. */
072:
073: public XMLPageManager() {
074: paths = new ArrayList();
075: }
076:
077: /** Get the configuration File object.
078:
079: @return The configuration file
080: */
081:
082: public File getFile() {
083: return file;
084: }
085:
086: /** Set the configuration File object.
087:
088: @param file The configuration file
089: */
090:
091: public void setFile(File file) {
092: this .file = file;
093: }
094:
095: /** Set the configuration File object using the given File path String.
096:
097: @param file The configuration file path
098: */
099:
100: public void setFile(String file) {
101: if (file != null) {
102: setFile(new File(file));
103: } else {
104: this .file = null;
105: }
106: }
107:
108: /** Get a PageInstance from the given path. If no page can be found
109: then this method will throw a FileNotFoundException.
110:
111: @param path The page path
112: @return The Page
113: @throws Exception Any Exception
114: */
115:
116: public synchronized PageInstance getPage(String path)
117: throws Exception {
118: if (pageDefinitions == null) {
119: loadPageDefinitions();
120: }
121:
122: String pagePath = PathUtilities.extractPagePath(path);
123: if (log.isDebugEnabled())
124: log.debug("Page path: " + pagePath);
125:
126: PageDefinition pageDefinition = (PageDefinition) pageDefinitions
127: .get(pagePath);
128: if (pageDefinition == null) {
129:
130: if (defaultPageDefinition != null) {
131: return defaultPageDefinition.getPageInstance(path);
132: }
133:
134: throw new FileNotFoundException("Page not found: " + path);
135: }
136:
137: return pageDefinition.getPageInstance(path);
138: }
139:
140: /** Put the page instance into the location specified by the given
141: path. The XMLPageManager does not currently support writing, so this
142: method will throw an UnsupportedOperationException.
143:
144: @param path The page path
145: @param page The Page object
146: @throws Exception
147: */
148:
149: public void putPage(String path, PageInstance page)
150: throws Exception {
151: throw new UnsupportedOperationException(
152: "Page put not supported");
153: }
154:
155: /** Remove the page at the specified path. The XMLPageManager does not
156: currently support writing, so this method will throw an
157: UnsupportedOperationException.
158:
159: @param path The page path
160: @throws Exception
161: */
162:
163: public void removePage(String path) throws Exception {
164: throw new UnsupportedOperationException(
165: "Page remove not supported");
166: }
167:
168: /** Make the directory for the specified path. Parent directories
169: will also be created if they do not exist. The XMLPageManager
170: does not currently support writing, so this method will throw
171: an UnsupportedOperationException.
172:
173: @param path The directory path
174: */
175:
176: public void makeDirectory(String path) {
177: throw new UnsupportedOperationException(
178: "Make directory not supported");
179: }
180:
181: /** Remove the directory for the specified path. The directory
182: must be empty. The XMLPageManager does not currently support
183: writing, so this method will throw an UnsupportedOperationException.
184:
185: @param path The path
186: @throws Exception
187: */
188:
189: public void removeDirectory(String path) throws Exception {
190: throw new UnsupportedOperationException(
191: "Remove directory not supported");
192: }
193:
194: /** Get an iterator which can be used to iterate through all pages
195: known to the PageManager.
196:
197: @return An Iterator of Pages
198: @throws Exception Any Exception
199: */
200:
201: public Iterator getPages() throws Exception {
202: return getPages("");
203: }
204:
205: /** Get an iterator which can be used to iterate through all the
206: pages at or below the specified path. If the path refers
207: to a file, then the file's parent directory is used.
208:
209: @param path The base path
210: @return An Iterator of Pages
211: @throws Exception Any Exception
212: */
213:
214: public Iterator getPages(String path) throws Exception {
215: return new XMLPageIterator(this , paths, path);
216: }
217:
218: /** Get the Virtual File System root file. The Virtual File System
219: provides a datasource-independent way of navigating through all
220: items known to the PageManager.
221:
222: @return The root VFSFile
223: @throws Exception
224: */
225:
226: public synchronized VFSFile getVFSRoot() throws Exception {
227: // NYI
228: throw new UnsupportedOperationException();
229: }
230:
231: /** Load the Page definitions from an XML configuration file.
232:
233: @throws Exception Any Exception
234: */
235:
236: protected void loadPageDefinitions() throws Exception {
237: if (file == null) {
238: file = new File(DEFAULT_FILE_NAME);
239: }
240:
241: if (!file.isAbsolute()) {
242: file = new File(siteContext.getWebInfPath(), file.getPath());
243: }
244:
245: if (fileResourceLoader != null) {
246: fileResourceLoader.stopMonitors();
247: }
248:
249: fileResourceLoader = new FileResourceLoader();
250: fileResourceLoader.loadResource(file.getAbsolutePath(), this );
251: }
252:
253: /** Load all page definitions from the given configuration InputStream.
254:
255: @param in The InputStream
256: @throws Exception Any Exception
257: */
258:
259: public void load(InputStream in) throws Exception {
260: if (pageDefinitions == null) {
261: pageDefinitions = new HashMap();
262: }
263:
264: paths.clear();
265: pageDefinitions.clear();
266:
267: Configuration configuration = new XMLConfiguration(in);
268: Iterator pageElements = configuration.getChildren("page")
269: .iterator();
270: while (pageElements.hasNext()) {
271: Configuration pageElement = (Configuration) pageElements
272: .next();
273: String path = pageElement.getAttribute("path");
274: if (path == null) {
275: throw new ConfigurationException(
276: "Path attribute required");
277: }
278:
279: PageDefinition pageDefinition = new PageDefinition(
280: siteContext, path);
281: pageDefinition.loadConfiguration(pageElement);
282:
283: paths.add(path);
284:
285: pageDefinitions.put(path, pageDefinition);
286: }
287:
288: loadDefaultPageDefinition(configuration
289: .getChild("default-page"));
290: }
291:
292: /** Load the XMLPageManager configuration.
293:
294: @param configuration The Configuration object
295: @throws ConfigurationException
296: */
297:
298: public void loadConfiguration(Configuration configuration)
299: throws ConfigurationException {
300: setFile(configuration.getChildValue("file"));
301: }
302:
303: /** Load the default PageDefinition from the given Configuration object.
304: The default page definition is optional.
305:
306: @param configuration The Configuration object
307: */
308:
309: private void loadDefaultPageDefinition(Configuration configuration)
310: throws Exception {
311: if (configuration != null) {
312: defaultPageDefinition = new PageDefinition(siteContext, "");
313: defaultPageDefinition.loadConfiguration(configuration);
314: }
315: }
316:
317: }
|