001/* 002 * Copyright 2010 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.plugins.skineditor.skin; 017 018import java.io.IOException; 019import java.nio.file.Files; 020import java.nio.file.Path; 021import java.util.HashMap; 022import java.util.HashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.function.Predicate; 027import java.util.stream.Collectors; 028 029import org.apache.avalon.framework.component.Component; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033 034import org.ametys.core.right.RightManager; 035import org.ametys.core.right.RightManager.RightResult; 036import org.ametys.core.ui.Callable; 037import org.ametys.core.user.CurrentUserProvider; 038import org.ametys.core.user.UserIdentity; 039import org.ametys.core.util.path.PathUtils; 040import org.ametys.plugins.skincommons.SkinEditionHelper; 041import org.ametys.plugins.skincommons.SkinLockManager; 042import org.ametys.runtime.i18n.I18nizableText; 043import org.ametys.web.repository.site.Site; 044import org.ametys.web.repository.site.SiteManager; 045import org.ametys.web.skin.Skin; 046import org.ametys.web.skin.SkinsManager; 047 048/** 049 * DAO for files and folders inside a skin directory 050 */ 051public class SkinDAO implements Serviceable, Component 052{ 053 /** The Avalon role */ 054 public static final String ROLE = SkinDAO.class.getName(); 055 056 /** Constant for skin editor tool id */ 057 public static final String SKIN_EDITOR_TOOL_ID = "uitool-skineditor"; 058 059 private static final String __WORK_MODE = "work"; 060 private static final String __PROD_MODE = "prod"; 061 062 /** The lock manager */ 063 protected SkinLockManager _lockManager; 064 /** The skin edition helper */ 065 protected SkinEditionHelper _skinHelper; 066 067 private SkinsManager _skinManager; 068 069 private CurrentUserProvider _userProvider; 070 071 private RightManager _rightManager; 072 073 private SiteManager _siteManager; 074 075 @Override 076 public void service(ServiceManager manager) throws ServiceException 077 { 078 _skinHelper = (SkinEditionHelper) manager.lookup(SkinEditionHelper.ROLE); 079 _lockManager = (SkinLockManager) manager.lookup(SkinLockManager.ROLE); 080 _skinManager = (SkinsManager) manager.lookup(SkinsManager.ROLE); 081 _userProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 082 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 083 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 084 } 085 086 /** 087 * Get the list of available and modifiable skins for a site 088 * @param siteName The site name 089 * @return the list of skins 090 */ 091 @Callable 092 public List<Object> getSkinsList(String siteName) 093 { 094 Site site = _siteManager.getSite(siteName); 095 String currentSkinId = site.getSkinId(); 096 097 Set<String> skins = new HashSet<>(); 098 099 UserIdentity user = _userProvider.getUser(); 100 if (_rightManager.hasRight(user, "Plugins_SkinEditor_EditAllSkin", "/cms") == RightResult.RIGHT_ALLOW) 101 { 102 skins.addAll(_skinManager.getSkins()); 103 } 104 else if (_rightManager.hasRight(user, "Plugins_SkinEditor_EditCurrentSkin", "/cms") == RightResult.RIGHT_ALLOW) 105 { 106 skins.add(currentSkinId); 107 } 108 109 return skins.stream() 110 .map(id -> _skinManager.getSkin(id)) 111 .filter(Skin::isModifiable) 112 .filter(Predicate.not(Skin::isAbstract)) 113 .map(s -> _skin2JsonObject(s, s.getId().equals(currentSkinId))) 114 .collect(Collectors.toList()); 115 } 116 117 private Map<String, Object> _skin2JsonObject (Skin skin, boolean current) 118 { 119 Map<String, Object> jsonObject = new HashMap<>(); 120 121 I18nizableText label = skin.getLabel(); 122 String icon = skin.getLargeImage(); 123 124 jsonObject.put("id", skin.getId()); 125 jsonObject.put("current", current); 126 jsonObject.put("label", label); 127 jsonObject.put("icon", icon); 128 129 return jsonObject; 130 } 131 132 /** 133 * Open a skin for editing 134 * @param skinId the skin id 135 * @param mode the edition mode 136 * @param unlinkModel True to remove any existing change 137 * @return the skin id 138 * @throws Exception if an error occurs during the skin opening process 139 */ 140 @Callable 141 public String openSkin(String skinId, String mode, boolean unlinkModel) throws Exception 142 { 143 Skin skin = _skinManager.getSkin(skinId); 144 if (!skin.isModifiable()) 145 { 146 throw new IllegalStateException("The skin '" + skinId + "' is not modifiable and thus cannot be opened in skin editor."); 147 } 148 149 Path tempDir = _skinHelper.getTempDirectory(skinId); 150 Path workDir = _skinHelper.getWorkDirectory(skinId); 151 Path skinDir = _skinHelper.getSkinDirectory(skinId); 152 153 if (unlinkModel) 154 { 155 unlinkModel (skinDir); 156 unlinkModel(workDir); 157 unlinkModel(tempDir); 158 } 159 160 if (__PROD_MODE.equals(mode) || __WORK_MODE.equals(mode)) 161 { 162 // Delete temp directory if exists 163 if (Files.exists(tempDir)) 164 { 165 _skinHelper.deleteQuicklyDirectory(tempDir); 166 } 167 168 if (__PROD_MODE.equals(mode)) 169 { 170 // Delete work directory if exists 171 if (Files.exists(workDir)) 172 { 173 _skinHelper.deleteQuicklyDirectory(workDir); 174 } 175 176 // Copy from skin 177 PathUtils.copyDirectory(skinDir, workDir); 178 } 179 180 // Copy work in temp 181 PathUtils.copyDirectory(workDir, tempDir); 182 183 // Create .lock file 184 _lockManager.updateLockFile(tempDir, SKIN_EDITOR_TOOL_ID); 185 } 186 else 187 { 188 // Update .lock file 189 _lockManager.updateLockFile(tempDir, SKIN_EDITOR_TOOL_ID); 190 } 191 192 return skinId; 193 } 194 195 /** 196 * Unlink model 197 * @param skinDir The skin directory 198 * @throws IOException If an error occurred 199 */ 200 protected void unlinkModel (Path skinDir) throws IOException 201 { 202 Path modelFile = skinDir.resolve("model.xml"); 203 Path bakFile = skinDir.resolve("model.xml.bak"); 204 205 if (Files.exists(bakFile)) 206 { 207 // Delete old bak file if exists 208 PathUtils.deleteQuietly(bakFile); 209 } 210 211 if (Files.exists(modelFile)) 212 { 213 Files.move(modelFile, bakFile); 214 } 215 } 216}