001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.theme.resources;
021
022import java.io.ByteArrayOutputStream;
023import java.io.File;
024import java.io.IOException;
025import java.io.InputStream;
026import java.net.URL;
027import java.util.ArrayList;
028import java.util.Arrays;
029import java.util.List;
030import java.util.Map;
031
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.common.utils.FileUtils;
035import org.nuxeo.common.utils.ZipUtils;
036import org.nuxeo.theme.themes.ThemeManager;
037import org.yaml.snakeyaml.Yaml;
038
039public class BankManager {
040    private static final Log log = LogFactory.getLog(BankManager.class);
041
042    private static File BANKS_DIR;
043
044    private static List<String> FOLDER_NAMES = Arrays.asList("style", "preset", "image");
045
046    private static final String CUSTOM_COLLECTION_DIRNAME = "custom";
047
048    public static File getBanksDir() {
049        if (BANKS_DIR == null) {
050            BANKS_DIR = new File(ThemeManager.getThemeDir(), "banks");
051            BANKS_DIR.mkdirs();
052        }
053        return BANKS_DIR;
054    }
055
056    public static File getFile(String path) throws IOException {
057        if (!BankUtils.checkFilePath(path)) {
058            throw new IOException("File path not allowed: " + path);
059        }
060        return new File(getBanksDir(), path);
061    }
062
063    public static File getBankDir(String bankName) throws IOException {
064        return getFile(bankName);
065    }
066
067    public static List<String> getBankNames() {
068        List<String> names = new ArrayList<String>();
069        File[] sortedFiles = BankUtils.listFilesSorted(getBanksDir());
070        if (sortedFiles != null) {
071            for (File bankFile : sortedFiles) {
072                names.add(bankFile.getName());
073            }
074        }
075        return names;
076    }
077
078    public static void setupBanks() {
079        for (String bankName : getBankNames()) {
080            try {
081                setupBankStructure(bankName);
082            } catch (IOException e) {
083                log.error("Could not create bank structure: " + bankName, e);
084            }
085        }
086    }
087
088    public static void setupBankStructure(String bankName) throws IOException {
089        for (String folderName : FOLDER_NAMES) {
090            String folderPath = String.format("/%s/%s", CUSTOM_COLLECTION_DIRNAME, folderName);
091            createFolder(bankName, folderPath);
092        }
093    }
094
095    /*
096     * Collections
097     */
098    public static List<String> getCollections(String bank) throws IOException {
099        List<String> names = new ArrayList<String>();
100        File file = getBankDir(bank);
101        if (file.exists()) {
102            for (File collectionFile : BankUtils.listFilesSorted(file)) {
103                names.add(collectionFile.getName());
104            }
105        }
106        return names;
107    }
108
109    public static List<String> getItemsInCollection(String bank, String collection, String typeName) throws IOException {
110        List<String> names = new ArrayList<String>();
111        String path = String.format("%s/%s/%s", bank, collection, typeName);
112        File file = getFile(path);
113        if (file.exists()) {
114            for (File item : BankUtils.listFilesSorted(file)) {
115                String itemName = item.getName();
116                if (typeName.equals("style") && !itemName.endsWith(".css")) {
117                    continue;
118                }
119                names.add(itemName);
120            }
121        }
122        return names;
123    }
124
125    public static File getStyleFile(String bank, String collection, String resource) throws IOException {
126        String path = String.format("%s/%s/style/%s", bank, collection, resource);
127        return getFile(path);
128    }
129
130    public static File getImageFile(String bank, String collection, String resource) throws IOException {
131        String path = String.format("%s/%s/image/%s", bank, collection, resource);
132        return getFile(path);
133    }
134
135    public static File getBankLogoFile(String bank) throws IOException {
136        String path = String.format("%s/logo.png", bank);
137        return getFile(path);
138    }
139
140    @SuppressWarnings("rawtypes")
141    public static File getStylePreviewFile(String bank, String collection, String resource) throws IOException {
142        Map<String, Object> info = getInfo(bank, collection, "style");
143
144        if (!info.containsKey(resource)) {
145            throw new IOException("Style preview not found: " + resource);
146        }
147
148        Map value = (Map) info.get(resource);
149        if (!value.containsKey("preview")) {
150            throw new IOException("Style preview not found: " + resource);
151        }
152
153        String preview = (String) value.get("preview");
154        String path = String.format("%s/%s/style/%s", bank, collection, preview);
155
156        File file = getFile(path);
157        if (!file.exists()) {
158            throw new IOException("Style preview not found: " + resource);
159        }
160        return file;
161    }
162
163    public static File getInfoFile(String bank, String collection, String typeName) throws IOException {
164        String path = String.format("%s/%s/%s/info.txt", bank, collection, typeName);
165        return getFile(path);
166    }
167
168    @SuppressWarnings("unchecked")
169    public static Map<String, Object> getInfo(String bank, String collection, String typeName) throws IOException {
170        File file = getInfoFile(bank, collection, typeName);
171        Yaml yaml = new Yaml();
172        String content = "";
173        if (file.exists()) {
174            content = BankUtils.getFileContent(file);
175        }
176        return (Map<String, Object>) yaml.load(content);
177    }
178
179    /*
180     * I/O
181     */
182    public static void importBankData(String bankName, String collection, URL srcFileUrl) throws IOException {
183        if (CUSTOM_COLLECTION_DIRNAME.equals(collection)) {
184            throw new IOException("Bank collection name not allowed: " + CUSTOM_COLLECTION_DIRNAME);
185        }
186        InputStream in = null;
187        in = srcFileUrl.openStream();
188        String path = String.format("%s/%s", bankName, collection);
189        File folder = getFile(path);
190        if (folder.exists()) {
191            FileUtils.deleteTree(folder);
192        }
193        folder.mkdir();
194        ZipUtils.unzip(in, folder);
195        if (in != null) {
196            in.close();
197        }
198    }
199
200    public static byte[] exportBankData(String bankName, String collection) throws IOException {
201        ByteArrayOutputStream out = new ByteArrayOutputStream();
202        String path = String.format("%s/%s", bankName, collection);
203        File folder = getFile(path);
204        if (!folder.exists()) {
205            throw new IOException("Folder not found: " + path);
206        }
207        ZipUtils.zip(folder.listFiles(), out, null);
208        out.close();
209        return out.toByteArray();
210    }
211
212    public static File createFolder(String path, String folderName) throws IOException {
213        String folderPath = String.format("%s/%s", path, folderName);
214        File file = getFile(folderPath);
215        if (!file.exists()) {
216            file.mkdirs();
217        }
218        return file;
219    }
220
221    public static File createFile(String path, String fileName, String content) throws IOException {
222        return createFile(path, fileName, content.getBytes());
223    }
224
225    public static File createFile(String path, String fileName, byte[] data) throws IOException {
226        File file = new File(getFile(path), fileName);
227        file.createNewFile();
228        FileUtils.writeFile(file, data);
229        return file;
230    }
231
232    public static void editFile(String path, String fileName, String content) throws IOException {
233        File file = new File(getFile(path), fileName);
234        FileUtils.writeFile(file, content);
235    }
236}