/* * * Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved. * * This file is part of jAPS software. * jAPS is a free software; * you can redistribute it and/or modify it * under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2. * * See the file License for the specific language governing permissions * and limitations under the License * * * * Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved. * */ package com.agiletec.plugins.jacms.aps.system.services.resource; import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import com.agiletec.aps.system.ApsSystemUtils; import com.agiletec.aps.system.SystemConstants; import com.agiletec.aps.system.common.AbstractService; import com.agiletec.aps.system.exception.ApsSystemException; import com.agiletec.aps.system.services.category.CategoryUtilizer; import com.agiletec.aps.system.services.category.ICategoryManager; import com.agiletec.aps.system.services.group.GroupUtilizer; import com.agiletec.aps.system.services.keygenerator.IKeyGeneratorManager; import com.agiletec.aps.util.DateConverter; import com.agiletec.plugins.jacms.aps.system.services.resource.event.ResourceChangedEvent; import com.agiletec.plugins.jacms.aps.system.services.resource.model.AbstractMonoInstanceResource; import com.agiletec.plugins.jacms.aps.system.services.resource.model.AbstractMultiInstanceResource; import com.agiletec.plugins.jacms.aps.system.services.resource.model.ResourceDataBean; import com.agiletec.plugins.jacms.aps.system.services.resource.model.ResourceInstance; import com.agiletec.plugins.jacms.aps.system.services.resource.model.ResourceInterface; import com.agiletec.plugins.jacms.aps.system.services.resource.model.ResourceRecordVO; import com.agiletec.plugins.jacms.aps.system.services.resource.parse.ResourceHandler; /** * Servizio gestore tipi di risorse (immagini, audio, video, etc..). * @author W.Ambu - E.Santoboni */ public class ResourceManager extends AbstractService implements IResourceManager, GroupUtilizer, CategoryUtilizer { @Override public void init() throws Exception { ApsSystemUtils.getLogger().config(this.getClass().getName() + ": initialized " + this._resourceTypes.size() + " resource types"); } /** * Crea una nuova istanza di un tipo di risorsa del tipo richiesto. Il nuovo * tipo di risorsa è istanziato mediante clonazione del prototipo corrispondente. * @param typeCode Il codice del tipo di risorsa richiesto, come definito in configurazione. * @return Il tipo di risorsa istanziato (vuoto). */ @Override public ResourceInterface createResourceType(String typeCode) { ResourceInterface resource = (ResourceInterface) _resourceTypes.get(typeCode); return resource.getResourcePrototype(); } /** * Restituisce la lista delle chiavi dei tipi risorsa presenti nel sistema. * @return La lista delle chiavi dei tipi risorsa esistenti. */ @Override public List<String> getResourceTypeCodes() { return new ArrayList<String>(this._resourceTypes.keySet()); } /** * Salva una risorsa nel db con incluse nel filesystem, indipendentemente dal tipo. * @param bean L'oggetto detentore dei dati della risorsa da inserire. * @throws ApsSystemException in caso di errore. */ @Override public ResourceInterface addResource(ResourceDataBean bean) throws ApsSystemException { return this.saveResource(bean); } /** * Salva una risorsa nel db, indipendentemente dal tipo. * @param resource La risorsa da salvare. * @throws ApsSystemException in caso di errore. */ @Override public void addResource(ResourceInterface resource) throws ApsSystemException { try { IKeyGeneratorManager keyGenerator = (IKeyGeneratorManager) this.getService(SystemConstants.KEY_GENERATOR_MANAGER); int id = keyGenerator.getUniqueKeyCurrentValue(); resource.setId(String.valueOf(id)); this.getResourceDAO().addResource(resource); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "addResource"); throw new ApsSystemException("Error adding resource", t); } } @Override public void updateResource(ResourceDataBean bean) throws ApsSystemException { ResourceInterface oldResource = this.loadResource(bean.getResourceId()); try { if (null == bean.getInputStream()) { oldResource.setDescr(bean.getDescr()); oldResource.setCategories(bean.getCategories()); this.getResourceDAO().updateResource(oldResource); this.notifyResourceChanging(oldResource); } else { ResourceInterface updatedResource = this.saveResource(bean); if (!updatedResource.getMasterFileName().equals(oldResource.getMasterFileName())) { oldResource.deleteResourceInstances(); } this.notifyResourceChanging(updatedResource); } } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "updateResource"); throw new ApsSystemException("Error updating resource", t); } } /** * Aggiorna una risorsa nel db. * @param resource Il contenuto da aggiungere o modificare. * @throws ApsSystemException in caso di errore nell'accesso al db. */ @Override public void updateResource(ResourceInterface resource) throws ApsSystemException { try { this.getResourceDAO().updateResource(resource); this.notifyResourceChanging(resource); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "updateResource"); throw new ApsSystemException("Error updating resource", t); } } protected ResourceInterface saveResource(ResourceDataBean bean) throws ApsSystemException { ResourceInterface resource = this.createResourceType(bean.getResourceType()); try { resource.setDescr(bean.getDescr()); resource.setMainGroup(bean.getMainGroup()); resource.setCategories(bean.getCategories()); resource.setMasterFileName(bean.getFileName()); resource.saveResourceInstances(bean); if (null != bean.getResourceId() && bean.getResourceId().trim().length() > 0) { resource.setId(bean.getResourceId()); this.getResourceDAO().updateResource(resource); this.notifyResourceChanging(resource); } else { this.addResource(resource); } } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "saveResource"); if (null == bean.getResourceId()) { resource.deleteResourceInstances(); } throw new ApsSystemException("Error saving resource", t); } return resource; } private void notifyResourceChanging(ResourceInterface resource) throws ApsSystemException { ResourceChangedEvent event = new ResourceChangedEvent(); event.setResource(resource); this.notifyEvent(event); } /** * Carica una lista di identificativi di risorse * in base al tipo, ad una parola chiave e dalla categoria della risorsa. * @param type Tipo di risorsa da cercare. * @param text Testo immesso per il raffronto con la descrizione della risorsa. null o * stringa vuota nel caso non si voglia ricercare le risorse per parola chiave. * @param categoryCode Il codice della categoria delle risorse. null o * stringa vuota nel caso non si voglia ricercare le risorse per categoria. * @param groupCodes I codici dei gruppi consentiti tramite il quale * filtrare le risorse. * @return La lista di identificativi di risorse. * @throws ApsSystemException In caso di errore. */ @Override public List<String> searchResourcesId(String type, String text, String categoryCode, Collection<String> groupCodes) throws ApsSystemException { return this.searchResourcesId(type, text, null, categoryCode, groupCodes); } @Override public List<String> searchResourcesId(String type, String text, String filename, String categoryCode, Collection<String> groupCodes) throws ApsSystemException { if (null == groupCodes || groupCodes.size() == 0) return new ArrayList<String>(); List<String> resources = null; try { resources = this.getResourceDAO().searchResourcesId(type, text, filename, categoryCode, groupCodes); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "searchResourcesId"); throw new ApsSystemException("Error extracting resources id", t); } return resources; } /** * Restituisce la risorsa con l'id specificato. * @param id L'identificativo della risorsa da caricare. * @return La risorsa cercata. null se non vi è nessuna risorsa con l'identificativo immesso. * @throws ApsSystemException in caso di errore. */ @Override public ResourceInterface loadResource(String id) throws ApsSystemException { ResourceInterface resource = null; try { ResourceRecordVO resourceVo = this.getResourceDAO().loadResourceVo(id); if (null != resourceVo) { resource = this.createResource(resourceVo); resource.setMasterFileName(resourceVo.getMasterFileName()); } } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "loadResource"); throw new ApsSystemException("Error loading resource : id " + id, t); } return resource; } /** * Metodo di servizio. Restituisce una risorsa * in base ai dati del corrispondente record. * @param resourceVo Il vo relativo al record. * @return La risorsa valorizzata. * @throws ApsSystemException in caso di errore. */ private ResourceInterface createResource(ResourceRecordVO resourceVo) throws ApsSystemException { String resourceType = resourceVo.getResourceType(); String resourceXML = resourceVo.getXml(); ResourceInterface resource = this.createResourceType(resourceType); this.fillEmptyResourceFromXml(resource, resourceXML); resource.setMainGroup(resourceVo.getMainGroup()); return resource; } /** * Valorizza una risorsa prototipo con gli elementi * dell'xml che rappresenta una risorsa specifica. * @param resource Il prototipo di risorsa da specializzare con gli attributi dell'xml. * @param xml L'xml della risorsa specifica. * @throws ApsSystemException */ protected void fillEmptyResourceFromXml(ResourceInterface resource, String xml) throws ApsSystemException { try { SAXParserFactory parseFactory = SAXParserFactory.newInstance(); SAXParser parser = parseFactory.newSAXParser(); InputSource is = new InputSource(new StringReader(xml)); ResourceHandler handler = new ResourceHandler(resource, this.getCategoryManager()); parser.parse(is, handler); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "fillEmptyResourceFromXml"); throw new ApsSystemException("Error loading resource", t); } } /** * Cancella una risorsa dal db ed i file di ogni istanza dal filesystem. * @param resource La risorsa da cancellare. * @throws ApsSystemException in caso di errore nell'accesso al db. */ @Override public void deleteResource(ResourceInterface resource) throws ApsSystemException { try { this.getResourceDAO().deleteResource(resource.getId()); resource.deleteResourceInstances(); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "deleteResource"); throw new ApsSystemException("Error deleting resource", t); } } @Override public void refreshMasterFileNames() throws ApsSystemException { this.startResourceReloaderThread(null, ResourceReloaderThread.RELOAD_MASTER_FILE_NAME); } @Override public void refreshResourcesInstances(String resourceTypeCode) throws ApsSystemException { this.startResourceReloaderThread(resourceTypeCode, ResourceReloaderThread.REFRESH_INSTANCE); } protected void startResourceReloaderThread(String resourceTypeCode, int operationCode) throws ApsSystemException { if (this.getStatus() != STATUS_READY) { ApsSystemUtils.getLogger().severe("Service not ready : status " + this.getStatus()); return; } String threadName = this.getName() + "_resourceReloader_" + DateConverter.getFormattedDate(new Date(), "yyyyMMdd"); try { List<String> resources = this.getResourceDAO().searchResourcesId(resourceTypeCode, null, null, null); ResourceReloaderThread thread = new ResourceReloaderThread(this, operationCode, resources); thread.setName(threadName); thread.start(); ApsSystemUtils.getLogger().info("Reloader started"); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "startResourceReloaderThread", "Error refreshing Resource of type " + resourceTypeCode + " - Thread Name '" + threadName + "'"); } } protected void refreshMasterFileNames(String resourceId) { try { ResourceInterface resource = this.loadResource(resourceId); if (resource.isMultiInstance()) { ResourceInstance instance = ((AbstractMultiInstanceResource) resource).getInstance(0, null); String filename = instance.getFileName(); int index = filename.lastIndexOf("_d0."); String masterFileName = filename.substring(0, index) + filename.substring(index+3); resource.setMasterFileName(masterFileName); } else { ResourceInstance instance = ((AbstractMonoInstanceResource) resource).getInstance(); resource.setMasterFileName(instance.getFileName()); } this.updateResource(resource); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "refreshMasterFileNames", "Error reloading master file name of resource " + resourceId); } } protected void refreshResourceInstances(String resourceId) { try { ResourceInterface resource = this.loadResource(resourceId); resource.reloadResourceInstances(); this.updateResource(resource); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "refreshResourceInstances", "Error refreshing resource instances of resource " + resourceId); } } @Override public List getGroupUtilizers(String groupName) throws ApsSystemException { List<String> resourcesId = null; try { List<String> allowedGroups = new ArrayList<String>(1); allowedGroups.add(groupName); resourcesId = this.getResourceDAO().searchResourcesId(null, null, null, null, allowedGroups); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "getGroupUtilizers"); throw new ApsSystemException("Error searching group utilizers : group '" + groupName + "'", t); } return resourcesId; } @Override public List getCategoryUtilizers(String categoryCode) throws ApsSystemException { List<String> resourcesId = null; try { resourcesId = this.getResourceDAO().searchResourcesId(null, null, null, categoryCode, null); } catch (Throwable t) { ApsSystemUtils.logThrowable(t, this, "getCategoryUtilizers"); throw new ApsSystemException("Error searching category utilizers : category code '" + categoryCode + "'", t); } return resourcesId; } @Override public int getStatus() { return this._status; } protected void setStatus(int status) { this._status = status; } /** * Restutuisce il dao in uso al manager. * @return Il dao in uso al manager. */ protected IResourceDAO getResourceDAO() { return _resourceDao; } /** * Setta il dao in uso al manager. * @param resourceDao Il dao in uso al manager. */ public void setResourceDAO(IResourceDAO resourceDao) { this._resourceDao = resourceDao; } public void setResourceTypes(Map<String, ResourceInterface> resourceTypes) { this._resourceTypes = resourceTypes; } protected ICategoryManager getCategoryManager() { return _categoryManager; } public void setCategoryManager(ICategoryManager categoryManager) { this._categoryManager = categoryManager; } /** * Mappa dei prototipi dei tipi di risorsa */ private Map<String, ResourceInterface> _resourceTypes; private int _status; private IResourceDAO _resourceDao; private ICategoryManager _categoryManager; }