001/*
002 * (C) Copyright 2006-2008 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 *     bstefanescu
016 */
017package org.nuxeo.ecm.webengine.model.impl;
018
019import java.io.File;
020import java.io.IOException;
021import java.util.List;
022
023import org.apache.commons.logging.Log;
024import org.apache.commons.logging.LogFactory;
025import org.nuxeo.common.utils.FileUtils;
026import org.nuxeo.ecm.webengine.loader.ClassProxy;
027import org.nuxeo.ecm.webengine.loader.StaticClassProxy;
028import org.nuxeo.ecm.webengine.loader.WebLoader;
029import org.nuxeo.ecm.webengine.model.WebAdapter;
030import org.nuxeo.ecm.webengine.model.WebObject;
031
032/**
033 * A type loader which is loading types from META-INF/web-types file. This loader is also checking the web module
034 * nature. If the project has for example a Groovy nature it will call at end the {@link GroovyTypeLoader}
035 *
036 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
037 */
038public class DefaultTypeLoader {
039
040    public static final Log log = LogFactory.getLog(DefaultTypeLoader.class);
041
042    public static final String WEB_TYPES_FILE = "META-INF/web-types";
043
044    protected GroovyTypeLoader gLoader;
045
046    protected final ModuleImpl module;
047
048    protected final WebLoader loader;
049
050    protected final TypeRegistry typeReg;
051
052    protected final File root;
053
054    public DefaultTypeLoader(ModuleImpl module, TypeRegistry typeReg, File root) {
055        this.typeReg = typeReg;
056        this.root = root;
057        this.module = module;
058        loader = module.getEngine().getWebLoader();
059        if (module.hasNature("groovy")) {
060            gLoader = new GroovyTypeLoader(module.getEngine(), typeReg, root);
061        }
062    }
063
064    public ModuleImpl getModule() {
065        return module;
066    }
067
068    public void load() {
069        if (module.configuration.types != null) {
070            loadTypes(module.configuration.types);
071        } else {
072            File file = new File(module.getRoot(), WEB_TYPES_FILE);
073            if (file.isFile()) {
074                try {
075                    loadTypesFile(file);
076                } catch (IOException | ClassNotFoundException e) {
077                    log.error("Failed to load web types from file " + WEB_TYPES_FILE, e);
078                }
079            }
080            if (gLoader != null) {
081                gLoader.load();
082            }
083        }
084    }
085
086    public void flushCache() {
087        if (gLoader != null) {
088            gLoader.flushCache();
089        }
090    }
091
092    protected void loadTypes(Class<?>[] types) {
093        for (Class<?> type : types) {
094            TypeDescriptor td = loadType(type);
095            if (td != null) {
096                typeReg.registerTypeDescriptor(td);
097            }
098        }
099    }
100
101    /**
102     * Old method to load types from a web-types file generated at build time
103     */
104    protected void loadTypesFile(File file) throws IOException, ClassNotFoundException {
105        List<String> lines = FileUtils.readLines(file);
106        for (String line : lines) {
107            line = line.trim();
108            if (line.length() == 0 || line.startsWith("#")) {
109                continue;
110            }
111            int p = line.indexOf('|');
112            if (p > -1) {
113                line = line.substring(0, p);
114            }
115            TypeDescriptor td = loadType(line);
116            if (td != null) {
117                typeReg.registerTypeDescriptor(td);
118            }
119        }
120    }
121
122    protected TypeDescriptor loadType(String className) throws ClassNotFoundException {
123        return loadType(loader.getClassProxy(className));
124    }
125
126    protected TypeDescriptor loadType(Class<?> clazz) {
127        return loadType(new StaticClassProxy(clazz));
128    }
129
130    protected TypeDescriptor loadType(ClassProxy clazz) {
131        WebObject type = clazz.get().getAnnotation(WebObject.class);
132        if (type != null) {
133            return TypeDescriptor.fromAnnotation(clazz, type);
134        }
135        WebAdapter ws = clazz.get().getAnnotation(WebAdapter.class);
136        if (ws != null) {
137            return AdapterDescriptor.fromAnnotation(clazz, ws);
138        }
139        return null;
140    }
141
142}