package ameba.mvc.assets;

import ameba.util.IOUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceModel;

import javax.ws.rs.ConstrainedTo;
import javax.ws.rs.RuntimeType;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * @author: ICode
 * @since: 13-8-17 下午2:55
 */
@ConstrainedTo(RuntimeType.SERVER)
public class AssetsFeature implements Feature {

    private static final Map<String, String[]> assetsMap = Maps.newLinkedHashMap();

    public static Map<String, String[]> getAssetMap(Configuration configuration) {
        Map<String, String[]> assetsMap = Maps.newLinkedHashMap();
        for (String key : configuration.getPropertyNames()) {
            if (key.startsWith("resource.assets.") || key.equals("resource.assets")) {
                String routePath = key.replaceFirst("^resource\\.assets", "");
                if (routePath.startsWith(".")) {
                    routePath = routePath.substring(1);
                } else if (StringUtils.isBlank(routePath)) {
                    routePath = "assets";
                }

                if (routePath.endsWith("/")) {
                    routePath = routePath.substring(0, routePath.lastIndexOf("/"));
                }

                String value = (String) configuration.getProperty(key);
                String[] uris = value.split(",");
                List<String> uriList = Lists.newArrayList();
                for (String uri : uris) {
                    uriList.add(uri.startsWith("/") ? uri : "/" + uri);
                }
                if (StringUtils.isNotBlank(value))
                    assetsMap.put(routePath, uriList.toArray(uris));
            }
        }
        return assetsMap;
    }

    @Override
    public boolean configure(FeatureContext context) {

        Configuration configuration = context.getConfiguration();

        assetsMap.putAll(getAssetMap(configuration));

        context.register(new ModelProcessor() {
            @Override
            public ResourceModel processResourceModel(ResourceModel resourceModel, Configuration configuration) {
                ResourceModel.Builder resourceModelBuilder = new ResourceModel.Builder(resourceModel, false);

                for (String routePath : assetsMap.keySet()) {
                    Resource.Builder resourceBuilder = Resource.builder(AssetsResource.class);
                    resourceBuilder.path(routePath);
                    Resource resource = resourceBuilder.build();
                    resourceModelBuilder.addResource(resource);
                }

                return resourceModelBuilder.build();
            }

            @Override
            public ResourceModel processSubResource(ResourceModel subResourceModel, Configuration configuration) {
                return subResourceModel;
            }
        });
        return true;
    }

    public static Map<String, String[]> getAssetsMap() {
        return Maps.newHashMap(assetsMap);
    }

    public static InputStream findAsset(String name, String file) {
        InputStream in = null;

        if (name.startsWith("/")) {
            name = name.substring(1);
        }

        if (name.endsWith("/")) {
            name = name.substring(0, name.lastIndexOf("/"));
        }

        String[] dirs = assetsMap.get(name);
        if (dirs != null) {
            for (String dir : dirs) {
                if (!dir.endsWith("/") && !file.startsWith("/")) {
                    dir = dir + "/";
                }
                in = IOUtils.getResourceAsStream(dir + file);
                if (in != null) {
                    break;
                }
            }
        }
        return in;
    }
}

@@ -126,16 +126,60 @@
 t.Maps;%0A
+import org.apache.commons.lang3.ArrayUtils;%0A
 import o
@@ -1973,16 +1973,18 @@
 (value))
+ %7B
 %0A       
@@ -2000,105 +2000,1204 @@
     
-assetsMap.put(routePath, uriList.toArray(uris));%0A            %7D%0A        %7D%0A        return assetsMap
+String%5B%5D _uris = assetsMap.get(routePath);%0A                    if (_uris == null) %7B%0A                        assetsMap.put(routePath, uriList.toArray(uris));%0A                    %7D else %7B%0A                        assetsMap.put(routePath, ArrayUtils.addAll(_uris, uriList.toArray(uris)));%0A                    %7D%0A                %7D%0A%0A            %7D%0A        %7D%0A        return assetsMap;%0A    %7D%0A%0A    public static Map%3CString, String%5B%5D%3E getAssetsMap() %7B%0A        return Maps.newHashMap(assetsMap);%0A    %7D%0A%0A    public static InputStream findAsset(String name, String file) %7B%0A        InputStream in = null;%0A%0A        if (name.startsWith(%22/%22)) %7B%0A            name = name.substring(1);%0A        %7D%0A%0A        if (name.endsWith(%22/%22)) %7B%0A            name = name.substring(0, name.lastIndexOf(%22/%22));%0A        %7D%0A%0A        String%5B%5D dirs = assetsMap.get(name);%0A        if (dirs != null) %7B%0A            for (String dir : dirs) %7B%0A                if (!dir.endsWith(%22/%22) && !file.startsWith(%22/%22)) %7B%0A                    dir = dir + %22/%22;%0A                %7D%0A                in = IOUtils.getResourceAsStream(dir + file);%0A                if (in != null) %7B%0A                    break;%0A                %7D%0A            %7D%0A        %7D%0A        return in
 ;%0A  
@@ -4348,829 +4348,7 @@
    %7D
-%0A%0A    public static Map%3CString, String%5B%5D%3E getAssetsMap() %7B%0A        return Maps.newHashMap(assetsMap);%0A    %7D%0A%0A    public static InputStream findAsset(String name, String file) %7B%0A        InputStream in = null;%0A%0A        if (name.startsWith(%22/%22)) %7B%0A            name = name.substring(1);%0A        %7D%0A%0A        if (name.endsWith(%22/%22)) %7B%0A            name = name.substring(0, name.lastIndexOf(%22/%22));%0A        %7D%0A%0A        String%5B%5D dirs = assetsMap.get(name);%0A        if (dirs != null) %7B%0A            for (String dir : dirs) %7B%0A                if (!dir.endsWith(%22/%22) && !file.startsWith(%22/%22)) %7B%0A                    dir = dir + %22/%22;%0A                %7D%0A                in = IOUtils.getResourceAsStream(dir + file);%0A                if (in != null) %7B%0A                    break;%0A                %7D%0A            %7D%0A        %7D%0A        return in;%0A    %7D
 %0A%7D%0A

增强静态资源特性,事其兼容多模块下的配置