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