/* * Copyright (C) 2014 Civilian Framework. * * Licensed under the Civilian License (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.civilian-framework.org/license.txt * * 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.civilian.asset; import java.io.File; import java.util.ArrayList; import java.util.List; import org.civilian.Application; import org.civilian.Context; import org.civilian.application.ConfigKeys; import org.civilian.content.ContentType; import org.civilian.internal.asset.AssetCache; import org.civilian.internal.asset.CombinedAssetService; import org.civilian.internal.asset.CivResourceLocation; import org.civilian.internal.asset.JavaResourceLocation; import org.civilian.internal.asset.DirectoryLocation; import org.civilian.resource.Path; import org.civilian.util.Settings; /** * AssetServices is a factory class to create AssetLocations * and other AssetService implementations. */ public abstract class AssetServices { /** * A key used civilian.ini for a directory based AssetLocation. */ public static final String DIR_LOCATION_KEY = "dir"; /** * A key used in civilian.ini for a class-path based AssetLocation * which serves Java resources. */ public static final String JAVARES_LOCATION_KEY = "res"; /** * A key used in civilian.ini for an AssetLocation which serves Java resource from civilian.jar */ public static final String CIVRES_LOCATION_KEY = "civres"; /** * The default path below the asset root. */ public static final String DEFAULT_PATH = ""; /** * Returns the AssetLocations of an application. * @param app the application * @param appSettings the application settings */ public static List<AssetLocation> getLocations(Application app, Settings appSettings) throws Exception { ArrayList<AssetLocation> list = new ArrayList<>(); int counter = -1; int missed = 0; while(missed < 5) { // keys are "location", "location.0", "location.1", etc. String key = ConfigKeys.LOCATION + (counter < 0 ? "" : '.' + String.valueOf(counter)); counter++; String def = appSettings.get(key, null); if (def == null) ++missed; else { Settings locSettings = new Settings(appSettings, key + '.'); AssetLocation location = getLocation(app, def, locSettings); list.add(location); } } return list; } /** * Returns the AssetLocation of an application, defined by an entry in civilian.ini. * The definition has the form type (':' param)? ('->' path)? * @param app the application * @param definition an entry app.<appid>.asset.location[.<n>] */ public static AssetLocation getLocation(Application app, String definition, Settings locSettings) throws Exception { String relPath; String type = definition; String param = null; // extract the path int p = definition.lastIndexOf("->"); if (p < 0) relPath = locSettings.get(ConfigKeys.PATH, null); else { relPath = definition.substring(p + 2).trim(); type = definition.substring(0, p).trim(); } // extract the param p = type.indexOf(':'); if (p >= 0) { param = type.substring(p + 1).trim(); type = type.substring(0, p).trim(); } AssetLocation location; if (DIR_LOCATION_KEY.equals(type)) { location = getDirectoryLocation(relPath, app.getContext(), param != null ? param : ""); } else if (JAVARES_LOCATION_KEY.equals(type)) { // type must be of form "res:<prefix>" if (param == null) throw new IllegalArgumentException("asset location '" + definition + "' has no resource prefix"); location = getJavaResourceLocation(relPath, param); } else if (CIVRES_LOCATION_KEY.equals(type)) { location = getCivResourceLocation(relPath, app.getPath().toString(), app.develop()); } else throw new IllegalArgumentException("invalid asset location type '" + type + "'"); String contentType = locSettings.get(ConfigKeys.CONTENT_TYPE, null); if (contentType != null) location.setContentType(ContentType.getContentType(contentType)); String encoding = locSettings.get(ConfigKeys.ENCODING, null); location.setEncoding(encoding); return location; } /** * Returns an AssetLocation whose assets * are files in the local file-system. The location * is defined by a root directory. Asset paths are translated into * file paths relative to that root directory. * @param path the path of the AssetLocation below the asset-root. * @param dir the root directory. */ public static AssetLocation getDirectoryLocation(String path, File dir) { return new DirectoryLocation(path, dir); } /** * Returns a new AssetDirectory for asset files in the local file-system. * @param path the path of the AssetLocation below the asset-root. * @param context the context * @param directory a directory. If null, then the context root directory is used. If relative * then the (context directory)/directory is used. Else if absolute the directory itself is used. */ public static AssetLocation getDirectoryLocation(String path, Context context, String directory) { File result; if (directory == null) result = context.getRootDir(); else { result = new File(directory); if (!result.exists()) result = new File(context.getRootDir(), directory); } return getDirectoryLocation(path, result); } /** * Returns an AssetLocation which returns Java resources from the class-path as Assets. * @param path the path of the AssetLocation below the asset root. * @param prefix the prefix path of the resources. * Must not be empty for security reasons. Asset paths are translated * into resource names by prepending the prefix to the asset path. */ public static AssetLocation getJavaResourceLocation(String path, String prefix) { return new JavaResourceLocation(path, prefix); } /** * Returns an AssetLocation which serves Java resources from civilian.jar. * @param path the path of the AssetLocation below the asset root. * If null, the path "civilian" is used. */ public static AssetLocation getCivResourceLocation(String path, String appPath, boolean develop) { return new CivResourceLocation(path, appPath, develop); } /** * Adds caching capabilities to an AssetService. Assets returned by the AssetService * will be cached and returned on subsequent requests, if the Asset is still valid. * @param service a AssetService implementation * @param maxMemSize if the size of an Asset is smaller than maxMemSize * than its contents will also be held in memory which will speed up request processing * of those assets. * @return the new caching AssetService * @see Asset#isValid() */ public static AssetService makeCaching(AssetService service, int maxMemSize) { return new AssetCache(service, maxMemSize); } /** * Returns an AssetService which combines the given services. * If no services are provided then the returned AssetService will not be able to serve assets. * (see {@link AssetService#hasAssets()}).<br> * @param prefixPath a path to be prepended to the paths of the given services * @param services a list of services. */ public static AssetService combine(Path prefixPath, AssetService... services) { return services.length == 1 ? services[0] : new CombinedAssetService(prefixPath, services); } }