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