001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Jean-Marc Orliaguet, Chalmers
011 *
012 * $Id$
013 */
014
015package org.nuxeo.theme.resources;
016
017import java.net.MalformedURLException;
018import java.net.URL;
019import java.util.ArrayList;
020import java.util.List;
021import java.util.Map;
022
023import net.sf.json.JSONArray;
024import net.sf.json.JSONObject;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.nuxeo.common.utils.URIUtils;
029import org.nuxeo.common.xmap.annotation.XNode;
030import org.nuxeo.common.xmap.annotation.XObject;
031import org.nuxeo.runtime.api.Framework;
032import org.nuxeo.theme.Manager;
033import org.nuxeo.theme.Utils;
034import org.nuxeo.theme.formats.styles.Style;
035import org.nuxeo.theme.presets.PresetManager;
036import org.nuxeo.theme.presets.PresetType;
037import org.nuxeo.theme.themes.ThemeException;
038import org.nuxeo.theme.themes.ThemeManager;
039import org.nuxeo.theme.types.Type;
040import org.nuxeo.theme.types.TypeFamily;
041import org.nuxeo.theme.types.TypeRegistry;
042import org.nuxeo.theme.uids.UidManager;
043
044@XObject("bank")
045public class ResourceBank implements Type {
046
047    private static final Log log = LogFactory.getLog(ResourceBank.class);
048
049    @XNode("@name")
050    public String name;
051
052    private String connectionUrl;
053
054    @XNode("@url")
055    public void setConnectionUrl(String connectionUrl) {
056        this.connectionUrl = Framework.expandVars(connectionUrl);
057    }
058
059    public ResourceBank() {
060    }
061
062    public String getConnectionUrl() {
063        return connectionUrl;
064    }
065
066    @Override
067    public String getTypeName() {
068        return name;
069    }
070
071    @Override
072    public TypeFamily getTypeFamily() {
073        return TypeFamily.RESOURCE_BANK;
074    }
075
076    public boolean checkStatus() {
077        String src = String.format("%s/status", connectionUrl);
078        byte[] status;
079        try {
080            status = Utils.fetchUrl(new URL(src));
081        } catch (MalformedURLException e) {
082            return false;
083        }
084        return status != null && "OK".equals(new String(status));
085    }
086
087    public byte[] getResourceContent(String collectionName, String typeName, String resourceId) {
088        String src = String.format("%s/%s/%s/%s", connectionUrl, URIUtils.quoteURIPathComponent(collectionName, true),
089                URIUtils.quoteURIPathComponent(typeName, true), URIUtils.quoteURIPathComponent(resourceId, true));
090        log.debug("Loading THEME " + typeName + " from: " + src);
091        try {
092            return Utils.fetchUrl(new URL(src));
093        } catch (MalformedURLException e) {
094            log.error("Could not retrieve RESOURCE: " + src + " from THEME BANK: " + name);
095        }
096        return null;
097    }
098
099    public List<ImageInfo> getImages() {
100        List<ImageInfo> images = new ArrayList<ImageInfo>();
101        String src = String.format("%s/json/images", connectionUrl);
102        String list = "";
103        try {
104            list = new String(Utils.fetchUrl(new URL(src)));
105        } catch (MalformedURLException e) {
106            log.error("Could not retrieve image list: " + src + " from THEME BANK: " + name);
107            return images;
108        }
109        for (Object object : JSONArray.fromObject(list)) {
110            Map<String, Object> image = JSONObject.fromObject(object);
111            images.add(new ImageInfo((String) image.get("name"), (String) image.get("collection")));
112        }
113        return images;
114    }
115
116    public List<String> getCollections() {
117        List<String> paths = new ArrayList<String>();
118        String src = String.format("%s/json/collections", connectionUrl);
119        String list = "";
120        try {
121            list = new String(Utils.fetchUrl(new URL(src)));
122        } catch (MalformedURLException e) {
123            log.error("Could not retrieve collection list: " + src + " from THEME BANK: " + name);
124            return paths;
125        }
126        for (Object path : JSONArray.fromObject(list)) {
127            paths.add((String) path);
128        }
129        return paths;
130    }
131
132    @SuppressWarnings("unchecked")
133    public List<SkinInfo> getSkins() {
134        List<SkinInfo> skins = new ArrayList<SkinInfo>();
135        String src = String.format("%s/json/skins", connectionUrl);
136        String list = "";
137        try {
138            list = new String(Utils.fetchUrl(new URL(src)));
139        } catch (MalformedURLException e) {
140            log.error("Could not retrieve skin list: " + src + " from THEME BANK: " + name);
141            return skins;
142        }
143        for (Object object : JSONArray.fromObject(list)) {
144            Map<String, Object> skin = JSONObject.fromObject(object);
145            skins.add(new SkinInfo((String) skin.get("name"), (String) skin.get("bank"),
146                    (String) skin.get("collection"), (String) skin.get("resource"), (String) skin.get("preview"),
147                    (Boolean) skin.get("base")));
148        }
149        return skins;
150    }
151
152    @SuppressWarnings("unchecked")
153    public List<StyleInfo> getStyles() {
154        List<StyleInfo> styles = new ArrayList<StyleInfo>();
155        String src = String.format("%s/json/styles", connectionUrl);
156        String list = "";
157        try {
158            list = new String(Utils.fetchUrl(new URL(src)));
159        } catch (MalformedURLException e) {
160            log.error("Could not retrieve the style list: " + src + " from THEME BANK: " + name);
161            return styles;
162        }
163        for (Object object : JSONArray.fromObject(list)) {
164            Map<String, Object> style = JSONObject.fromObject(object);
165            styles.add(new StyleInfo((String) style.get("name"), (String) style.get("bank"),
166                    (String) style.get("collection"), (String) style.get("resource"), (String) style.get("preview")));
167        }
168        return styles;
169    }
170
171    @SuppressWarnings("unchecked")
172    public List<PresetInfo> getPresets() {
173        List<PresetInfo> presets = new ArrayList<PresetInfo>();
174        String src = String.format("%s/json/presets", connectionUrl);
175        String list = "";
176        try {
177            list = new String(Utils.fetchUrl(new URL(src)));
178        } catch (MalformedURLException e) {
179            log.error("Could not retrieve the preset list: " + src + " from THEME BANK: " + name);
180            return presets;
181        }
182        for (Object object : JSONArray.fromObject(list)) {
183            Map<String, Object> preset = JSONObject.fromObject(object);
184            presets.add(new PresetInfo((String) preset.get("name"), (String) preset.get("bank"),
185                    (String) preset.get("collection"), (String) preset.get("category"), (String) preset.get("value")));
186        }
187        return presets;
188    }
189
190    public String getName() {
191        return name;
192    }
193
194    public void connect(String themeName) throws ThemeException {
195        loadRemotePresets();
196        loadRemoteStyles(themeName);
197    }
198
199    public void disconnect(String themeName) throws ThemeException {
200        unloadRemotePresets();
201        unloadRemoteStyles(themeName);
202    }
203
204    private void loadRemotePresets() throws ThemeException {
205        TypeRegistry typeRegistry = Manager.getTypeRegistry();
206        for (PresetInfo presetInfo : getPresets()) {
207            String name = presetInfo.getName();
208            String label = name;
209            String category = presetInfo.getCategory();
210            String group = String.format("%s %s", presetInfo.getCollection(), presetInfo.getCategory());
211            String value = presetInfo.getValue();
212
213            String typeName = presetInfo.getTypeName();
214
215            PresetType preset = PresetManager.getPresetByName(typeName);
216            if (preset == null) {
217                preset = new PresetType();
218                preset.setName(name);
219                preset.setGroup(group);
220                typeRegistry.register(preset);
221            }
222            preset.setLabel(label);
223            preset.setCategory(category);
224            preset.setValue(value);
225        }
226    }
227
228    private void loadRemoteStyles(String themeName) throws ThemeException {
229        ThemeManager themeManager = Manager.getThemeManager();
230        List<StyleInfo> bankStyles = getStyles();
231        for (StyleInfo styleInfo : bankStyles) {
232            String styleName = styleInfo.getName();
233            Style style = (Style) themeManager.getNamedObject(themeName, "style", styleName);
234
235            if (style == null) {
236                style = themeManager.createStyle();
237                style.setName(styleName);
238                style.setRemote(true);
239                themeManager.setNamedObject(themeName, "style", style);
240            }
241            String collectionName = styleInfo.getCollection();
242            String resourceId = styleInfo.getResource();
243            String cssSource = ResourceManager.getBankResource(name, collectionName, "style", resourceId);
244            style.setCollection(collectionName);
245            Utils.loadCss(style, cssSource, "*");
246        }
247    }
248
249    private void unloadRemotePresets() throws ThemeException {
250        TypeRegistry typeRegistry = Manager.getTypeRegistry();
251        for (PresetInfo presetInfo : getPresets()) {
252            String typeName = presetInfo.getTypeName();
253            PresetType preset = PresetManager.getPresetByName(typeName);
254            if (preset != null) {
255                typeRegistry.unregister(preset);
256            }
257        }
258    }
259
260    private void unloadRemoteStyles(String themeName) throws ThemeException {
261        ThemeManager themeManager = Manager.getThemeManager();
262        UidManager uidManager = Manager.getUidManager();
263        List<StyleInfo> bankStyles = getStyles();
264        for (StyleInfo styleInfo : bankStyles) {
265            String styleName = styleInfo.getName();
266            Style style = (Style) themeManager.getNamedObject(themeName, "style", styleName);
267            if (style == null || style.isCustomized()) {
268                continue;
269            }
270            themeManager.removeNamedObject(themeName, "style", styleName);
271            themeManager.deleteFormat(style);
272            uidManager.unregister(style);
273        }
274    }
275
276}