Package juzu.impl.plugin.asset

Source Code of juzu.impl.plugin.asset.AssetService

/*
* Copyright 2013 eXo Platform SAS
*
* Licensed 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 juzu.impl.plugin.asset;

import juzu.PropertyType;
import juzu.Response;
import juzu.asset.AssetLocation;
import juzu.impl.asset.AssetDeployment;
import juzu.impl.common.Name;
import juzu.impl.common.Tools;
import juzu.impl.plugin.ServiceContext;
import juzu.impl.plugin.ServiceDescriptor;
import juzu.impl.asset.AssetManager;
import juzu.impl.asset.AssetMetaData;
import juzu.impl.plugin.application.ApplicationService;
import juzu.impl.request.Request;
import juzu.impl.request.RequestFilter;
import juzu.impl.common.JSON;
import juzu.impl.request.Stage;
import juzu.plugin.asset.Assets;
import juzu.io.Chunk;
import juzu.io.Stream;
import juzu.impl.io.StreamableDecorator;
import juzu.request.Phase;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class AssetService extends ApplicationService implements RequestFilter<Stage.Unmarshalling> {

  /** . */
  private LinkedHashMap<String, Chunk.Property<String>> assets;

  /** . */
  private AssetDescriptor descriptor;

  /** . */
  private ServiceContext context;

  /** The path to the assets dir. */
  private String assetsPath;

  /** . */
  @Inject
  AssetManager assetManager;

  public AssetService() {
    super("asset");
  }

  public AssetManager getAssetManager() {
    return assetManager;
  }

  /**
   * Returns the plugin assets path.
   *
   * @return the assets path
   */
  public String getAssetsPath() {
    return assetsPath;
  }

  @Override
  public ServiceDescriptor init(ServiceContext context) throws Exception {
    JSON config = context.getConfig();
    String assetsPath;
    List<AssetMetaData> assets;
    if (config != null) {
      String packageName = config.getString("package");
      assets = load(packageName, config.getJSON("assets"));
      assetsPath = "/" + Name.parse(application.getPackageName()).append(packageName).toString().replace('.', '/') + "/";
    } else {
      assets = Collections.emptyList();
      assetsPath = null;
    }
    this.descriptor = new AssetDescriptor(assets);
    this.context = context;
    this.assetsPath = assetsPath;
    return descriptor;
  }

  private List<AssetMetaData> load(
      String packageName,
      JSON assets) throws Exception {
    List<AssetMetaData> abc = Collections.emptyList();
    if (assets != null && assets.getSize() > 0) {
      abc = new ArrayList<AssetMetaData>();
      for (String id : assets.names()) {
        JSON asset = assets.getJSON(id);
        AssetLocation location = AssetLocation.safeValueOf(asset.getString("location"));

        //
        if (location == null) {
          location = AssetLocation.APPLICATION;
        }

        //
        String type = asset.getString("type");

        //
        String value = asset.getString("value");
        if (location == AssetLocation.APPLICATION && !value.startsWith("/")) {
          value = "/" + application.getPackageName().replace('.', '/') + "/" + packageName.replace('.', '/') + "/" + value;
        }
        String minified = asset.getString("minified");
        if (location == AssetLocation.APPLICATION && minified != null && !minified.startsWith("/")) {
          minified = "/" + application.getPackageName().replace('.', '/') + "/" + packageName.replace('.', '/') + "/" + minified;
        }
        Boolean header = asset.getBoolean("header");

        //
        Integer maxAge = asset.getInteger("max-age");

        //
        AssetMetaData descriptor = new AssetMetaData(
          id,
          type,
          location,
          value,
          header,
          minified,
          maxAge,
          asset.getArray("depends", String.class)
        );
        abc.add(descriptor);
      }
    }
    return abc;
  }

  @PostConstruct
  public void start() throws Exception {
    this.assets = process(descriptor.getAssets());
  }

  public URL resolve(AssetLocation location, String path) {
    switch (location) {
      case APPLICATION:
        return context.getApplicationResolver().resolve(path);
      case SERVER:
        return context.getServerResolver().resolve(path);
      default:
        return null;
    }
  }

  private LinkedHashMap<String, Chunk.Property<String>> process(List<AssetMetaData> data) throws Exception {
    LinkedHashMap<String, Chunk.Property<String>> assets = new LinkedHashMap<String, Chunk.Property<String>>();
    AssetDeployment deployment = assetManager.createDeployment();
    for (AssetMetaData script : data) {

      // Validate and resolve asset resources
      String[] a = new String[] { script.getValue(), script.getMinified() };
      URL[] resources = new URL[2];
      for (int i = 0;i < a.length; i++) {
        URL resource;
        String value = a[i];
        if (value != null) {
          AssetLocation location = script.getLocation();
          if (location == AssetLocation.APPLICATION) {
            URL url = resolve(AssetLocation.APPLICATION, value);
            if (url == null) {
              throw new Exception("Could not resolve application  " + value);
            } else {
              resource = url;
            }
          } else if (location == AssetLocation.SERVER) {
            if (!value.startsWith("/")) {
              URL url = resolve(AssetLocation.SERVER, "/" + value);
              if (url == null) {
                throw new Exception("Could not resolve server asset " + value);
              }
            }
            resource = null;
          } else {
            resource = null;
          }
        } else {
          resource = null;
        }
        resources[i] = resource;
      }


      //
      deployment.addAsset(script.getId(), script.getType(), script.getLocation(), a[0], script.getHeader(), a[1], script.getMaxAge(), resources[0], script.getDependencies());
      assets.put(script.getId(), new Chunk.Property<String>(script.getId(), PropertyType.ASSET));
    }

    // Should be true
    deployment.deploy();

    //
    return assets;
  }

  private Collection<Chunk.Property<String>> foo(AnnotatedElement elt, List<Chunk.Property<String>> bar) {
    Assets decl = elt.getAnnotation(Assets.class);
    if (decl != null) {
      String[] value = decl.value();
      for (String s : value) {
        if (s.equals("*")) {
          return assets.values();
        } else {
          Chunk.Property<String> p = assets.get(s);
          if (p == null) {
            throw new UnsupportedOperationException("handle me gracefully");
          } else {
            if (bar.size() == 0) {
              bar = new ArrayList<Chunk.Property<String>>();
            }
            bar.add(p);
          }
        }
      }
    }
    if (elt instanceof Method) {
      Method methodElt = (Method)elt;
      if (decl == null) {
        for (Class<?> current = methodElt.getDeclaringClass().getSuperclass();current != null;current = current.getSuperclass()) {
          try {
            methodElt = current.getDeclaredMethod(methodElt.getName(), methodElt.getParameterTypes());
            return foo(methodElt, bar);
          }
          catch (NoSuchMethodException ignore) {
          }
        }
      }
      return foo(methodElt.getDeclaringClass(), bar);
    } else if (elt instanceof Class<?>) {
      Class<?> classElt = (Class<Object>)elt;
      String pkgName;
      if (classElt.getSimpleName().equals("package-info")) {
        pkgName = Tools.parentPackageOf(Tools.parentPackageOf(classElt.getName()));
      } else {
        pkgName = Tools.parentPackageOf(classElt.getName());
      }
      while (pkgName != null) {
        Class<?> currentPackage = Tools.getPackageClass(Thread.currentThread().getContextClassLoader(), pkgName);
        if (currentPackage != null) {
          return foo(currentPackage, bar);
        } else {
          pkgName = Tools.parentPackageOf(pkgName);
        }
      }
      return bar;
    } else {
      return bar;
    }
  }

  @Override
  public Class<Stage.Unmarshalling> getStageType() {
    return Stage.Unmarshalling.class;
  }

  @Override
  public Response handle(Stage.Unmarshalling argument) {
    Response result = argument.invoke();
    Request request = argument.getRequest();
    if (request.getPhase() == Phase.VIEW) {
      if (result instanceof Response.Content) {
        final Collection<Chunk.Property<String>> bar = foo(request.getHandler().getMethod(), Collections.<Chunk.Property<String>>emptyList());
        Response.Status status = (Response.Status)result;
        if ((bar.size() > 0)) {
          status = new Response.Content(status.getCode(), new StreamableDecorator(status.streamable()) {
            @Override
            protected void sendHeader(Stream consumer) {
              for (Chunk.Property<String> asset : bar) {
                consumer.provide(asset);
              }
            }
          });
          result = status;
        }
      }
    }
    return result;
  }
}
TOP

Related Classes of juzu.impl.plugin.asset.AssetService

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.