Java tutorial
/* * Copyright 2004-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.jpublish.page.filesystem; import com.anthonyeden.lib.config.Configuration; import com.anthonyeden.lib.config.ConfigurationException; import com.anthonyeden.lib.util.IOUtilities; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jpublish.page.PageDefinition; import org.jpublish.page.PageDefinitionCacheEntry; import org.jpublish.page.PageInstance; import org.jpublish.util.PathUtilities; import java.io.*; import java.util.HashMap; import java.util.Map; /** * The PageManager is a central access point for locating pages. Pages * are loaded and cached automatically. The cache will check the file's * last modification time and will update if the stored time does not match * the file system's time. * <p/> * <p>This PageManager implementation will fall back to the default.xml page * descriptor of a pages directory and its parents, if the path's expected page * descriptor is not found.</p> * * @author Anthony Eden * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a> */ public class FileSystemPageManagerWithContextDefault extends AbstractFileSystemPageManager { /** * The default path (default.xml) of each page directory. */ public static final String DEFAULT_PATH = "default.xml"; private static Log log = LogFactory.getLog(FileSystemPageManager.class); protected Map cache; protected String defaultPath = DEFAULT_PATH; /** * Construct a new FileSystemPageManagerWithContextDefault. */ public FileSystemPageManagerWithContextDefault() { this.cache = new HashMap(); } /** * Get the path to the default descriptor. * * @return The default path */ public String getDefaultPath() { return defaultPath; } /** * Set the path to the default descriptor. * * @param defaultPath the default descriptor */ public void setDefaultPath(String defaultPath) { if (defaultPath == null) { this.defaultPath = DEFAULT_PATH; } else { this.defaultPath = defaultPath; } } /** * Get a PageInstance from the given path. If no page can be found * then this method will throw a FileNotFoundException. * * @param path The page path * @return The Page * @throws Exception Any Exception */ public synchronized PageInstance getPage(String path) throws Exception { File file = new File(path); File parentDirectory = file.getParentFile(); String pageName = PathUtilities.extractPageName(path); String pageType = PathUtilities.extractPageType(path); String pagePath = PathUtilities.extractPagePath(path); if (log.isDebugEnabled()) { log.debug("Page name: " + pageName); log.debug("Page type: " + pageType); log.debug("Page path: " + pagePath); } File xmlFile = new File(getRoot(), new File(parentDirectory, pageName + ".xml").getPath()); if (!xmlFile.exists()) { xmlFile = getPathContextDefaultPage(getRoot(), pagePath); if (!xmlFile.exists()) { throw new FileNotFoundException("Default page descriptor not found: " + xmlFile); } } if (log.isDebugEnabled()) log.debug("Looking for page:" + xmlFile); // check the cache and load the page definition if necessary PageDefinitionCacheEntry cacheEntry = (PageDefinitionCacheEntry) cache.get(pagePath); PageInstance page = null; PageDefinition pageDefinition = null; FileInputStream in = null; try { if (cacheEntry == null) { if (log.isDebugEnabled()) log.debug("Page definition (" + pagePath + ") not found in cache."); if (log.isDebugEnabled()) log.debug("Loading page definition configuration: " + xmlFile); in = new FileInputStream(xmlFile); pageDefinition = new PageDefinition(siteContext, pagePath); pageDefinition.loadConfiguration(in); cache.put(pagePath, new PageDefinitionCacheEntry(pageDefinition, xmlFile.lastModified())); } else { if (log.isDebugEnabled()) log.debug("Page definition (" + pagePath + ") found in cache."); pageDefinition = cacheEntry.getPageDefinition(); if (cacheEntry.getLastModified() != xmlFile.lastModified()) { if (log.isDebugEnabled()) { log.debug("Page modification dates do not match."); log.debug("Reloading page definition."); } long lastModified = xmlFile.lastModified(); in = new FileInputStream(xmlFile); pageDefinition = new PageDefinition(siteContext, pagePath); pageDefinition.loadConfiguration(in); cache.put(pagePath, new PageDefinitionCacheEntry(pageDefinition, lastModified)); } } } catch (Exception e) { log.error("Error loading page definition: " + e.getMessage()); throw e; } finally { IOUtilities.close(in); } if (pageDefinition != null) { if (log.isDebugEnabled()) log.debug("Getting page instance for " + path); page = pageDefinition.getPageInstance(path); } return page; } /** * browse the parent folders for searching the default page descriptor * * @param root the root directory * @param path the requested path * @return default file */ private File getPathContextDefaultPage(File root, String path) { String defPage = File.separatorChar + getDefaultPath(); File parentDir = new File(root, path.substring(0, path.lastIndexOf("/"))); File rootDefaultPage = new File(root, defPage); File defaultFile = new File(parentDir, defPage); while (!defaultFile.exists() && !(rootDefaultPage.equals(defaultFile))) { parentDir = new File(parentDir.getParent()); defaultFile = new File(parentDir + defPage); } return defaultFile; } /** * Put the page instance into the location specified by the given * path. * * @param path The page path * @param page The PageInstance object * @throws Exception */ public void putPage(String path, PageInstance page) throws Exception { // NYI } /** * Remove the page at the specified path. * * @param path The page path * @throws Exception Any Exception */ public void removePage(String path) throws Exception { pathToFile(path).delete(); } /** * Make the directory for the specified path. Parent directories * will also be created if they do not exist. * * @param path The directory path */ public void makeDirectory(String path) { File file = new File(getRoot(), path); file.mkdirs(); } /** * Remove the directory for the specified path. The directory * must be empty. * * @param path The path * @throws Exception */ public void removeDirectory(String path) throws Exception { File file = new File(getRoot(), path); if (file.isDirectory()) { file.delete(); } else { throw new Exception("Path is not a directory: " + path); } } /** * Load the PageManager's configuration. * * @param configuration The Configuration object * @throws ConfigurationException */ public void loadConfiguration(Configuration configuration) throws ConfigurationException { setDefaultPath(configuration.getChildValue("default-path")); } /** * Get a page configuration reader for the page at the specified * path. * * @param path The page path * @return The configuration reader * @throws Exception */ public Reader getPageConfigurationReader(String path) throws Exception { File xmlFile = pathToFile(path); if (!xmlFile.exists()) { throw new FileNotFoundException("File not found: " + xmlFile); } return new FileReader(xmlFile); } /** * Get a page configuration writer for the page at the specified * path. This method may throw an UnsupportedOperationException if * the PageManager implementation does not provide for updating * a page's configuration. * * @param path The page path * @return The Writer * @throws Exception */ public Writer getPageConfigurationWriter(String path) throws Exception { return new FileWriter(pathToFile(path)); } protected File pathToFile(String path) { if (path.endsWith("/")) { return new File(getRoot(), path); } File file = new File(path); File parentDirectory = file.getParentFile(); String pageName = PathUtilities.extractPageName(path); return new File(getRoot(), new File(parentDirectory, pageName + ".xml").getPath()); } }