Package org.apache.marmotta.platform.core.services.modules

Source Code of org.apache.marmotta.platform.core.services.modules.MarmottaResourceServiceImpl

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.marmotta.platform.core.services.modules;

import com.google.common.io.ByteStreams;
import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.MimeUtil2;
import org.apache.marmotta.platform.core.api.config.ConfigurationService;
import org.apache.marmotta.platform.core.api.modules.MarmottaResourceService;
import org.apache.marmotta.platform.core.api.modules.ModuleService;
import org.apache.marmotta.platform.core.api.modules.ResourceEntry;
import org.apache.marmotta.platform.core.events.SystemStartupEvent;
import org.apache.marmotta.platform.core.model.module.ModuleConfiguration;
import org.apache.marmotta.platform.core.qualifiers.cache.MarmottaCache;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.slf4j.Logger;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;

import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* A service for resolving and accessing resources contained in the Apache Marmotta modules. The resource service takes care
* of retrieving, caching and refreshing resources from the appropriate locations.
* <p/>
* Note that the resource service is not to be confused with the RDF resources maintained by the server. It is
* purely meant to retrieve static non-Java resources contained in the modules and web application.
*
* User: sschaffe
*/
@ApplicationScoped
public class MarmottaResourceServiceImpl implements MarmottaResourceService {

    @Inject
    private Logger log;

    @Inject
    private ConfigurationService configurationService;


    @Inject
    private ModuleService moduleService;


    @Inject @MarmottaCache("resource-cache")
    private Ehcache resourceCache;

    /**
     * Used for detecting the mime type of resources contained in KiWi modules
     */
    private MimeUtil2 mimeUtil;


    private Map<String,String> resourceMap;


    @PostConstruct
    public void initialise() {
        // find all kiwi-module.properties and check whether they contain a baseurl property to map module web
        // resources to a certain path prefix; if yes, store the prefix and jar URL in the map for lookup and
        // resource resolving by the filter
        this.resourceMap = new HashMap<String, String>();


        for(String module : moduleService.listModules()) {
            ModuleConfiguration config = moduleService.getModuleConfiguration(module);

            if(config.getConfiguration().containsKey("baseurl")) {
                String path = config.getConfiguration().getString("baseurl");
                resourceMap.put(path.startsWith("/")?path:"/"+path,moduleService.getModuleJar(module).toString());
            }
        }



        // detect the mime type of resources
        this.mimeUtil = new MimeUtil2();
        this.mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.ExtensionMimeDetector");
    }


    /**
     * Makes sure the service is initialised on system startup
     *
     * @param event
     */
    public void systemStartup(@Observes SystemStartupEvent event) {

    }


    /**
     * Return the resource identified by the relative URL passed as argument. The passed argument is relative
     * to the web application root of this web application.
     *
     * @param relativeURL a URL relative to the web application root of this web application
     * @return the resource identified by the relative URL, or null if it does not exist
     */
    @Override
    public ResourceEntry getResource(String relativeURL) {
        ResourceEntry data = null;

        // check the request path prefix whether it matches with one of the prefixes in the prefix mapping; if yes,
        // lookup the resource as follows:
        // 1. look in the cache using the path of the request url as cache key
        // 2. if not found: look in the jar file by mapping the resource to the correct jar file and retrieving it
        //    from the "web" folder contained therein
        // 3. if not found: proceed with the chain by calling chain.doFilter()
        // TODO: (FIXME) data_cache.get(path) might return null some times even though path is in cache
        if(isCached(relativeURL)) {
            data = getFromCache(relativeURL);
        } else {

            try {
                URL jarUrl = resolveResource(relativeURL);

                if(jarUrl != null) {
                    try {
                        byte[] bytes = ByteStreams.toByteArray(jarUrl.openStream());

                        data = new ResourceEntry(jarUrl,bytes,bytes.length,getMimeType(jarUrl));

                        log.debug("retrieved resource {} (mime type {}, length {} bytes)", jarUrl.toString(), data.getContentType(),data.getLength());
                    } catch (NullPointerException e) {
                        // This happens if a directory is accessed in the jar-file.
                        data = null;
                    }
                    putInCache(relativeURL,data);
                } else {
                    putInCache(relativeURL,null);

                    log.debug("resource {} not found in any module",relativeURL);
                }

            } catch(IOException ex) {
                log.debug("error while trying to retrieve resource {}: {}",relativeURL,ex.getMessage());
            }
        }
        return data;

    }

    /**
     * Return the file system URL of the resource identified by the relative HTTP URL passed as argument.
     * he passed argument is relative to the web application root of this web application.
     *
     * @param relativeURL a URL relative to the web application root of this web application
     * @return the file system URL of the resource, regardless whether it actually exists or not
     */
    @Override
    public URL resolveResource(String relativeURL) {

        // we take the first match from the resource map ...
        for(String key : resourceMap.keySet()) {
            if(relativeURL.startsWith(key)) {

                // the name of the resource inside the jar file
                String entryPath    = relativeURL.substring(key.length());
                // map "/" to /index.html
                if(entryPath.endsWith("/") || entryPath.equals("")) {
                    entryPath += "index.html";
                }

                // the base URL of the jar file in the file system
                String jarUrlBase   = resourceMap.get(key);

                // the JAR URL of the resource inside the jar file
                String jarUrlEntry;

                if(jarUrlBase.endsWith(".jar")) {
                    jarUrlEntry = "jar:" + jarUrlBase + "!/web" + ( entryPath.startsWith("/") ? entryPath : "/" + entryPath);
                } else {
                    jarUrlEntry = jarUrlBase + (jarUrlBase.endsWith("/")?"":"/") + "web" + ( entryPath.startsWith("/") ? entryPath : "/" + entryPath);
                }


                try {
                    return new URL(jarUrlEntry);

                } catch(IOException ex) {
                    log.debug("error while trying to retrieve resource {}: {}",jarUrlEntry,ex.getMessage());

                }
            }
        }
        return null;
    }





    private boolean isCacheEnabled() {
        return configurationService.getBooleanConfiguration("resources.servercache.enabled", false);
    }


    private boolean isCached(String key) {
        return isCacheEnabled() && resourceCache.isKeyInCache(key) && resourceCache.get(key) != null;
    }

    private ResourceEntry getFromCache(String key) {
        if (isCacheEnabled())
            return (ResourceEntry) resourceCache.get(key).getObjectValue();
        else
            return null;
    }

    // Store in the cache
    private void putInCache(String key, ResourceEntry data) {
        if(isCacheEnabled()) {
            resourceCache.put(new Element(key,data));
        }
    }


    private String getMimeType(URL resource) {

        @SuppressWarnings("unchecked")
        Collection<MimeType> types = mimeUtil.getMimeTypes(resource);

        if(types.size() > 0) {
            MimeType t = types.iterator().next();
            return t.toString();
        } else
            return null;

    }


}
TOP

Related Classes of org.apache.marmotta.platform.core.services.modules.MarmottaResourceServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.