001/* 002 * Copyright 2011 Anyware Services 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 */ 016package org.ametys.skinfactory.generators; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.nio.file.Files; 021import java.nio.file.Path; 022import java.nio.file.StandardCopyOption; 023import java.util.HashSet; 024import java.util.Map; 025import java.util.Set; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.ProcessingException; 030import org.apache.cocoon.components.source.impl.SitemapSource; 031import org.apache.cocoon.generation.ServiceableGenerator; 032import org.apache.cocoon.xml.XMLUtils; 033import org.apache.commons.collections.SetUtils; 034import org.apache.excalibur.source.Source; 035import org.apache.excalibur.source.SourceResolver; 036import org.apache.excalibur.xml.dom.DOMParser; 037import org.apache.excalibur.xml.sax.SAXParser; 038import org.apache.excalibur.xml.xpath.XPathProcessor; 039import org.w3c.dom.Document; 040import org.w3c.dom.Element; 041import org.w3c.dom.NodeList; 042import org.xml.sax.InputSource; 043import org.xml.sax.SAXException; 044 045import org.ametys.core.util.IgnoreRootHandler; 046import org.ametys.plugins.skincommons.SkinEditionHelper; 047import org.ametys.skinfactory.SkinFactoryComponent; 048import org.ametys.skinfactory.parameters.AbstractSkinParameter; 049import org.ametys.web.skin.SkinModel; 050import org.ametys.web.skin.SkinModelsManager; 051 052/** 053 * SAX ribbon definition for skin parameters 054 * 055 */ 056public class RibbonGenerator extends ServiceableGenerator 057{ 058 private SourceResolver _srcResolver; 059 private SkinModelsManager _modelsManager; 060 private SkinFactoryComponent _skinFactoryManager; 061 private DOMParser _domParser; 062 private XPathProcessor _xpathProcessor; 063 private SkinEditionHelper _skinHelper; 064 065 @Override 066 public void service(ServiceManager smanager) throws ServiceException 067 { 068 super.service(smanager); 069 _srcResolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE); 070 _skinHelper = (SkinEditionHelper) smanager.lookup(SkinEditionHelper.ROLE); 071 _modelsManager = (SkinModelsManager) smanager.lookup(SkinModelsManager.ROLE); 072 _skinFactoryManager = (SkinFactoryComponent) smanager.lookup(SkinFactoryComponent.ROLE); 073 _domParser = (DOMParser) smanager.lookup(DOMParser.ROLE); 074 _xpathProcessor = (XPathProcessor) smanager.lookup(XPathProcessor.ROLE); 075 } 076 077 @Override 078 public void generate() throws IOException, SAXException, ProcessingException 079 { 080 String skinName = parameters.getParameter("skinName", null); 081 082 String modelName = _skinHelper.getTempModel(skinName); 083 if (modelName == null) 084 { 085 throw new IllegalArgumentException("The current skin has no model"); 086 } 087 088 SkinModel model = _modelsManager.getModel(modelName); 089 if (model == null) 090 { 091 throw new IllegalArgumentException("The model '" + modelName + "' does not exit anymore"); 092 } 093 094 contentHandler.startDocument(); 095 XMLUtils.startElement(contentHandler, "cms"); 096 097 Source src = null; 098 try 099 { 100 Path ribbonFile = model.getPath().resolve("model/cms-ribbon.xml"); 101 if (Files.exists(ribbonFile)) 102 { 103 if (_isUpToDate(ribbonFile, modelName)) 104 { 105 SAXParser saxParser = null; 106 try (InputStream is = Files.newInputStream(ribbonFile)) 107 { 108 saxParser = (SAXParser) manager.lookup(SAXParser.ROLE); 109 saxParser.parse(new InputSource(is), new IgnoreRootHandler(contentHandler)); 110 } 111 catch (ServiceException e) 112 { 113 throw new ProcessingException("Unable to get a SAX parser", e); 114 } 115 finally 116 { 117 manager.release(saxParser); 118 } 119 } 120 else 121 { 122 src = _srcResolver.resolveURI("cocoon:/" + modelName + "/update/cms-ribbon.xml"); 123 ((SitemapSource) src).toSAX(new IgnoreRootHandler(contentHandler)); 124 125 // Update file 126 try (InputStream is = Files.newInputStream(ribbonFile)) 127 { 128 Files.copy(is, ribbonFile, StandardCopyOption.REPLACE_EXISTING); 129 } 130 } 131 } 132 else 133 { 134 src = _srcResolver.resolveURI("cocoon:/" + modelName + "/create/cms-ribbon.xml"); 135 ((SitemapSource) src).toSAX(new IgnoreRootHandler(contentHandler)); 136 137 // Create file 138 try (InputStream is = Files.newInputStream(ribbonFile)) 139 { 140 Files.copy(is, ribbonFile); 141 } 142 } 143 } 144 finally 145 { 146 if (src != null) 147 { 148 _srcResolver.release(src); 149 } 150 } 151 152 XMLUtils.startElement(contentHandler, "parameters"); 153 Map<String, AbstractSkinParameter> modelParameters = _skinFactoryManager.getModelParameters(modelName); 154 for (AbstractSkinParameter parameter : modelParameters.values()) 155 { 156 parameter.toSAX(contentHandler, modelName); 157 } 158 XMLUtils.endElement(contentHandler, "parameters"); 159 160 XMLUtils.endElement(contentHandler, "cms"); 161 contentHandler.endDocument(); 162 163 } 164 165 private boolean _isUpToDate (Path ribbonFile, String modelName) throws IOException, SAXException 166 { 167 Set<String> ribbonParams = new HashSet<>(); 168 169 try (InputStream is = Files.newInputStream(ribbonFile)) 170 { 171 Document document = _domParser.parseDocument(new InputSource(is)); 172 NodeList paramNodes = _xpathProcessor.selectNodeList(document, "/ribbon/tab/groups/group//parameter"); 173 174 for (int i = 0; i < paramNodes.getLength(); i++) 175 { 176 Element consistency = (Element) paramNodes.item(i); 177 String id = consistency.getAttribute("id"); 178 179 ribbonParams.add(id); 180 } 181 182 return SetUtils.isEqualSet(ribbonParams, _skinFactoryManager.getModelParameters(modelName).keySet()); 183 } 184 } 185}