| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.lenya.defaultpub.cms.publication.templating; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.net.MalformedURLException; |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.TransformerConfigurationException; |
| import javax.xml.transform.TransformerException; |
| |
| import org.apache.avalon.framework.configuration.Configuration; |
| import org.apache.avalon.framework.configuration.MutableConfiguration; |
| import org.apache.avalon.framework.configuration.ConfigurationException; |
| import org.apache.avalon.framework.configuration.DefaultConfiguration; |
| import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; |
| import org.apache.avalon.framework.configuration.DefaultConfigurationSerializer; |
| import org.apache.avalon.framework.logger.AbstractLogEnabled; |
| import org.apache.avalon.framework.service.ServiceException; |
| import org.apache.avalon.framework.service.ServiceManager; |
| import org.apache.avalon.framework.service.Serviceable; |
| import org.apache.cocoon.components.search.components.IndexManager; |
| import org.apache.excalibur.source.ModifiableSource; |
| import org.apache.excalibur.source.Source; |
| import org.apache.excalibur.source.SourceNotFoundException; |
| import org.apache.excalibur.source.SourceResolver; |
| import org.apache.excalibur.source.impl.FileSource; |
| import org.apache.lenya.cms.publication.Publication; |
| import org.apache.lenya.cms.publication.PublicationManager; |
| // import org.apache.lenya.cms.publication.PublicationConfiguration; |
| import org.apache.lenya.xml.DocumentHelper; |
| import org.apache.lenya.xml.NamespaceHelper; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Instantiate the publication. |
| * |
| * @version $Id$ |
| */ |
| public class Instantiator extends AbstractLogEnabled implements |
| org.apache.lenya.cms.publication.templating.Instantiator, Serviceable { |
| |
| protected static final String[] sourcesToCopy = { |
| "config/publication.xml", |
| "config/access-control/access-control.xml", |
| "config/access-control/policies/", |
| "config/access-control/usecase-policies.xml", |
| "config/workflow/workflow.xml", |
| "config/" |
| + org.apache.cocoon.components.search.components.impl.IndexManagerImpl.INDEX_CONF_FILE }; |
| |
| // the following stuff should actually come from PublicationConfiguration, |
| // but there's currently no way to get at it. |
| // the correct solution suggested by andreas is not to meddle with config |
| // files here at all, but instead implement |
| // appropriate setter functions in the Publication class. postponed to after |
| // 2.0. |
| // thus, don't waste too much effort on this file, it's all an intermediate |
| // hack. |
| private static final String CONFIGURATION_FILE = "config/publication.xml"; |
| private static final String CONFIGURATION_NAMESPACE = "http://apache.org/cocoon/lenya/publication/1.1"; |
| private static final String ELEMENT_NAME = "name"; |
| private static final String ELEMENT_TEMPLATE = "template"; |
| private static final String ATTRIBUTE_ID = "id"; |
| private static final String ELEMENT_RESOURCE_TYPES = "resource-types";// * |
| private static final String ELEMENT_RESOURCE_TYPE = "resource-type";// * |
| private static final String ELEMENT_MODULES = "modules";// * |
| private static final String ELEMENT_MODULE = "module";// * |
| |
| /** |
| * @see org.apache.lenya.cms.publication.templating.Instantiator#instantiate(org.apache.lenya.cms.publication.Publication, |
| * java.lang.String, java.lang.String) |
| */ |
| public void instantiate(Publication template, String newPublicationId, String name) |
| throws Exception { |
| |
| SourceResolver resolver = null; |
| Source publicationsSource = null; |
| PublicationManager pubManager = null; |
| try { |
| resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); |
| |
| publicationsSource = resolver.resolveURI("context://" |
| + Publication.PUBLICATION_PREFIX_URI); |
| String publicationsUri = publicationsSource.getURI(); |
| |
| for (int i = 0; i < sourcesToCopy.length; i++) { |
| |
| String source = sourcesToCopy[i]; |
| if (source.endsWith("/")) { |
| copyDirSource(template, newPublicationId, resolver, publicationsUri, source); |
| } else { |
| copySource(template, newPublicationId, resolver, publicationsUri, source); |
| } |
| } |
| |
| updateMetaData(resolver, newPublicationId, name, publicationsUri); |
| |
| configureSearchIndex(resolver, template, newPublicationId, publicationsUri); |
| |
| updateConfiguration(resolver, template, newPublicationId, publicationsUri); |
| |
| pubManager = (PublicationManager) this.manager.lookup(PublicationManager.ROLE); |
| pubManager.addPublication(newPublicationId); |
| |
| } finally { |
| if (resolver != null) { |
| this.manager.release(resolver); |
| if (publicationsSource != null) { |
| resolver.release(publicationsSource); |
| } |
| } |
| if (pubManager != null) { |
| this.manager.release(pubManager); |
| } |
| } |
| |
| } |
| |
| protected void updateMetaData(SourceResolver resolver, String newPublicationId, String name, |
| String publicationsUri) throws MalformedURLException, IOException, |
| ParserConfigurationException, SAXException, SourceNotFoundException, |
| TransformerConfigurationException, TransformerException { |
| ModifiableSource metaSource = null; |
| try { |
| metaSource = (ModifiableSource) resolver.resolveURI(publicationsUri + "/" |
| + newPublicationId + "/" + CONFIGURATION_FILE); |
| Document metaDoc = DocumentHelper.readDocument(metaSource.getInputStream()); |
| NamespaceHelper helper = new NamespaceHelper(CONFIGURATION_NAMESPACE, "", metaDoc); |
| Element nameElement = helper.getFirstChild(metaDoc.getDocumentElement(), ELEMENT_NAME); |
| DocumentHelper.setSimpleElementText(nameElement, name); |
| |
| save(metaDoc, metaSource); |
| } finally { |
| if (resolver != null) { |
| if (metaSource != null) { |
| resolver.release(metaSource); |
| } |
| } |
| } |
| } |
| |
| protected void updateConfiguration(SourceResolver resolver, Publication template, |
| String newPublicationId, String publicationsUri) throws MalformedURLException, |
| IOException, SAXException, ConfigurationException, SourceNotFoundException { |
| ModifiableSource configSource = null; |
| try { |
| |
| configSource = (ModifiableSource) resolver.resolveURI(publicationsUri + "/" |
| + newPublicationId + "/" + CONFIGURATION_FILE); |
| |
| final boolean ENABLE_XML_NAMESPACES = true; |
| DefaultConfiguration config = (DefaultConfiguration) new DefaultConfigurationBuilder( |
| ENABLE_XML_NAMESPACES).build(configSource.getInputStream()); |
| addTemplateConfiguration(template, config); |
| |
| removeChildren(config.getMutableChild(ELEMENT_MODULES), ELEMENT_MODULE); |
| removeChildren(config.getMutableChild(ELEMENT_RESOURCE_TYPES), ELEMENT_RESOURCE_TYPE); |
| |
| OutputStream oStream = configSource.getOutputStream(); |
| new DefaultConfigurationSerializer().serialize(oStream, config); |
| if (oStream != null) { |
| oStream.flush(); |
| try { |
| oStream.close(); |
| } catch (Throwable t) { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Exception closing output stream: ", t); |
| } |
| throw new RuntimeException("Could not write document: ", t); |
| } |
| } |
| } finally { |
| if (resolver != null) { |
| if (configSource != null) { |
| resolver.release(configSource); |
| } |
| } |
| } |
| } |
| |
| protected void addTemplateConfiguration(Publication template, DefaultConfiguration config) |
| throws ConfigurationException { |
| Configuration[] templateConfigs = config.getChildren(ELEMENT_TEMPLATE); |
| for (int i = 0; i < templateConfigs.length; i++) { |
| config.removeChild(templateConfigs[i]); |
| } |
| DefaultConfiguration templateConfig = new DefaultConfiguration(ELEMENT_TEMPLATE, null, |
| CONFIGURATION_NAMESPACE, ""); |
| templateConfig.setAttribute(ATTRIBUTE_ID, template.getId()); |
| config.addChild(templateConfig); |
| } |
| |
| protected void removeChildren(MutableConfiguration config, String name) |
| throws ConfigurationException { |
| MutableConfiguration[] moduleConfigs = config.getMutableChildren(name); |
| for (int i = 0; i < moduleConfigs.length; i++) { |
| config.removeChild(moduleConfigs[i]); |
| } |
| } |
| |
| protected void configureSearchIndex(SourceResolver resolver, Publication template, |
| String newPublicationId, String publicationsUri) throws MalformedURLException, |
| IOException, ParserConfigurationException, SAXException, SourceNotFoundException, |
| TransformerConfigurationException, TransformerException, ServiceException, |
| ConfigurationException { |
| ModifiableSource indexSource = null; |
| IndexManager indexManager = null; |
| try { |
| |
| // RGE: Soc addition |
| // First, patch the xconf patchfile with the new publication name |
| |
| String indexDir = "lenya/pubs/" + newPublicationId + "/work/lucene/index"; |
| |
| indexSource = (ModifiableSource) resolver |
| .resolveURI(publicationsUri |
| + "/" |
| + newPublicationId |
| + "/config/" |
| + org.apache.cocoon.components.search.components.impl.IndexManagerImpl.INDEX_CONF_FILE); |
| Document indexDoc = DocumentHelper.readDocument(indexSource.getInputStream()); |
| Element[] indexElement = DocumentHelper.getChildren(indexDoc.getDocumentElement(), |
| null, "index"); |
| |
| for (int i = 0; i < indexElement.length; i++) { |
| String id = indexElement[i].getAttribute("id"); |
| String area = id.split("-")[1]; |
| indexElement[i].setAttribute("id", newPublicationId + "-" + area); |
| indexElement[i].setAttribute("directory", indexDir + "/" + area + "/index"); |
| } |
| |
| save(indexDoc, indexSource); |
| |
| // Second, configure the index and add it to the IndexManager |
| |
| indexManager = (IndexManager) manager.lookup(IndexManager.ROLE); |
| |
| indexManager.addIndexes(indexSource); |
| |
| // TODO: release all objects! |
| |
| // RGE: End Soc addition |
| |
| } finally { |
| if (indexManager != null) { |
| this.manager.release(indexManager); |
| } |
| if (resolver != null) { |
| this.manager.release(resolver); |
| if (indexSource != null) { |
| resolver.release(indexSource); |
| } |
| } |
| } |
| } |
| |
| protected void copySource(Publication template, String publicationId, SourceResolver resolver, |
| String publicationsUri, String source) throws MalformedURLException, IOException { |
| Source templateSource = null; |
| ModifiableSource targetSource = null; |
| try { |
| templateSource = resolver.resolveURI(publicationsUri + "/" + template.getId() + "/" |
| + source); |
| targetSource = (ModifiableSource) resolver.resolveURI(publicationsUri + "/" |
| + publicationId + "/" + source); |
| |
| org.apache.lenya.cms.cocoon.source.SourceUtil.copy(templateSource, targetSource, false); |
| } finally { |
| if (templateSource != null) { |
| resolver.release(templateSource); |
| } |
| if (targetSource != null) { |
| resolver.release(targetSource); |
| } |
| } |
| } |
| |
| protected void copyDirSource(Publication template, String publicationId, |
| SourceResolver resolver, String publicationsUri, String source) |
| throws MalformedURLException, IOException { |
| FileSource directory = new FileSource(publicationsUri + "/" + template.getId() + "/" |
| + source); |
| Collection files = directory.getChildren(); |
| for (Iterator iter = files.iterator(); iter.hasNext();) { |
| FileSource filesource = (FileSource) iter.next(); |
| if (filesource.isCollection()) { |
| copyDirSource(template, publicationId, resolver, publicationsUri, source + "/" |
| + filesource.getName()); |
| } else { |
| copySource(template, publicationId, resolver, publicationsUri, source + "/" |
| + filesource.getName()); |
| } |
| } |
| } |
| |
| protected void save(Document metaDoc, ModifiableSource metaSource) throws IOException, |
| TransformerConfigurationException, TransformerException { |
| OutputStream oStream = metaSource.getOutputStream(); |
| DocumentHelper.writeDocument(metaDoc, new OutputStreamWriter(oStream)); |
| if (oStream != null) { |
| oStream.flush(); |
| try { |
| oStream.close(); |
| } catch (Throwable t) { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Exception closing output stream: ", t); |
| } |
| throw new RuntimeException("Could not write document: ", t); |
| } |
| } |
| } |
| |
| private ServiceManager manager; |
| |
| /** |
| * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) |
| */ |
| public void service(ServiceManager manager) throws ServiceException { |
| this.manager = manager; |
| } |
| |
| } |