/* * $Id: CachedBuilderPage.java,v 1.22 2009/04/07 23:54:02 eiki Exp $ * * Copyright (C) 2001-2004 Idega hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. * Use is subject to license terms. * */ package com.idega.builder.business; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Serializable; import java.io.StringReader; import java.rmi.RemoteException; import java.util.Iterator; import java.util.List; import java.util.Vector; import org.apache.webdav.lib.WebdavResource; import com.idega.business.IBOLookup; import com.idega.core.builder.data.ICPage; import com.idega.core.builder.data.ICPageHome; import com.idega.core.view.DefaultViewNode; import com.idega.core.view.ViewNode; import com.idega.data.IDOLookup; import com.idega.exception.PageDoesNotExist; import com.idega.idegaweb.IWMainApplication; import com.idega.presentation.IWContext; import com.idega.slide.business.IWSlideService; import com.idega.slide.business.IWSlideSession; import com.idega.util.CoreConstants; import com.idega.util.CoreUtil; import com.idega.util.StringUtil; /** * An abstract class that represents a cached instance of a Builder page. * Subclasses of this class handle pages of different formats such as IBXML,HTML and JSP. * * @author <a href="mailto:tryggvi@idega.is">Tryggvi Larusson</a>, * <a href="mailto:palli@idega.is">Pall Helgason</a> * * @version 1.0 */ public abstract class CachedBuilderPage extends DefaultViewNode implements ViewNode,Serializable { public final static String TYPE_PAGE = IBXMLConstants.PAGE_TYPE_PAGE; public final static String TYPE_TEMPLATE = IBXMLConstants.PAGE_TYPE_TEMPLATE; protected final static String TYPE_DRAFT = IBXMLConstants.PAGE_TYPE_DRAFT; protected final static String TYPE_DPT_TEMPLATE = IBXMLConstants.PAGE_TYPE_DPT_TEMPLATE; protected final static String TYPE_DPT_PAGE = IBXMLConstants.PAGE_TYPE_DPT_PAGE; private String type=TYPE_PAGE; private String _key; private String pageFormat; private String sourceAsString; private List pageKeysUsingThisTemplate; private String pageUri; private String templateKey; /** public IBXMLPage(){ //Default constructor } private IBXMLPage(boolean verify) { setVerifyXML(verify); //_parser = new XMLParser(verify); }*/ public CachedBuilderPage(String key) { super(key,BuilderLogic.getInstance().getBuilderPageRootViewNode()); //this(verify); //setVerifyXML(verifyXML); setPageKey(key); } protected abstract void readPageStream(InputStream stream) throws PageDoesNotExist; /** * Gets the key for the page that this instance represents. * This is typically an id to a ICPage or ib_page. */ public void setSourceFromString(String xmlRepresentation) throws Exception { //htmlSource = htmlRepresentation; //super.setSourceFromString(htmlRepresentation); this.sourceAsString=xmlRepresentation; } public String getSourceAsString(){ return this.sourceAsString; } public String getPageKey() { return this._key; } public void setPageKey(String key){ this._key=key; } public String getType(){ return this.type; } public void setType(String type){ this.type=type; } /** * @return Returns the pageFormat. */ public String getPageFormat() { return this.pageFormat; } /** * @param pageFormat The pageFormat to set. */ public void setPageFormat(String pageFormat) { this.pageFormat = pageFormat; } public void addPageUsingThisTemplate(String id) { if (this.pageKeysUsingThisTemplate == null) { this.pageKeysUsingThisTemplate = new Vector(); } if (!this.pageKeysUsingThisTemplate.contains(id)) { this.pageKeysUsingThisTemplate.add(id); } } public void removePageAsUsingThisTemplate(String id) { if (this.pageKeysUsingThisTemplate == null) { return; } if (this.pageKeysUsingThisTemplate.contains(id)) { this.pageKeysUsingThisTemplate.remove(id); } } public List getUsingTemplate() { if (this.pageKeysUsingThisTemplate == null) { findAllPagesUsingThisTemplate(); } return this.pageKeysUsingThisTemplate; } private void findAllPagesUsingThisTemplate() { this.pageKeysUsingThisTemplate = new Vector(); List l = IBPageFinder.getAllPagesExtendingTemplate(Integer.parseInt(getPageKey())); if (l == null) { return; } Iterator i = l.iterator(); while (i.hasNext()) { ICPage p = (ICPage) i.next(); addPageUsingThisTemplate(p.getPrimaryKey().toString()); } } protected void invalidateAllPagesUsingThisTemplate() { List l = getUsingTemplate(); if (l != null) { Iterator i = l.iterator(); while (i.hasNext()) { String invalid = (String) i.next(); CachedBuilderPage child = getPageCacher().getCachedBuilderPageIfInCache(invalid); if (child != null) { if (child.getType().equals(TYPE_TEMPLATE)) { child.invalidateAllPagesUsingThisTemplate(); } getPageCacher().flagPageInvalid(invalid); } } } } protected BuilderLogic getBuilderLogic(){ return BuilderLogic.getInstance(); } protected PageCacher getPageCacher(){ return getBuilderLogic().getPageCacher(); } /** * This method is called from setPageKey to initialize the page document. * @return * @throws PageDoesNotExist */ protected void setICPage(ICPage ibpage){ try{ setPageFormat(ibpage.getFormat()); InputStream stream = null; try { stream = getPageInputStream(ibpage); } catch (RuntimeException re) { re.printStackTrace(); } if (stream == null) { return; } ensureReferencedPagesLoaded(ibpage); readPageStream(stream); if (ibpage.isPage()) { setType(TYPE_PAGE); } else if (ibpage.isDraft()) { setType(TYPE_DRAFT); } else if (ibpage.isTemplate()) { setType(TYPE_TEMPLATE); } else if (ibpage.isDynamicTriggeredTemplate()) { setType(TYPE_DPT_TEMPLATE); } else if (ibpage.isDynamicTriggeredPage()) { setType(TYPE_DPT_PAGE); } else { setType(TYPE_PAGE); } super.setName(ibpage.getName()); this.templateKey=ibpage.getTemplateKey(); } catch (PageDoesNotExist pe) { int template = ibpage.getTemplateId(); String templateString = null; if (template != -1) { templateString = Integer.toString(template); } if (ibpage.isPage()) { setPageAsEmptyPage(TYPE_PAGE, templateString); } else if (ibpage.isDraft()) { setPageAsEmptyPage(TYPE_DRAFT, templateString); } else if (ibpage.isTemplate()) { setPageAsEmptyPage(TYPE_TEMPLATE, templateString); } else if (ibpage.isDynamicTriggeredTemplate()) { setPageAsEmptyPage(TYPE_DPT_TEMPLATE, templateString); } else if (ibpage.isDynamicTriggeredPage()) { setPageAsEmptyPage(TYPE_DPT_PAGE, templateString); } else { setPageAsEmptyPage(TYPE_PAGE, templateString); } } } protected void ensureReferencedPagesLoaded(ICPage ibpage) { //Ensuring that referenced templates are loaded before us String templateKey = ibpage.getTemplateKey(); if(templateKey!=null){ if(!templateKey.equals("-1")){ getPageCacher().getCachedBuilderPage(templateKey); } } } /** * <p> * Method for getting a reference to the inputstream for reading the page. * </p> * @param pageType * @param templateString */ protected InputStream getPageInputStream(ICPage icPage){ String webdavUri = icPage.getWebDavUri(); if (StringUtil.isEmpty(webdavUri)) { // Older method, read it from ICFile return icPage.getPageValue(); } IWSlideService service = null; try { service = IBOLookup.getServiceInstance(IWMainApplication.getDefaultIWApplicationContext(), IWSlideService.class); } catch (Exception e) { throw new RuntimeException("Error getting " + IWSlideService.class, e); } InputStream stream = null; try { stream = service.getInputStream(webdavUri); } catch (Exception e) {} if (stream == null) { try { WebdavResource file = service.getWebdavResourceAuthenticatedAsRoot(webdavUri); stream = file.getMethodData(); } catch (Exception e) { throw new RuntimeException("Error getting file: " + webdavUri, e); } } return stream; } /** * <p> * Method for getting a reference to the outputStream for storing the page. * </p> * @param pageType * @param templateString */ protected OutputStream getPageOutputStream(ICPage icPage, IWSlideSession session) { String webdavUri = icPage.getWebDavUri(); if (webdavUri == null) { // older method, read it from ICFile return icPage.getPageValueForWrite(); } else { try { if (session == null) { session = IBOLookup.getSessionInstance(IWContext.getInstance(), IWSlideSession.class); } OutputStream out = getPageOutputStream(session, webdavUri); return out; } catch (Exception e) { e.printStackTrace(); } } throw new RuntimeException("Page OutputStream cannot be read"); } private OutputStream getPageOutputStream(IWSlideSession session, String uri) throws IOException { try { String basePath = "/files/cms/pages"; if (uri.startsWith(basePath)) { File baseDir = session.getFile(basePath); baseDir.mkdirs(); } File file = session.getFile(uri); if (!file.exists()) { file.createNewFile(); } return session.getOutputStream(uri); } catch (Exception e) { File file = null; if (IWMainApplication.getDefaultIWMainApplication().getSettings().getBoolean("load_page_for_change_as_file", Boolean.FALSE)) { file = CoreUtil.getFileFromRepository(uri); BuilderLogic.getInstance().clearAllCaches(); } if (file == null || !file.exists() || !file.canWrite()) { throw new IOException("File at " + uri + " can not be found or does not exist or it is impossible to write into it", e); } return new FileOutputStream(file); } } public void setPageAsEmptyPage(String pageType,String templateString){ //does nothing by default } protected ICPage getICPage(){ try { ICPageHome icPageHome = (ICPageHome) IDOLookup.getHome(ICPage.class); return icPageHome.findByPrimaryKey(getPageKey()); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } private boolean store(String webDavUri, IWSlideSession session) { if (webDavUri == null || session == null) { return false; } IWSlideService service = null; try { service = session.getIWSlideService(); } catch (RemoteException e) { e.printStackTrace(); return false; } String source = getSourceAsString(); if (source == null) { return false; } String fileName = webDavUri; String[] pathParts = webDavUri.split(BuilderConstants.BASE_PAGE_PATH); if (pathParts != null) { if (pathParts.length == 2) { fileName = pathParts[1]; } } boolean result = false; try { result = service.uploadFileAndCreateFoldersFromStringAsRoot(BuilderConstants.BASE_PAGE_PATH, fileName, source, "text/xml", true); } catch (RemoteException e) { e.printStackTrace(); return false; } return result; } public synchronized boolean store() { return store(null); } public synchronized boolean store(IWSlideSession session) { try { ICPage icPage = getICPage(); icPage.setFormat(this.getPageFormat()); if (icPage.getWebDavUri() == null || session == null) { OutputStream stream = getPageOutputStream(icPage, session); storeStream(stream); } else { store(icPage.getWebDavUri(), session); } icPage.store(); } catch (NumberFormatException ne) { /*try { OutputStream stream = new FileOutputStream(_key); store(stream); } catch (FileNotFoundException fnfe) { fnfe.printStackTrace(); }*/ } catch (Exception e) { e.printStackTrace(System.err); } //setPopulatedPage(XMLReader.getPopulatedPage(this)); //setPopulatedPage(null); // invalidate the page getPageCacher().flagPageInvalid(getPageKey()); if (getType().equals(TYPE_TEMPLATE)) { invalidateAllPagesUsingThisTemplate(); } return true; } /** * Writes this page to the given OutputStream stream. * Called from the update method * @param stream */ protected synchronized void storeStream(OutputStream stream) { try { //convert the string to utf-8 //String theString = new String(this.toString().getBytes(),"ISO-8859-1"); //String theString = new String(this.toString().getBytes(),CoreConstants.ENCODING_UTF8); String theString = this.toString(); StringReader sr = new StringReader(theString); OutputStreamWriter out = new OutputStreamWriter(stream,CoreConstants.ENCODING_UTF8); int bufferlength=1000; char[] buf = new char[bufferlength]; int read = sr.read(buf); while (read!=-1){ out.write(buf,0,read); read = sr.read(buf); } sr.close(); out.close(); stream.close(); } catch (IOException e) { e.printStackTrace(System.err); } } @Override public String toString() { String s = getSourceAsString(); if(s!=null){ return s; } else{ return super.toString(); } } @Override public String getName() { String sName = super.getName(); if(sName==null){ try { sName= getICPage().getName(); super.setName(sName); } catch (Exception e) { return ""; } } return sName; } public String getTemplateKey() { if(this.templateKey==null){ try { this.templateKey= Integer.toString(getICPage().getTemplateId()); } catch (Exception e) { return "-1"; } } return this.templateKey; } public void setTemplateKey(String templateKey) { try { int id = Integer.parseInt(templateKey); ICPage page = getICPage(); page.setTemplateId(id); page.store(); this.templateKey=templateKey; } catch (Exception e) { e.printStackTrace(); } } @Override public void setName(String name) { try { ICPage page = getICPage(); page.setName(name); page.store(); super.setName(name); } catch (Exception e) { e.printStackTrace(); } } public String getPageUri(){ return this.pageUri; } public void setPageUri(String pageUri){ this.pageUri=pageUri; } @Override public String getURI(){ ViewNode parent = getParent(); String parentUri = parent.getURI(); if(parentUri.endsWith(SLASH)){ //strip the last slash off: parentUri = parentUri.substring(0,parentUri.length()-1); } String theReturn = parentUri+this.getPageUri(); return theReturn; } @Override public String getURIWithContextPath(){ ViewNode parent = getParent(); String parentUri = parent.getURIWithContextPath(); if(parentUri.endsWith(SLASH)){ //strip the last slash off: parentUri = parentUri.substring(0,parentUri.length()-1); } String theReturn = parentUri+this.getPageUri(); return theReturn; } public void initializeEmptyPage(){ //meant to be overrided in subclasses. } }