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