/** * Resolves template names into URLs. * * <p>Resolves templates by iterating over all known {@link Resolver} implementations while * providing a cache for frequently checked names / URIs. */ @Register(classes = Resources.class) public class Resources { /* * Logger used by the resource discovery framework */ public static final Log LOG = Log.get("resources"); @PriorityParts(Resolver.class) private Collection<Resolver> resolvers; /** Cache used to map a scope name and local uri to an URL pointing to a resolved content. */ private Cache<String, Optional<Resource>> resolverCache = CacheManager.createCache("resolver-cache"); /** * Tries to resolve a template or content-file into a {@link Resource} * * @param uri the local name of the uri to load * @return a {@link Resource} (wrapped as resource) pointing to the requested content or an empty * optional if no resource was found */ @Nonnull public Optional<Resource> resolve(@Nonnull String uri) { return resolve(UserContext.getCurrentScope().getScopeId(), uri); } /** * Tries to resolve a template or content-file into a {@link Resource} * * @param scopeId the scope to use. Use {@link #resolve(String)} to pick the currently active * scope * @param uri the local name of the uri to load * @return a {@link Resource} (wrapped as resource) pointing to the requested content or an empty * optional if no resource was found */ @Nonnull public Optional<Resource> resolve(@Nonnull String scopeId, @Nonnull String uri) { String lookupKey = scopeId + "://" + uri; Optional<Resource> result = resolverCache.get(lookupKey); if (result != null) { if (Sirius.isDev()) { // In dev environments, we always perform a lookup in case something changed Optional<Resource> currentResult = resolveURI(scopeId, uri); if (!result.isPresent()) { return currentResult; } if (!currentResult.isPresent() || !Objects.equals(result.get().getUrl(), currentResult.get().getUrl())) { return currentResult; } } return result; } result = resolveURI(scopeId, uri); resolverCache.put(lookupKey, result); return result; } /* * Calls all available resolvers to pick the right content for the given scope and uri (without using a cache) */ private Optional<Resource> resolveURI(String scopeId, String uri) { if (!uri.startsWith("/")) { uri = "/" + uri; } for (Resolver res : resolvers) { Resource r = res.resolve(scopeId, uri); if (r != null) { return Optional.of(r); } } return Optional.empty(); } }
/** Created by aha on 08.05.15. */ public class BizController implements Controller { @Part protected OMA oma; @Part protected Tenants tenants; public static final Log LOG = Log.get("biz"); protected UserInfo getUser() { return UserContext.getCurrentUser(); } protected boolean hasPermission(String permission) { return getUser().hasPermission(permission); } protected void assertPermission(String permission) {} protected void assertTenant(TenantAware tenantAware) {} protected void assertNotNull(Object obj) {} protected void assertNotNew(Object obj) {} protected Consumer<WebContext> defaultRoute; public BizController() { Optional<Method> defaultMethod = Arrays.stream(getClass().getDeclaredMethods()) .filter(m -> m.isAnnotationPresent(DefaultRoute.class)) .findFirst(); if (!defaultMethod.isPresent()) { throw new IllegalStateException( Strings.apply("Controller %s has no default route!", getClass().getName())); } this.defaultRoute = ctx -> { try { defaultMethod.get().invoke(this, ctx); } catch (IllegalAccessException e) { throw Exceptions.handle(e); } catch (InvocationTargetException e) { throw Exceptions.handle(e.getTargetException()); } }; } @Override public void onError(WebContext ctx, HandledException error) { if (error != null) { UserContext.message(Message.error(error.getMessage())); } defaultRoute.accept(ctx); } @ConfigValue("product.baseUrl") private String baseUrl; protected String getBaseUrl() { return baseUrl; } public void showSavedMessage() { UserContext.message(Message.info(NLS.get("BizController.changesSaved"))); } public void showDeletedMessage() { UserContext.message(Message.info(NLS.get("BizController.objectDeleted"))); } protected void load(WebContext ctx, Entity entity, Column... columns) { for (Column c : columns) { Property property = entity.getDescriptor().getProperty(c); if (property == null) { throw new IllegalArgumentException( Strings.apply("Unknown property '%s' for type '%s'", c, entity.getClass().getName())); } property.parseValue(entity, ctx.get(property.getName())); } } protected <E extends BizEntity> E find(Class<E> type, String id) { if (BizEntity.NEW.equals(id)) { try { return type.newInstance(); } catch (Throwable e) { throw Exceptions.handle() .to(LOG) .error(e) .withSystemErrorMessage("Cannot create a new instance of '%s'", type.getName()) .handle(); } } Optional<E> result = oma.find(type, id); if (!result.isPresent()) { throw Exceptions.createHandled() .withNLSKey("BizController.unknownObject") .set("id", id) .handle(); } return result.get(); } protected <E extends BizEntity> Optional<E> tryFind(Class<E> type, String id) { if (BizEntity.NEW.equals(id)) { return Optional.empty(); } return oma.find(type, id); } protected <E extends BizEntity> E findForTenant(Class<E> type, String id) { E result = find(type, id); if (!result.isNew() && result instanceof TenantAware) { assertTenant((TenantAware) result); } return result; } protected <E extends BizEntity> Optional<E> tryFindForTenant(Class<E> type, String id) { return tryFind(type, id) .map( e -> { if (e instanceof TenantAware) { assertTenant((TenantAware) e); } return e; }); } }