/* * Created on Jan 28, 2005 */ package com.openedit.page.manage; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Element; import org.openedit.repository.RepositoryException; import com.openedit.Generator; import com.openedit.OpenEditException; import com.openedit.config.Configuration; import com.openedit.config.Script; import com.openedit.config.Style; import com.openedit.generators.CompositeGenerator; import com.openedit.generators.GeneratorWithAcceptFilter; import com.openedit.generators.GeneratorWithMimeTypeFilter; import com.openedit.page.Page; import com.openedit.page.PageAction; import com.openedit.page.PageProperty; import com.openedit.page.PageSettings; import com.openedit.page.Permission; import com.openedit.page.XconfConfiguration; import com.openedit.util.OutputFiller; import com.openedit.util.PathUtilities; import com.openedit.util.XmlUtil; import com.openedit.util.strainer.Filter; import com.openedit.util.strainer.FilterReader; /** * @author cburkey * */ public class XConfToPageSettingsConverter { private static final Log log = LogFactory.getLog(XConfToPageSettingsConverter.class); protected PageSettingsManager fieldPageSettingsManager; protected FilterReader fieldFilterReader; protected XmlUtil fieldXmlUtil = new XmlUtil(); protected OutputFiller fieldOutputFiller = new OutputFiller(); protected List loadActions( PageSettings inSettings,List inPageActionList ) throws OpenEditException { if ( inPageActionList.size() == 0) { return null; } List pageActions = new ArrayList(inPageActionList.size()); Iterator pageActionElements = inPageActionList.iterator(); while (pageActionElements.hasNext()) { Configuration pageActionElement = (Configuration) pageActionElements.next(); PageAction currentPageAction = createAction(inSettings, pageActionElement ); pageActions.add( currentPageAction ); } return pageActions; } protected List loadScripts( PageSettings inSettings,List inScripts ) throws OpenEditException { if ( inScripts.size() == 0) { return null; } List pageActions = new ArrayList(inScripts.size()); Iterator pageActionElements = inScripts.iterator(); while (pageActionElements.hasNext()) { Configuration pageActionElement = (Configuration) pageActionElements.next(); Script script = createScript(inSettings, pageActionElement ); pageActions.add( script ); } return pageActions; } protected List loadStyles( PageSettings inSettings,List inStyles ) throws OpenEditException { if ( inStyles.size() == 0) { return null; } List pageActions = new ArrayList(inStyles.size()); Iterator pageActionElements = inStyles.iterator(); while (pageActionElements.hasNext()) { Configuration pageActionElement = (Configuration) pageActionElements.next(); Style script = createStyle(inSettings, pageActionElement ); if( script != null) { pageActions.add( script ); } } return pageActions; } protected Script createScript(PageSettings inSettings, Configuration inConfigElement) { String cancel = inConfigElement.get("cancel"); if(cancel != null && cancel.equals("true") ) { return null; } Script script = new Script(); script.setId(inConfigElement.get("id")); script.setSrc(inConfigElement.get("src")); String external = inConfigElement.get("external"); script.setExternal(Boolean.parseBoolean(external)); return script; } protected Style createStyle(PageSettings inSettings, Configuration inConfigElement) { Style style = new Style(); style.setId(inConfigElement.get("id")); style.setHref(inConfigElement.get("href")); style.setExternal(Boolean.parseBoolean(inConfigElement.get("external"))); return style; } private PageAction createAction(PageSettings inSettings, Configuration inPageActionElement) { String actionName = inPageActionElement.getAttribute("name"); PageAction currentPageAction = new PageAction( actionName ); currentPageAction.setPath(inSettings.getXConf().getPath()); currentPageAction.setConfig( inPageActionElement ); currentPageAction.setIncludesAll(Boolean.parseBoolean( inPageActionElement.getAttribute("alltypes") ) ); return currentPageAction; } protected void loadAlternateContentFile( PageSettings inPageConfig, String inAlternatePath ) { if ( inAlternatePath != null ) { String path = PathUtilities.resolveRelativePath(inAlternatePath,inPageConfig.getPath()); inPageConfig.setAlternateContentPath( path ); } } protected void loadGenerators( PageSettings inPageConfig, Configuration inParentConfig) throws OpenEditException { if ( inParentConfig == null ) { return; } List allGens = new ArrayList(2); List root = inParentConfig.getChildren("generator"); //these are top level generators for (Iterator iter = root.iterator(); iter.hasNext();) { Configuration rootconfig = (Configuration) iter.next(); Generator generator = createGenerator(rootconfig); allGens.add(generator); } inPageConfig.setGenerators(allGens); } protected Generator createGenerator(Configuration inRootconfig) throws OpenEditException { String name = inRootconfig.getAttribute("name"); Generator generator = null; if ( name.equals("composite")) { //now add any children to a list List children = inRootconfig.getChildren("generator"); List all = new ArrayList(children.size()); for (Iterator iter = children.iterator(); iter.hasNext();) { Configuration config = (Configuration) iter.next(); Generator child = createGenerator(config); all.add(child); } CompositeGenerator composite = new CompositeGenerator(); composite.setGenerators(all); generator = composite; } else { generator = getPageSettingsManager().getGenerator( name ); } generator = addFilter(inRootconfig,generator); return generator; } protected Generator addFilter(Configuration config, Generator generator) { String types = config.getAttribute("mimetypes"); if( types != null) { generator = new GeneratorWithMimeTypeFilter(generator,types); } String accepts = config.getAttribute("accepts"); if ( accepts != null) { generator = new GeneratorWithAcceptFilter(generator,accepts); } return generator; } protected void loadLayout( PageSettings inPageConfig, Configuration inLayoutConfig ) throws OpenEditException { if ( inLayoutConfig == null ) { return; } String layoutPath = inLayoutConfig.getValue(); if ( layoutPath == null ) { inPageConfig.setLayout(Page.BLANK_LAYOUT); return; } layoutPath = PathUtilities.resolveRelativePath( layoutPath, inPageConfig.getPath() ); if ( layoutPath.equals(inPageConfig.getPath())) { //dont set layout to self inPageConfig.setLayout(null); return; } inPageConfig.setLayout( layoutPath ); } protected void loadInnerLayout( PageSettings inPageConfig, Configuration inInnerLayoutConfig ) throws OpenEditException { if ( inInnerLayoutConfig == null ) { return; } String innerLayoutPath = inInnerLayoutConfig.getValue(); if ( innerLayoutPath == null ) { inPageConfig.setInnerLayout(Page.BLANK_LAYOUT); return; } innerLayoutPath = PathUtilities.resolveRelativePath( innerLayoutPath, inPageConfig.getPath() ); if ( innerLayoutPath.equals(inPageConfig.getPath())) { //dont set layout to self inPageConfig.setInnerLayout(Page.BLANK_LAYOUT); return; } inPageConfig.setInnerLayout( innerLayoutPath ); } protected void loadPermissionFilters( PageSettings inPageConfig, XconfConfiguration inConfig ) throws OpenEditException { List permissions = new ArrayList(); Filter viewf = getFilterReader().readFilterCollection( inConfig.getViewRequirements(),"view" ); if( viewf != null) { Permission per = new Permission(); per.setName("view"); per.setRootFilter(viewf); per.setPath(inPageConfig.getPath()); permissions.add(per); } Filter edit = getFilterReader().readFilterCollection( inConfig.getEditRequirements(),"edit" ); if( edit != null) { Permission per = new Permission(); per.setName("edit"); per.setRootFilter(edit); per.setPath(inPageConfig.getPath()); permissions.add(per); } for (Iterator iterator = inConfig.getChildIterator("permission"); iterator.hasNext();) { Configuration top = (Configuration) iterator.next(); String name = top.getAttribute("name"); Filter root = getFilterReader().readFilterCollection( top,name ); Permission per = new Permission(); per.setName(name); per.setRootFilter(root); per.setPath(inPageConfig.getPath()); permissions.add(per); } if( permissions.size() > 0) { inPageConfig.setPermissions(permissions); } } protected Map loadProperties( List inPropertyList ) { Map properties = new HashMap(inPropertyList.size()); Iterator propertyElements = inPropertyList.iterator(); while (propertyElements.hasNext()) { Configuration propertyElement = (Configuration) propertyElements.next(); String name = propertyElement.getAttribute("name"); PageProperty property = new PageProperty(name); boolean hasvalue = false; for (Iterator iter = propertyElement.getChildIterator("value"); iter.hasNext();) { hasvalue = true; Configuration val = (Configuration) iter.next(); String locale = val.getAttribute("locale"); property.setValue(val.getValue(), locale); //TODO: Should I pass "" if its the default locale already? } if( !hasvalue ) { String value = propertyElement.getValue(); // if( value == null) // { // value = ""; // } property.setValue(value, (Locale)null); } properties.put(name, property); } return properties; } public PageSettingsManager getPageSettingsManager() { return fieldPageSettingsManager; } public void setPageSettingsManager(PageSettingsManager inPageSettingsManager) { fieldPageSettingsManager = inPageSettingsManager; } /** * @param inPageSettings * @param inUrlPath */ public void configure(PageSettings inPageSettings, String inUrlPath) throws OpenEditException { boolean contentexists = getPageSettingsManager().getRepository().doesExist( inUrlPath ); boolean settings = inPageSettings.exists(); if ( !settings ) { loadFallBackDirectory( inPageSettings, inUrlPath, contentexists ); // loadOverrideDirectory( inPageSettings, inUrlPath ); loadAlternativeContent(inPageSettings, inUrlPath, contentexists); // return; } if( log.isDebugEnabled()) { log.info( "Configure: " + inPageSettings.getPath() ); } XconfConfiguration config = new XconfConfiguration( ); Element root= null; try { root = fieldXmlUtil.getXml(inPageSettings.getReader(),inPageSettings.getPageCharacterEncoding()); } catch (Exception e ) { log.error("Could not read: " + inUrlPath ); throw new OpenEditException(e + "path: " + inPageSettings.getPath(),e,inUrlPath); } config.populate(root); inPageSettings.getProperties().putAll( loadProperties( config.getProperties())); if( settings ) //Reloads it here since it was not loaded above { loadFallBackDirectory( inPageSettings, inUrlPath, contentexists ); loadAlternativeContent(inPageSettings, inUrlPath, contentexists); } loadPermissionFilters( inPageSettings, config ); loadGenerators(inPageSettings, config); loadLayout( inPageSettings, config.getLayout() ); loadInnerLayout( inPageSettings, config.getInnerLayout() ); //TODO: Move this to a module //List pageActions = new ArrayList(); //pageActions.addAll( loadValues( config.getPageValues(), "PageValue." ) ); //pageActions.addAll( loadValues( config.getSessionValues(), "SessionValue.") ); List pagea = loadActions( inPageSettings,config.getPageActions() ); inPageSettings.setPageActions( pagea ); List patha = loadActions(inPageSettings,config.getPathActions()); inPageSettings.setPathActions(patha); inPageSettings.setScripts(loadScripts(inPageSettings,config.getScripts())); inPageSettings.setStyles(loadStyles(inPageSettings,config.getStyles())); //turns out we need this for login-path and other places I am sure //If there are unkown tags in the xconf then set the user defined data field if ( config.hasChild("product") || config.hasChild("asset") || config.hasChild("blog")) //TODO: Do we use this anymore? { inPageSettings.setUserDefinedData(config); } String mime = inPageSettings.getPropertyValue("mimetype", null); if( mime != null) { inPageSettings.setMimeType(mime); } } protected void loadAlternativeContent(PageSettings inPageSettings, String inUrlPath, boolean inContentexists) throws RepositoryException { inPageSettings.setOriginalyExistedContentPath(inContentexists); //Find the alternative content path if found someplace else String fallback = inPageSettings.getPropertyValueFixed("fallbackcontentpath"); if( fallback != null) { fallback = PathUtilities.resolveRelativePath(fallback, inPageSettings.getPath()); inPageSettings.setAlternateContentPath(fallback); } else if(!inContentexists) { //Look for some content to use PageSettings settings = inPageSettings.getFallback(); boolean isfolder = false; if( settings != null && settings.getPath().endsWith("/_site.xconf") && !inUrlPath.endsWith("_site.xconf")) { isfolder = true; } while( settings != null) { String alternativepath = settings.getPath(); alternativepath = PathUtilities.extractDirectoryPath(alternativepath); if(!isfolder) { alternativepath += "/" + PathUtilities.extractFileName(inUrlPath); } boolean fallbackcontentexists = getPageSettingsManager().getRepository().doesExist(alternativepath); if( fallbackcontentexists ) { inPageSettings.setAlternateContentPath(alternativepath); break; } settings = settings.getFallback(); } } } /** * @param inPageSettings * @param inUrlPath */ protected void loadFallBackDirectory(PageSettings inPageSettings, String inUrlPath, boolean contentexists) throws OpenEditException { boolean inwebinfs = false; if ( inUrlPath.startsWith("/WEB-INF/")) { inwebinfs = true; } boolean specified = false; String fallBackValue = null; //this is a catch 22. If we don't have a 1st level fallback set it might not look for second level PageProperty fallBackDir = inPageSettings.getProperty("fallbackdirectory"); String alternativepath = null; if ( fallBackDir != null && fallBackDir.getValue() != null ) { fallBackValue = fallBackDir.getValue(); //1. First is looks in mattcatalog. But there we want to use another fallback //this might be using a variable. The value for this comes from the parent fallBackValue = inPageSettings.replaceProperty(fallBackValue); fallBackValue = inPageSettings.getParent().replaceProperty(fallBackValue); if( fallBackValue.equals("/")) { fallBackValue = ""; } if ( fallBackValue.endsWith("/")){ throw new OpenEditException("Fall back setting must not end in slash for " + inUrlPath); } if( fallBackValue.equals("NO_FALLBACK") ) { return; } //Find out the directory we are in. String thisdir = fallBackDir.getPath(); //There is a problem here, we seem to be mixing and matching paths and the substring // if( !inUrlPath.startsWith(thisdir) ) // { // inwebinfs = true; // } // else // { thisdir = PathUtilities.extractDirectoryPath(thisdir); //what level the path was defined String filepart = inUrlPath.substring(thisdir.length(),inUrlPath.length()); alternativepath = fallBackValue + filepart; //end part might be a file name or _site.xconf if( alternativepath.equals(inUrlPath)) { //Now sure why this happens log.debug(inUrlPath + " Cannot specify self as fallback directory"); return; } specified = true; // } } else if(!inwebinfs)//Site wide default { fallBackValue = "/WEB-INF/base"; alternativepath = fallBackValue + inUrlPath; } try { if( inwebinfs && !specified) { //log.info("Not loading fallback for " + inUrlPath); } else { PageSettings otherxconf = getPageSettingsManager().getPageSettings(alternativepath); //log.info("loading fallback for " + inUrlPath + " with " + alternativepath); inPageSettings.setFallBack(otherxconf); // if( specified ) // { // followFallBack(inPageSettings, fallBackDir, alternativepath); // } } } catch ( Exception ex ) { log.error(ex); if( ex instanceof OpenEditException) { throw (OpenEditException)ex; } throw new OpenEditException(ex); } } /* protected void followFallBack(PageSettings inPageSettings, PageProperty fallBackDir, String alternativepath) { PageSettings otherxconf; PageProperty fallBackDirNew = inPageSettings.getProperty("fallbackdirectory"); String oldval = fallBackDir == null?null:fallBackDir.getValue(); String newval = fallBackDirNew == null?null:fallBackDirNew.getValue(); if( newval != null && !newval.equals( oldval ) ) { //loadFallBackDirectory(inPageSettings,inUrlPath, contentexists); //log.info(newval); String defined = PathUtilities.extractDirectoryPath(fallBackDirNew.getPath()); //what level the path was defined String extrapathinfo = alternativepath.substring(defined.length() ); newval = inPageSettings.replaceProperty(newval); newval = inPageSettings.getParent().replaceProperty(newval); newval = newval + extrapathinfo; otherxconf = getPageSettingsManager().getPageSettings(newval); inPageSettings.setFallBack(otherxconf); followFallBack(inPageSettings,fallBackDirNew,alternativepath); } } */ public FilterReader getFilterReader() { return fieldFilterReader; } public void setFilterReader(FilterReader inFilterReader) { fieldFilterReader = inFilterReader; } }