All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ro.isdc.wro.manager.WroManager Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/*
 * Copyright (c) 2008. All rights reserved.
 */
package ro.isdc.wro.manager;

import static org.apache.commons.lang3.Validate.notNull;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ro.isdc.wro.cache.CacheKey;
import ro.isdc.wro.cache.CacheStrategy;
import ro.isdc.wro.cache.CacheValue;
import ro.isdc.wro.cache.factory.CacheKeyFactory;
import ro.isdc.wro.cache.factory.DefaultCacheKeyFactory;
import ro.isdc.wro.cache.impl.LruMemoryCacheStrategy;
import ro.isdc.wro.cache.support.DefaultSynchronizedCacheStrategyDecorator;
import ro.isdc.wro.config.Context;
import ro.isdc.wro.config.jmx.WroConfiguration;
import ro.isdc.wro.config.metadata.DefaultMetaDataFactory;
import ro.isdc.wro.config.metadata.MetaDataFactory;
import ro.isdc.wro.config.support.ContextPropagatingCallable;
import ro.isdc.wro.config.support.WroConfigurationChangeListener;
import ro.isdc.wro.manager.callback.LifecycleCallback;
import ro.isdc.wro.manager.callback.LifecycleCallbackRegistry;
import ro.isdc.wro.manager.factory.WroManagerFactory;
import ro.isdc.wro.manager.runnable.ReloadCacheRunnable;
import ro.isdc.wro.manager.runnable.ReloadModelRunnable;
import ro.isdc.wro.model.WroModel;
import ro.isdc.wro.model.factory.DefaultWroModelFactoryDecorator;
import ro.isdc.wro.model.factory.WroModelFactory;
import ro.isdc.wro.model.group.DefaultGroupExtractor;
import ro.isdc.wro.model.group.GroupExtractor;
import ro.isdc.wro.model.group.Inject;
import ro.isdc.wro.model.group.processor.InjectorBuilder;
import ro.isdc.wro.model.resource.ResourceType;
import ro.isdc.wro.model.resource.locator.factory.DefaultUriLocatorFactory;
import ro.isdc.wro.model.resource.locator.factory.UriLocatorFactory;
import ro.isdc.wro.model.resource.processor.Destroyable;
import ro.isdc.wro.model.resource.processor.ResourcePostProcessor;
import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;
import ro.isdc.wro.model.resource.processor.factory.ProcessorsFactory;
import ro.isdc.wro.model.resource.processor.factory.SimpleProcessorsFactory;
import ro.isdc.wro.model.resource.support.DefaultResourceAuthorizationManager;
import ro.isdc.wro.model.resource.support.ResourceAuthorizationManager;
import ro.isdc.wro.model.resource.support.change.ResourceWatcher;
import ro.isdc.wro.model.resource.support.hash.HashStrategy;
import ro.isdc.wro.model.resource.support.hash.SHA1HashStrategy;
import ro.isdc.wro.model.resource.support.naming.NamingStrategy;
import ro.isdc.wro.model.resource.support.naming.NoOpNamingStrategy;
import ro.isdc.wro.model.transformer.WildcardExpanderModelTransformer;
import ro.isdc.wro.util.LazyInitializer;
import ro.isdc.wro.util.ObjectFactory;
import ro.isdc.wro.util.SchedulerHelper;
import ro.isdc.wro.util.Transformer;


/**
 * Contains all the factories used by optimizer in order to perform the logic. This object should be created through
 * {@link WroManagerFactory}, in order to ensure that all dependencies are injected properly. In other words, avoid
 * setting the fields explicitly after creating a new instance of {@link WroManager}.
 * 

* Most of the fields of this class are annotated with @Inject, in order to ensure that each instance can benefit use * @Inject annotation on its fields. * * @author Alex Objelean * @created Created on Oct 30, 2008 */ public class WroManager implements WroConfigurationChangeListener { private static final Logger LOG = LoggerFactory.getLogger(WroManager.class); @Inject private final WroModelFactory modelFactory; @Inject private final GroupExtractor groupExtractor; /** * A cacheStrategy used for caching processed results. . */ @Inject private final CacheStrategy cacheStrategy; @Inject private final ProcessorsFactory processorsFactory; @Inject private final UriLocatorFactory locatorFactory; /** * Rename the file name based on its original name and content. */ @Inject private final NamingStrategy namingStrategy; @Inject private LifecycleCallbackRegistry callbackRegistry; /** * HashBuilder for creating a hash based on the processed content. */ @Inject private final HashStrategy hashStrategy; @Inject private ResourceBundleProcessor resourceBundleProcessor; @Inject private final ResourceAuthorizationManager authorizationManager; @Inject private final CacheKeyFactory cacheKeyFactory; @Inject private final MetaDataFactory metaDataFactory; @Inject private final ResourceWatcher resourceWatcher; /** * Schedules the model update. */ private final SchedulerHelper modelSchedulerHelper = SchedulerHelper.create(new LazyInitializer() { @Override protected Runnable initialize() { // decorate with ContextPropagatingCallable to make context available in the new thread return ContextPropagatingCallable.decorate(new ReloadModelRunnable(getModelFactory())); } }, ReloadModelRunnable.class.getSimpleName()); /** * Schedules the cache update. */ private final SchedulerHelper cacheSchedulerHelper = SchedulerHelper.create(new LazyInitializer() { @Override protected Runnable initialize() { // decorate with ContextPropagatingCallable to make context available in the new thread return ContextPropagatingCallable.decorate(new ReloadCacheRunnable(getCacheStrategy())); } }, ReloadCacheRunnable.class.getSimpleName()); private WroManager(final Builder builder) { this.authorizationManager = builder.authorizationManager; this.cacheKeyFactory = builder.cacheKeyFactory; this.cacheStrategy = DefaultSynchronizedCacheStrategyDecorator.decorate(builder.cacheStrategy); this.callbackRegistry = builder.callbackRegistry; this.groupExtractor = builder.groupExtractor; this.hashStrategy = builder.hashStrategy; this.locatorFactory = builder.locatorFactory; this.metaDataFactory = builder.metaDataFactory; this.namingStrategy = builder.namingStrategy; this.processorsFactory = builder.processorsFactory; this.modelFactory = DefaultWroModelFactoryDecorator.decorate(builder.modelFactory, builder.modelTransformers); this.resourceWatcher = new ResourceWatcher(); } /** * Perform processing of the uri. * * @throws IOException * when any IO related problem occurs or if the request cannot be processed. */ public final void process() throws IOException { // reschedule cache & model updates final WroConfiguration config = Context.get().getConfig(); cacheSchedulerHelper.scheduleWithPeriod(config.getCacheUpdatePeriod()); modelSchedulerHelper.scheduleWithPeriod(config.getModelUpdatePeriod()); resourceBundleProcessor.serveProcessedBundle(); } /** * Encodes a fingerprint of the resource into the path. The result may look like this: ${fingerprint}/myGroup.js * * @return a path to the resource with the fingerprint encoded as a folder name. */ public final String encodeVersionIntoGroupPath(final String groupName, final ResourceType resourceType, final boolean minimize) { // TODO use CacheKeyFactory final CacheKey key = new CacheKey(groupName, resourceType, minimize); final CacheValue cacheValue = cacheStrategy.get(key); final String groupUrl = groupExtractor.encodeGroupUrl(groupName, resourceType, minimize); // encode the fingerprint of the resource into the resource path return formatVersionedResource(cacheValue.getHash(), groupUrl); } /** * Format the version of the resource in the path. Default implementation use hash as a folder: /groupName.js. * The implementation can be changed to follow a different versioning style, like version parameter: * /groupName.js?version= * * @param hash * Hash of the resource. * @param resourcePath * Path of the resource. * @return formatted versioned path of the resource. */ protected String formatVersionedResource(final String hash, final String resourcePath) { return String.format("%s/%s", hash, resourcePath); } @Override public final void onCachePeriodChanged(final long period) { LOG.info("onCachePeriodChanged with value {} has been triggered!", period); cacheSchedulerHelper.scheduleWithPeriod(period); // flush the cache by destroying it. cacheStrategy.clear(); } @Override public final void onModelPeriodChanged(final long period) { LOG.info("onModelPeriodChanged with value {} has been triggered!", period); // trigger model destroy getModelFactory().destroy(); modelSchedulerHelper.scheduleWithPeriod(period); } /** * Called when {@link WroManager} is being taken out of service. */ public final void destroy() { try { cacheSchedulerHelper.destroy(); modelSchedulerHelper.destroy(); cacheStrategy.destroy(); modelFactory.destroy(); resourceWatcher.destroy(); destroyProcessors(); } catch (final Exception e) { LOG.error("Exception occured during manager destroy!", e); } finally { LOG.debug("WroManager destroyed"); } } /** * Invokes destroy method on all {@link Destroyable} processors. */ private void destroyProcessors() throws Exception { for (final ResourcePreProcessor processor : processorsFactory.getPreProcessors()) { if (processor instanceof Destroyable) { ((Destroyable) processor).destroy(); } } for (final ResourcePostProcessor processor : processorsFactory.getPostProcessors()) { if (processor instanceof Destroyable) { ((Destroyable) processor).destroy(); } } } public final HashStrategy getHashStrategy() { return hashStrategy; } /** * @return the modelFactory */ public final WroModelFactory getModelFactory() { return modelFactory; } /** * @return the processorsFactory used by this WroManager. */ public final ProcessorsFactory getProcessorsFactory() { return processorsFactory; } /** * @return the cacheStrategy */ public final CacheStrategy getCacheStrategy() { return cacheStrategy; } /** * @return the uriLocatorFactory */ public final UriLocatorFactory getUriLocatorFactory() { return locatorFactory; } /** * @return The strategy used to rename bundled resources. */ public final NamingStrategy getNamingStrategy() { return this.namingStrategy; } public final GroupExtractor getGroupExtractor() { return groupExtractor; } public CacheKeyFactory getCacheKeyFactory() { return cacheKeyFactory; } public MetaDataFactory getMetaDataFactory() { return metaDataFactory; } public ResourceWatcher getResourceWatcher() { return resourceWatcher; } /** * Registers a callback. * * @param callbackFactory * {@link ObjectFactory} responsible for creating {@link LifecycleCallback} instance. */ public final void registerCallback(final ObjectFactory callbackFactory) { notNull(callbackFactory); getCallbackRegistry().registerCallback(callbackFactory); } public LifecycleCallbackRegistry getCallbackRegistry() { // TODO check if initialization is required. if (callbackRegistry == null) { callbackRegistry = new LifecycleCallbackRegistry(); } return callbackRegistry; } public ResourceAuthorizationManager getResourceAuthorizationManager() { return authorizationManager; } private static class EmptyModelFactory implements WroModelFactory { @Override public WroModel create() { return new WroModel(); } @Override public void destroy() { } } public static class Builder { private WroModelFactory modelFactory = new EmptyModelFactory(); private GroupExtractor groupExtractor = new DefaultGroupExtractor(); private CacheStrategy cacheStrategy = new LruMemoryCacheStrategy(); private ProcessorsFactory processorsFactory = new SimpleProcessorsFactory(); private UriLocatorFactory locatorFactory = new DefaultUriLocatorFactory(); private NamingStrategy namingStrategy = new NoOpNamingStrategy(); private LifecycleCallbackRegistry callbackRegistry = new LifecycleCallbackRegistry(); private HashStrategy hashStrategy = new SHA1HashStrategy(); private List> modelTransformers = createDefaultTransformers(); private ResourceAuthorizationManager authorizationManager = new DefaultResourceAuthorizationManager(); private CacheKeyFactory cacheKeyFactory = new DefaultCacheKeyFactory(); private MetaDataFactory metaDataFactory = new DefaultMetaDataFactory(); public Builder() { } public Builder(final WroManager manager) { notNull(manager); this.groupExtractor = manager.getGroupExtractor(); this.cacheStrategy = manager.getCacheStrategy(); this.processorsFactory = manager.getProcessorsFactory(); this.locatorFactory = manager.getUriLocatorFactory(); this.namingStrategy = manager.getNamingStrategy(); this.callbackRegistry = manager.getCallbackRegistry(); this.hashStrategy = manager.getHashStrategy(); this.modelFactory = manager.getModelFactory(); this.authorizationManager = manager.getResourceAuthorizationManager(); this.cacheKeyFactory = manager.getCacheKeyFactory(); this.metaDataFactory = manager.getMetaDataFactory(); } public Builder setModelFactory(final WroModelFactory modelFactory) { this.modelFactory = modelFactory; return this; } public Builder setGroupExtractor(final GroupExtractor groupExtractor) { notNull(groupExtractor); this.groupExtractor = groupExtractor; return this; } public Builder setCacheStrategy(final CacheStrategy cacheStrategy) { notNull(cacheStrategy); this.cacheStrategy = cacheStrategy; return this; } public Builder setProcessorsFactory(final ProcessorsFactory processorsFactory) { notNull(processorsFactory); this.processorsFactory = processorsFactory; return this; } public Builder setLocatorFactory(final UriLocatorFactory locatorFactory) { notNull(locatorFactory); this.locatorFactory = locatorFactory; return this; } public Builder setNamingStrategy(final NamingStrategy namingStrategy) { notNull(namingStrategy); this.namingStrategy = namingStrategy; return this; } public Builder setCallbackRegistry(final LifecycleCallbackRegistry callbackRegistry) { notNull(callbackRegistry); this.callbackRegistry = callbackRegistry; return this; } public Builder setHashStrategy(final HashStrategy hashStrategy) { notNull(hashStrategy); this.hashStrategy = hashStrategy; return this; } public Builder setModelTransformers(final List> modelTransformers) { notNull(modelTransformers); this.modelTransformers = modelTransformers; return this; } public Builder setAuthorizationManager(final ResourceAuthorizationManager authorizationManager) { notNull(authorizationManager); this.authorizationManager = authorizationManager; return this; } public Builder setCacheKeyFactory(final CacheKeyFactory cacheKeyFactory) { notNull(cacheKeyFactory); this.cacheKeyFactory = cacheKeyFactory; return this; } public Builder setMetaDataFactory(final MetaDataFactory metaDataFactory) { notNull(metaDataFactory); this.metaDataFactory = metaDataFactory; return this; } private List> createDefaultTransformers() { final List> list = new ArrayList>(); list.add(new WildcardExpanderModelTransformer()); return list; } public WroManager build() { final WroManager manager = new WroManager(this); InjectorBuilder.create(manager).build().inject(manager); return manager; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy