001/*
002 * (C) Copyright 2006-2008 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 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.webengine.model.impl;
023
024import java.io.File;
025import java.util.ArrayList;
026import java.util.HashSet;
027import java.util.List;
028import java.util.Set;
029
030import org.nuxeo.common.xmap.annotation.XNode;
031import org.nuxeo.common.xmap.annotation.XNodeList;
032import org.nuxeo.common.xmap.annotation.XObject;
033import org.nuxeo.ecm.webengine.ResourceBinding;
034import org.nuxeo.ecm.webengine.WebEngine;
035import org.nuxeo.ecm.webengine.app.WebEngineModule;
036import org.nuxeo.ecm.webengine.model.LinkDescriptor;
037import org.nuxeo.ecm.webengine.model.Module;
038import org.nuxeo.ecm.webengine.model.WebContext;
039import org.nuxeo.ecm.webengine.model.exceptions.WebResourceNotFoundException;
040
041import com.sun.jersey.server.impl.inject.ServerInjectableProviderContext;
042
043/**
044 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
045 */
046@XObject("module")
047public class ModuleConfiguration {
048
049    /**
050     * A web module may have multiple roots
051     *
052     * @deprecated you should use new module definition - through {@link WebEngineModule}
053     */
054    @Deprecated
055    @XNode("@path")
056    public String path;
057
058    /**
059     * @deprecated you should use new module definition - through {@link WebEngineModule}
060     */
061    @Deprecated
062    @XNode("@root-type")
063    public String rootType;
064
065    /**
066     * Paths of root resources in the module. This is replacing the deprecated root-type.
067     */
068    public Class<?>[] roots;
069
070    @XNode("@extends")
071    public String base;
072
073    @XNode("@name")
074    public String name;
075
076    /**
077     * Use module links instead. If a module doesn't declare a module item it will be headless by default. Still used
078     * for compatibility mode - for those modules not yet using moduleItems.
079     */
080    @Deprecated
081    @XNode("@headless")
082    public boolean isHeadless;
083
084    /**
085     * A list of entry points into the module - to be shown in the main webengine page. This is optional and may be
086     * ignored if your don't want to provide shortcuts to your module entry points.
087     */
088    @XNodeList(value = "shortcuts/shortcut", type = ArrayList.class, componentType = ModuleShortcut.class, nullByDefault = true)
089    public List<ModuleShortcut> moduleShortcuts;
090
091    /**
092     * Web Types explicitly declared. If null no web types were explicitly declared and old type loading method from the
093     * generated web-types file should be used.
094     */
095    public Class<?>[] types;
096
097    /**
098     * The module directory. Must be set by the client before registering the descriptor.
099     */
100    @XNode("home")
101    public File directory;
102
103    @XNodeList(value = "fragments/directory", type = ArrayList.class, componentType = File.class, nullByDefault = false)
104    public List<File> fragmentDirectories = new ArrayList<File>();
105
106    /**
107     * The module configuration file (this will be set by the module config parser)
108     */
109    public File file;
110
111    @XNodeList(value = "nature", type = HashSet.class, componentType = String.class, nullByDefault = true)
112    public Set<String> natures;
113
114    @XNodeList(value = "links/link", type = ArrayList.class, componentType = LinkDescriptor.class, nullByDefault = true)
115    public List<LinkDescriptor> links;
116
117    /**
118     * @deprecated resources are deprecated - you should use a jax-rs application to declare more resources.
119     */
120    @Deprecated
121    @XNodeList(value = "resources/resource", type = ArrayList.class, componentType = ResourceBinding.class, nullByDefault = true)
122    public List<ResourceBinding> resources;
123
124    @XNode("templateFileExt")
125    public String templateFileExt = "ftl";
126
127    @XNodeList(value = "media-types/media-type", type = MediaTypeRef[].class, componentType = MediaTypeRef.class, nullByDefault = true)
128    public MediaTypeRef[] mediatTypeRefs;
129
130    public WebEngine engine;
131
132    // volatile for double-checked locking
133    private volatile ModuleImpl module;
134
135    public boolean allowHostOverride;
136
137    public ModuleConfiguration() {
138    }
139
140    public ModuleConfiguration(WebEngine engine) {
141        this.engine = engine;
142    }
143
144    public WebEngine getEngine() {
145        return engine;
146    }
147
148    public void setEngine(WebEngine engine) {
149        this.engine = engine;
150    }
151
152    public String getName() {
153        return name;
154    }
155
156    public List<ModuleShortcut> getShortcuts() {
157        return moduleShortcuts;
158    }
159
160    public List<LinkDescriptor> getLinks() {
161        return links;
162    }
163
164    public File getDirectory() {
165        return directory;
166    }
167
168    public String getBase() {
169        return base;
170    }
171
172    public Module get(WebContext context) {
173        ModuleImpl mod = module;
174        if (mod == null) {
175            synchronized (this) {
176                mod = module;
177                if (mod == null) {
178                    Module superModule = null;
179                    if (base != null) { // make sure super modules are resolved
180                        ModuleConfiguration superM = engine.getModuleManager().getModule(base);
181                        if (superM == null) {
182                            throw new WebResourceNotFoundException("The module '" + name
183                                    + "' cannot be loaded since its super module '" + base + "' cannot be found");
184                        }
185                        // force super module loading
186                        superModule = superM.get(context);
187                    }
188                    ServerInjectableProviderContext sic = context.getServerInjectableProviderContext();
189                    mod = new ModuleImpl(engine, (ModuleImpl) superModule, this, sic);
190                    if (sic != null) {
191                        // cache the module only if it has a ServerInjectableProviderContext
192                        module = mod;
193                    }
194                }
195            }
196        }
197        return mod;
198    }
199
200    public void flushCache() {
201        synchronized (this) {
202            if (module == null) {
203                return;
204            }
205            module.flushCache();
206            module = null;
207        }
208    }
209
210    public boolean isLoaded() {
211        return module != null;
212    }
213
214    public boolean isHeadless() {
215        return isHeadless;
216    }
217
218}