/* Index ECM Engine - A system for managing the capture (when created * or received), classification (cataloguing), storage, retrieval, * revision, sharing, reuse and disposition of documents. * * Copyright (C) 2008 Regione Piemonte * Copyright (C) 2008 Provincia di Torino * Copyright (C) 2008 Comune di Torino * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package it.doqui.index.ecmengine.business.publishing; import it.csi.util.performance.StopWatch; import it.doqui.index.ecmengine.business.foundation.TransactionSvc; import it.doqui.index.ecmengine.business.foundation.TransactionSvcHome; import it.doqui.index.ecmengine.business.foundation.audit.AuditSvc; import it.doqui.index.ecmengine.business.foundation.audit.AuditSvcHome; import it.doqui.index.ecmengine.business.foundation.audit.AuditTrailSvc; import it.doqui.index.ecmengine.business.foundation.audit.AuditTrailSvcHome; import it.doqui.index.ecmengine.business.foundation.category.CategorySvc; import it.doqui.index.ecmengine.business.foundation.category.CategorySvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.ActionSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.ActionSvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.CheckOutCheckInSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.CheckOutCheckInSvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.CopySvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.CopySvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.FileFolderSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.FileFolderSvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.LockSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.LockSvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.NamespaceSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.NamespaceSvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.RuleSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.RuleSvcHome; import it.doqui.index.ecmengine.business.foundation.contentmanagement.VersionSvc; import it.doqui.index.ecmengine.business.foundation.contentmanagement.VersionSvcHome; import it.doqui.index.ecmengine.business.foundation.fileformat.FileFormatSvc; import it.doqui.index.ecmengine.business.foundation.fileformat.FileFormatSvcHome; import it.doqui.index.ecmengine.business.foundation.integrity.IntegritySvc; import it.doqui.index.ecmengine.business.foundation.integrity.IntegritySvcHome; import it.doqui.index.ecmengine.business.foundation.job.JobSvc; import it.doqui.index.ecmengine.business.foundation.job.JobSvcHome; import it.doqui.index.ecmengine.business.foundation.mimetype.MimetypeSvc; import it.doqui.index.ecmengine.business.foundation.mimetype.MimetypeSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.ContentSvc; import it.doqui.index.ecmengine.business.foundation.repository.ContentSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.DictionarySvc; import it.doqui.index.ecmengine.business.foundation.repository.DictionarySvcHome; import it.doqui.index.ecmengine.business.foundation.repository.ExportSvc; import it.doqui.index.ecmengine.business.foundation.repository.ExportSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.ImportSvc; import it.doqui.index.ecmengine.business.foundation.repository.ImportSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.NodeArchiveSvc; import it.doqui.index.ecmengine.business.foundation.repository.NodeArchiveSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.NodeSvc; import it.doqui.index.ecmengine.business.foundation.repository.NodeSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.RepoAdminSvc; import it.doqui.index.ecmengine.business.foundation.repository.RepoAdminSvcHome; import it.doqui.index.ecmengine.business.foundation.repository.TenantAdminSvc; import it.doqui.index.ecmengine.business.foundation.repository.TenantAdminSvcHome; import it.doqui.index.ecmengine.business.foundation.search.SearchSvc; import it.doqui.index.ecmengine.business.foundation.search.SearchSvcHome; import it.doqui.index.ecmengine.business.foundation.security.AuthenticationSvc; import it.doqui.index.ecmengine.business.foundation.security.AuthenticationSvcHome; import it.doqui.index.ecmengine.business.foundation.security.AuthoritySvc; import it.doqui.index.ecmengine.business.foundation.security.AuthoritySvcHome; import it.doqui.index.ecmengine.business.foundation.security.OwnableSvc; import it.doqui.index.ecmengine.business.foundation.security.OwnableSvcHome; import it.doqui.index.ecmengine.business.foundation.security.PermissionSvc; import it.doqui.index.ecmengine.business.foundation.security.PermissionSvcHome; import it.doqui.index.ecmengine.business.foundation.security.PersonSvc; import it.doqui.index.ecmengine.business.foundation.security.PersonSvcHome; import it.doqui.index.ecmengine.business.foundation.util.FoundationBeansConstants; import it.doqui.index.ecmengine.business.foundation.util.FoundationErrorCodes; import it.doqui.index.ecmengine.business.personalization.multirepository.Repository; import it.doqui.index.ecmengine.business.personalization.multirepository.RepositoryManager; import it.doqui.index.ecmengine.business.publishing.util.IntegrityViolationHandler; import it.doqui.index.ecmengine.dto.AclRecord; import it.doqui.index.ecmengine.dto.ContentItem; import it.doqui.index.ecmengine.dto.Node; import it.doqui.index.ecmengine.dto.OperationContext; import it.doqui.index.ecmengine.dto.backoffice.DataArchive; import it.doqui.index.ecmengine.dto.backoffice.Group; import it.doqui.index.ecmengine.dto.backoffice.Tenant; import it.doqui.index.ecmengine.dto.backoffice.User; import it.doqui.index.ecmengine.dto.backoffice.model.CustomModel; import it.doqui.index.ecmengine.dto.engine.audit.AuditInfo; import it.doqui.index.ecmengine.dto.engine.audit.OperazioneAudit; import it.doqui.index.ecmengine.dto.engine.management.Aspect; import it.doqui.index.ecmengine.dto.engine.management.Association; import it.doqui.index.ecmengine.dto.engine.management.Category; import it.doqui.index.ecmengine.dto.engine.management.Content; import it.doqui.index.ecmengine.dto.engine.management.EncryptionInfo; import it.doqui.index.ecmengine.dto.engine.management.Property; import it.doqui.index.ecmengine.dto.engine.search.ResultProperty; import it.doqui.index.ecmengine.dto.engine.search.SearchParams; import it.doqui.index.ecmengine.dto.engine.search.SearchParamsAggregate; import it.doqui.index.ecmengine.exception.EcmEngineFoundationException; import it.doqui.index.ecmengine.exception.InvalidParameterException; import it.doqui.index.ecmengine.exception.publishing.EcmEngineTransactionException; import it.doqui.index.ecmengine.exception.publishing.InvalidCredentialsException; import it.doqui.index.ecmengine.exception.publishing.NoSuchNodeException; import it.doqui.index.ecmengine.exception.publishing.PermissionDeniedException; import it.doqui.index.ecmengine.exception.repository.DictionaryRuntimeException; import it.doqui.index.ecmengine.exception.repository.NodeRuntimeException; import it.doqui.index.ecmengine.exception.security.AuthenticationRuntimeException; import it.doqui.index.ecmengine.util.EcmEngineConstants; import it.doqui.index.ecmengine.util.ISO8601DateFormat; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Vector; import javax.ejb.CreateException; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.transaction.RollbackException; import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.node.integrity.IntegrityException; import org.alfresco.repo.node.integrity.IntegrityRecord; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Classe astratta che implementa un generico EJB 2.x di pubblicazione dei servizi. * * <p>Questa classe si occupa di raccogliere in un unico punto le operazioni di inizializzazione * del logger e dello stopwatch utilizzati dai servizi pubblicati, oltre che di reperire i riferimenti * a tutti gli EJB wrapper dei servizi applicativi. Ogni EJB publisher deve ereditare da questa classe * in modo da avere direttamente disponibili i riferimenti a tutti i servizi applicativi.</p> * * @author Doqui */ public abstract class EcmEnginePublisherBean implements SessionBean, EcmEngineConstants { /** Il log utilizzato da tutti i servizi pubblicati. */ protected static Log logger; /** Regex che definisce il formato degli identificativi di nodo validi. */ protected static final String NODE_CHECK_REGEX = "[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}"; protected static final long MASSIVE_MAX_CREATE_NUMBER=50; protected static final long MASSIVE_MAX_CREATE_SIZE=9437184; //9 MB, in Byte. protected static final long MASSIVE_MAX_RETRIEVE_NUMBER=50; protected static final long MASSIVE_MAX_RETRIEVE_SIZE=9437184; //9 MB, in Byte. protected static final long MASSIVE_MAX_GET_METADATA_SIZE=50; protected static final long MASSIVE_MAX_DELETE_NUMBER=50; protected static final long USERNAME_MAX_LENGTH = 70; /** * Restituisce il repository sul quale verranno eseguite le operazioni successive. * * @return L'identificativo del repository corrente. */ protected static String getCurrentRepository() { logger.debug("[EcmEnginePublisherBean::getCurrentRepository] BEGIN"); final String repository = RepositoryManager.getCurrentRepository(); if( logger.isDebugEnabled() ) { logger.debug("[EcmEnginePublisherBean::getCurrentRepository] Current repository: " + repository); } logger.debug("[EcmEnginePublisherBean::getCurrentRepository] END"); return repository; } /** * Restituisce il repository predefinito. * * @return L'identificativo del repository predefinito. */ protected static String getDefaultRepository() { logger.debug("[EcmEnginePublisherBean::getDefaultRepository] BEGIN"); final String repository = RepositoryManager.getInstance().getDefaultRepository().getId(); if( logger.isDebugEnabled() ) { logger.debug("[EcmEnginePublisherBean::getDefaultRepository] Default repository: " + repository); } logger.debug("[EcmEnginePublisherBean::getDefaultRepository] END"); return repository; } /** * Restituisce gli identificativi dei repository conosciuti. * * @return Una lista di identificativi dei repository conosciuti. */ protected static List<Repository> getKnownRepositories() { logger.debug("[EcmEnginePublisherBean::getKnownRepositories] BEGIN"); List<Repository> repositories = new ArrayList<Repository>(RepositoryManager.getInstance().getRepositories().size()); for (Repository repo : RepositoryManager.getInstance().getRepositories()) { Repository newRep = new Repository(); newRep.setDataSource( repo.getDataSource() ); newRep.setId( repo.getId() ); newRep.setContentRootLocation(repo.getContentRootLocation() ); newRep.setIndexRootLocation( repo.getIndexRootLocation() ); newRep.setIndexBackupLocation(repo.getIndexBackupLocation() ); newRep.setCacheConfigLocation(repo.getCacheConfigLocation() ); newRep.setIndexRecoveryMode( repo.getIndexRecoveryMode() ); newRep.setContentStores( repo.getContentStores() ); repositories.add( newRep ); } logger.debug("[EcmEnginePublisherBean::getKnownRepositories] END"); return repositories; } /** * Seleziona il repository richiesto per l'esecuzione delle operazioni successive. * * <p><strong>NB:</strong> se viene specificato un valore {@code null} viene impostato il * repository predefinito. Se il repository viene specificato ma non esiste viene sollevata * un'eccezione e viene eseguito il rollback della transazione eventualmente specificata.</p> * * @param repository L'identificativo del repository da selezionare. * @param transaction La transazione di cui eseguire il rollback, oppure {@code null}. * * @throws InvalidParameterException Se il repository specificato non esiste. */ protected static void selectRepository(String repository, UserTransaction transaction) throws InvalidParameterException { logger.debug("[EcmEnginePublisherBean::selectRepository] BEGIN"); try { RepositoryManager.setCurrentRepository(repository); if (logger.isDebugEnabled()) { logger.debug("[EcmEnginePublisherBean::selectRepository] Repository selected: " + repository); } } catch (IllegalArgumentException e) { logger.warn("[EcmEnginePublisherBean::selectRepository] Non-existent repository requested: " + repository); if (transaction != null) { rollbackQuietely(transaction); } throw new InvalidParameterException("Repository '" + repository + "' doesn't exist!"); } finally { logger.debug("[EcmEnginePublisherBean::selectRepository] END"); } } private SessionContext sessionContext; private transient InitialContext initialContext; private transient AuthenticationSvcHome authenticationServiceHome; private transient AuthoritySvcHome authorityServiceHome; private transient ContentSvcHome contentServiceHome; private transient DictionarySvcHome dictionaryServiceHome; private transient FileFolderSvcHome fileFolderServiceHome; private transient NodeSvcHome nodeServiceHome; private transient NodeArchiveSvcHome nodeArchiveServiceHome; private transient OwnableSvcHome ownableServiceHome; private transient PermissionSvcHome permissionServiceHome; private transient PersonSvcHome personServiceHome; private transient SearchSvcHome searchServiceHome; private transient TransactionSvcHome transactionServiceHome; /* Content management services */ private transient LockSvcHome lockServiceHome; private transient CheckOutCheckInSvcHome checkOutCheckInHome; private transient CopySvcHome copyHome; private transient VersionSvcHome versionHome; private transient ActionSvcHome actionHome; private transient RuleSvcHome ruleHome; private transient TenantAdminSvcHome tenantAdminHome; private transient RepoAdminSvcHome repoAdminHome; private transient JobSvcHome jobHome; protected transient AuditSvcHome auditHome; protected transient AuditTrailSvcHome auditTrailHome; private transient MimetypeSvcHome mimetypeHome; private transient IntegritySvcHome integrityHome; private transient NamespaceSvcHome namespaceServiceHome; private transient FileFormatSvcHome fileFormatHome; private transient CategorySvcHome categoryHome; private transient ExportSvcHome exporterHome; private transient ImportSvcHome importerHome; /** Lo stopwatch da utilizzare per la registrazione dei tempi. */ protected transient StopWatch stopwatch; /** Il servizio di autenticazione. */ protected transient AuthenticationSvc authenticationService; /** Il servizio di gestione delle authority. */ protected transient AuthoritySvc authorityService; /** Il servizio di gestione dei contenuti. */ protected transient ContentSvc contentService; /** Il servizio di gestione del dizionario del content model. */ protected transient DictionarySvc dictionaryService; /** Il servizio di gestione del dizionario del content model. */ protected transient FileFolderSvc fileFolderService; /** Il servizio di gestione dei nodi. */ protected transient NodeSvc nodeService; /** Il servizio di gestione dei nodi eliminati. */ protected transient NodeArchiveSvc nodeArchiveService; /** Il servizio di gestione delle ownership. */ protected transient OwnableSvc ownableService; /** Il servizio di gestione dei permessi. */ protected transient PermissionSvc permissionService; /** Il servizio di gestione delle persone. */ protected transient PersonSvc personService; /** Il servizio di ricerca. */ protected transient SearchSvc searchService; /** Il servizio di gestione delle transazioni. */ protected transient TransactionSvc transactionService; /** Il servizio di gestione del lock. */ protected transient LockSvc lockService; /** Il servizio di gestione del checkout/checkin. */ protected transient CheckOutCheckInSvc checkOutCheckInService; /** Il servizio di copia dei contenuti. */ protected transient CopySvc copyService; /** Il servizio di gestione dl versioning. */ protected transient VersionSvc versionService; /** Il servizio di gestione delle action. */ protected transient ActionSvc actionService; /** Il servizio di gestione delle rule. */ protected transient RuleSvc ruleService; /** Il servizio di gestione dei tenant. */ protected transient TenantAdminSvc tenantAdminService; /** Il servizio di gestione dei content model dinamici. */ protected transient RepoAdminSvc repoAdminService; /** Il servizio di gestione dei job. */ protected transient JobSvc jobService; /** Il servizio di gestione degli audit. */ protected transient AuditSvc auditService; /** Il servizio di gestione degli audit trail. */ protected transient AuditTrailSvc auditTrailService; /** Il servizio di gestione dei mimetype */ protected transient MimetypeSvc mimetypeService; /** Il servizio di verifica di integrità degli indici */ protected transient IntegritySvc integrityService; /** Il servizio di gestione dei namespace */ protected transient NamespaceSvc namespaceService; /** Il servizio di riconoscimento dei formati dei file */ protected transient FileFormatSvc fileFormatService; /** Il servizio di gestione delle categorie */ protected transient CategorySvc categoryService; protected transient ExportSvc exporterService; protected transient ImportSvc importerService; /** * Seleziona il repository richiesto ed esegue l'autenticazione utilizzando * le informazioni specificate. * * <p>Le operazioni successive saranno eseguite sul repository che è stato selezionato * utilizzando questo metodo.</p> * * <p><strong>NB:</strong> se viene specificato un valore {@code null} viene impostato il * repository predefinito. Se si verifica un errore qualsiasi durante l'esecuzione viene eseguito il * rollback della transazione eventualmente specificata in input.</p> * * @param ctx L'oggetto {@link OperationContext} contenente le informazioni di autenticazione. * @param transaction La transazione di cui eseguire il rollback, oppure {@code null}. * * @throws InvalidParameterException Se uno dei parametri specificati non è valido. * @throws WrongCredentialsException Se le informazioni di autenticazione specificate sono errate. * @throws AuthenticationRuntimeException Se si verifica un errore generico nel servizio di autenticazione. */ public void authenticateOnRepository(OperationContext ctx, UserTransaction transaction) throws InvalidParameterException, AuthenticationRuntimeException { logger.debug("[EcmEnginePublisherBean::authenticateOnRepository] BEGIN"); try { // Set current repository. final String currentRepository = ctx.getRepository(); selectRepository(currentRepository, transaction); authenticationService.authenticate(ctx.getUsername(), ctx.getPassword().toCharArray()); if (logger.isDebugEnabled()) { logger.debug("[EcmEnginePublisherBean::authenticateOnRepository] Authenticated user \"" + ctx.getUsername() + "\" on repository \"" + currentRepository + "\""); } } catch (AuthenticationRuntimeException e) { logger.debug("[EcmEnginePublisherBean::authenticateOnRepository] " + "Got AuthenticationRuntimeException: " + e.getMessage()); if (transaction != null) { rollbackQuietely(transaction); } throw e; } finally { logger.debug("[EcmEnginePublisherBean::authenticateOnRepository] END"); } } /** * Verifica che il nodo specificato in input esista nel workspace sul repository dell'ECMENGINE. * * <p>Se il nodo non esiste ed è viene eseguito il <i>rollback</i> della transazione * eventualmente specificata.</p> * * <p><strong>NB:</strong> il controllo viene eseguito sul repository settato come corrente nel momento * in cui il metodo viene invocato. L'implementazione di questo metodo non prende in considerazione l'ID di * repository impostato nel DTO ricevuto in input.</p> * * @param node Il {@link Node} contente l'UID del nodo di cui verificare l'esistenza. * @param transaction La transazione corrente. * * @return Il riferimento al nodo, se esso esiste. * * @throws NoSuchNodeException Se il nodo non esiste o se si verifica un errore durante il controllo. */ protected NodeRef checkNodeExists(Node node, UserTransaction transaction) throws NoSuchNodeException { logger.debug("[EcmEnginePublisherBean::checkNodeExists] BEGIN"); final NodeRef nodeRef = new NodeRef(DictionarySvc.SPACES_STORE, node.getUid()); try { if (!nodeService.exists(nodeRef)) { logger.warn("[EcmEnginePublisherBean::checkNodeExists] Node not found: " + node.getUid()); if (transaction != null) { rollbackQuietely(transaction); } throw new NoSuchNodeException(node.getUid()); } return nodeRef; } catch (NodeRuntimeException e) { logger.error("[EcmEnginePublisherBean::checkNodeExists] Error while checking existance of node: " + nodeRef, e); if (transaction != null) { rollbackQuietely(transaction); } throw new NoSuchNodeException(node.getUid()); } finally { logger.debug("[EcmEnginePublisherBean::checkNodeExists] END"); } } /** * Verifica che il nodo specificato in input esista nell'archivio dei nodi eliminati sul * repository dell'ECMENGINE. * * <p>Se il nodo non esiste ed è viene eseguito il <i>rollback</i> della transazione * eventualmente specificata.</p> * * <p><strong>NB:</strong> il controllo viene eseguito sul repository settato come corrente nel momento * in cui il metodo viene invocato. L'implementazione di questo metodo non prende in considerazione l'ID di * repository impostato nel DTO ricevuto in input.</p> * * @param node Il {@link Node} contente l'UID del nodo di cui verificare l'esistenza. * @param transaction La transazione corrente. * * @return Il riferimento al nodo, se esso esiste. * * @throws NoSuchNodeException Se il nodo non esiste o se si verifica un errore durante il controllo. */ protected NodeRef checkNodeArchived(Node node, UserTransaction transaction) throws NoSuchNodeException { logger.debug("[EcmEnginePublisherBean::checkNodeArchived] BEGIN"); final NodeRef nodeRef = new NodeRef(DictionarySvc.ARCHIVE_SPACES_STORE, node.getUid()); try { if (!nodeService.exists(nodeRef)) { logger.warn("[EcmEnginePublisherBean::checkNodeArchived] " + "Node not found: " + node.getUid()); if (transaction != null) { rollbackQuietely(transaction); } throw new NoSuchNodeException(node.getUid()); } return nodeRef; } catch (NodeRuntimeException e) { logger.error("[EcmEnginePublisherBean::checkNodeArchived] Error while checking archived state of node: " + nodeRef, e); if (transaction != null) { rollbackQuietely(transaction); } throw new NoSuchNodeException(node.getUid()); } finally { logger.debug("[EcmEnginePublisherBean::checkNodeArchived] END"); } } protected String convertPropertyValueToString(Object value) { logger.debug("[EcmEnginePublisherBean::convertPropertyValueToString] BEGIN"); try { if (value == null) { return "-- null --"; } else if (value instanceof String || value instanceof Long || value instanceof Float || value instanceof Double || value instanceof Integer || value instanceof MLText || value instanceof ContentData || value instanceof Boolean || value instanceof NodeRef) { return value.toString(); } else if (value instanceof Date) { return ISO8601DateFormat.format((Date) value); } else { return "-- unknown type: " + value.getClass() + " --"; } } finally { logger.debug("[EcmEnginePublisherBean::convertPropertyValueToString] END"); } } /** * Registra sul logger dello stowpatch il tempo misurato al momento della chiamata. * * @param className Il nome della classe chiamante. * @param methodName Il nome del metodo chiamante. * @param ctx Il contesto in cui il metodo è stato chiamato. * @param message Un messaggio da registrare nel log assieme al tempo. */ protected void dumpElapsed(String className, String methodName, String ctx, String message) { this.stopwatch.dumpElapsed(className, methodName, ctx, message); } /** * Metodo richiamato all'attivazione di un'istanza del session bean. Nell'implementazione * corrente è vuoto. * * @throws EJBException Se si verificano errori durante l'esecuzione. * @throws RemoteException Se si verificano errori durante la comunicazione remota. */ public void ejbActivate() throws EJBException, RemoteException { } /** * Metodo chiamato dall'invocazione del metodo {@code create()} sulla * Home Interface dell'EJB di pubblicazione dei servizi. Esso si occupa del reperimento * degli EJB wrapper dei servizi applicativi, dell'inizializzazione del logger e dello * stopwatch. * * @throws EJBException Se si verificano errori durante l'inizializzazione dell'EJB. * @throws RemoteException Se si verificano errori durante la comunicazione remota. */ public void ejbCreate() throws EJBException, RemoteException { logger = LogFactory.getLog(ECMENGINE_BUSINESS_LOG_CATEGORY); logger.debug("[EcmEnginePublisherBean::ejbCreate] BEGIN"); try { this.initialContext = new InitialContext(); logger.debug("[EcmEnginePublisherBean::ejbCreate] Lookup dei servizi applicativi."); this.authenticationServiceHome = (AuthenticationSvcHome)lookup( FoundationBeansConstants.AUTHENTICATION_SERVICE_NAME_LOCAL); this.authorityServiceHome = (AuthoritySvcHome)lookup( FoundationBeansConstants.AUTHORITY_SERVICE_NAME_LOCAL); this.contentServiceHome = (ContentSvcHome)lookup( FoundationBeansConstants.CONTENT_SERVICE_NAME_LOCAL); this.dictionaryServiceHome = (DictionarySvcHome)lookup( FoundationBeansConstants.DICTIONARY_SERVICE_NAME_LOCAL); this.fileFolderServiceHome = (FileFolderSvcHome)lookup( FoundationBeansConstants.FILEFOLDER_SERVICE_NAME_LOCAL); this.namespaceServiceHome = (NamespaceSvcHome)lookup( FoundationBeansConstants.NAMESPACE_SERVICE_NAME_LOCAL); this.nodeServiceHome = (NodeSvcHome)lookup( FoundationBeansConstants.NODE_SERVICE_NAME_LOCAL); this.nodeArchiveServiceHome = (NodeArchiveSvcHome)lookup( FoundationBeansConstants.NODE_ARCHIVE_SERVICE_NAME_LOCAL); this.ownableServiceHome = (OwnableSvcHome)lookup( FoundationBeansConstants.OWNABLE_SERVICE_NAME_LOCAL); this.permissionServiceHome = (PermissionSvcHome)lookup( FoundationBeansConstants.PERMISSION_SERVICE_NAME_LOCAL); this.personServiceHome = (PersonSvcHome)lookup( FoundationBeansConstants.PERSON_SERVICE_NAME_LOCAL); this.searchServiceHome = (SearchSvcHome)lookup( FoundationBeansConstants.SEARCH_SERVICE_NAME_LOCAL); this.transactionServiceHome = (TransactionSvcHome)lookup( FoundationBeansConstants.TRANSACTION_SERVICE_NAME_LOCAL); this.lockServiceHome = (LockSvcHome)lookup( FoundationBeansConstants.LOCK_SERVICE_NAME_LOCAL); this.checkOutCheckInHome = (CheckOutCheckInSvcHome)lookup( FoundationBeansConstants.CHECKOUT_CHECKIN_NAME_LOCAL); this.copyHome = (CopySvcHome)lookup( FoundationBeansConstants.COPY_NAME_LOCAL); this.versionHome = (VersionSvcHome)lookup( FoundationBeansConstants.VERSION_NAME_LOCAL); this.actionHome = (ActionSvcHome)lookup( FoundationBeansConstants.ACTION_SERVICE_NAME_LOCAL); this.ruleHome = (RuleSvcHome)lookup( FoundationBeansConstants.RULE_SERVICE_NAME_LOCAL); this.tenantAdminHome = (TenantAdminSvcHome)lookup( FoundationBeansConstants.TENANT_ADMIN_SERVICE_NAME_LOCAL); this.repoAdminHome = (RepoAdminSvcHome)lookup( FoundationBeansConstants.REPO_ADMIN_SERVICE_NAME_LOCAL); this.jobHome = (JobSvcHome)lookup( FoundationBeansConstants.JOB_SERVICE_NAME_LOCAL); this.auditHome = (AuditSvcHome)lookup( FoundationBeansConstants.AUDIT_SERVICE_NAME_LOCAL); this.auditTrailHome = (AuditTrailSvcHome)lookup( FoundationBeansConstants.AUDIT_TRAIL_SERVICE_NAME_LOCAL); this.mimetypeHome = (MimetypeSvcHome)lookup( FoundationBeansConstants.MIMETYPE_SERVICE_NAME_LOCAL); this.integrityHome = (IntegritySvcHome)lookup( FoundationBeansConstants.INTEGRITY_SERVICE_NAME_LOCAL); this.fileFormatHome = (FileFormatSvcHome)lookup( FoundationBeansConstants.FILE_FORMAT_SERVICE_NAME_LOCAL); this.categoryHome = (CategorySvcHome)lookup( FoundationBeansConstants.CATEGORY_SERVICE_NAME_LOCAL); this.exporterHome = (ExportSvcHome)lookup( FoundationBeansConstants.EXPORTER_SERVICE_NAME_LOCAL); this.importerHome = (ImportSvcHome)lookup( FoundationBeansConstants.IMPORTER_SERVICE_NAME_LOCAL); logger.debug("[EcmEnginePublisherBean::ejbCreate] Creazione dei servizi applicativi."); this.authenticationService = this.authenticationServiceHome.create(); this.authorityService = this.authorityServiceHome.create(); this.contentService = this.contentServiceHome.create(); this.dictionaryService = this.dictionaryServiceHome.create(); this.nodeService = this.nodeServiceHome.create(); this.nodeArchiveService = this.nodeArchiveServiceHome.create(); this.ownableService = this.ownableServiceHome.create(); this.permissionService = this.permissionServiceHome.create(); this.personService = this.personServiceHome.create(); this.searchService = this.searchServiceHome.create(); this.transactionService = this.transactionServiceHome.create(); this.lockService = this.lockServiceHome.create(); this.checkOutCheckInService = this.checkOutCheckInHome.create(); this.copyService = this.copyHome.create(); this.versionService = this.versionHome.create(); this.actionService = this.actionHome.create(); this.ruleService = this.ruleHome.create(); this.tenantAdminService = this.tenantAdminHome.create(); this.repoAdminService = this.repoAdminHome.create(); this.jobService = this.jobHome.create(); this.auditService = this.auditHome.create(); this.auditTrailService = this.auditTrailHome.create(); this.mimetypeService = this.mimetypeHome.create(); this.integrityService = this.integrityHome.create(); this.namespaceService = this.namespaceServiceHome.create(); this.fileFolderService = this.fileFolderServiceHome.create(); this.fileFormatService = this.fileFormatHome.create(); this.categoryService = this.categoryHome.create(); this.exporterService = this.exporterHome.create(); this.importerService = this.importerHome.create(); } catch (NamingException e) { logger.error("[EcmEnginePublisherBean::ejbCreate] Errore nel lookup dei bean dei " + "servizi applicativi: " + e.getMessage()); throw new EJBException("Errore nel lookup dei bean dei servizi applicativi."); } catch (CreateException e) { logger.error("[EcmEnginePublisherBean::ejbCreate] Errore nella creazione dei bean dei" + "servizi applicativi: " + e.getMessage()); throw new EJBException("Errore nella creazione dei bean dei servizi applicativi."); } finally { logger.debug("[EcmEnginePublisherBean::ejbCreate] END"); } } /** * Metodo richiamato alla passivazione di un'istanza del session bean. Nell'implementazione * corrente è vuoto. * * @throws EJBException Se si verificano errori durante l'esecuzione. * @throws RemoteException Se si verificano errori durante la comunicazione remota. */ public void ejbPassivate() throws EJBException, RemoteException { } /** * Metodo richiamato alla distruzione di un'istanza del session bean. Nell'implementazione * corrente è vuoto. * * @throws EJBException Se si verificano errori durante l'esecuzione. * @throws RemoteException Se si verificano errori durante la comunicazione remota. */ public void ejbRemove() throws EJBException, RemoteException { } /** * Restituisce il context di esecuzione del session bean impostato dall'EJB container. * * @return Il context di esecuzione. */ protected SessionContext getSessionContext() { return this.sessionContext; } /** * Registra un record sul sistema di audit dell'ECMENGINE. * * @param className Il nome della classe chiamante. * @param methodName Il nome del metodo chiamante. * @param logContext Il contesto in cui il metodo è stato chiamato. * @param context L'oggetto {@link OperationContext} utilizzato per la chiamata al servizio. * @param idOggetto L'ID dell'oggetto modificato, creato o rimosso. * @param descrizioneOggetto La descrizione dell'oggetto modificato, creato o rimosso. */ protected void insertAudit(String className, String methodName, String logContext, OperationContext context, String idOggetto, String descrizioneOggetto) { try{ OperazioneAudit operazioneAudit = new OperazioneAudit(); operazioneAudit.setUtente(context.getNomeFisico()); operazioneAudit.setNomeOperazione(methodName); operazioneAudit.setServizio(className); operazioneAudit.setFruitore(context.getFruitore()); operazioneAudit.setDataOra(new Date()); operazioneAudit.setIdOggetto(idOggetto); operazioneAudit.setTipoOggetto(descrizioneOggetto); auditService.insertAudit(operazioneAudit); dumpElapsed(className, methodName, logContext, "Audit inserito."); } catch (Exception e) { logger.error("[" + className + "::" + methodName + "] Errore nell'inserimento Audit: " + e.getMessage()); } } /** * Esegue il lookup di un EJB arbitrario usando l'{@code InitialContext} unico * definito all'inizializzazione di un'istanza di {@code EcmEnginePublisherBean}. * * <p><strong>NB:</strong> il risultato va castato opportunamente.</p> * * @param ejbName Il nome della Home Interface da localizzare. * * @return L'istanza della Home Interface da utilizzare per creare una nuova istanza dell'EJB. * * @throws NamingException Se si verifica un errore durante il lookup. */ protected Object lookup(String ejbName) throws NamingException { Object home; if (this.initialContext == null) { return null; } home = this.initialContext.lookup(ejbName); if( logger.isDebugEnabled() ) { logger.debug("[EcmEnginePublisherBean::lookup] Looked up EJB \"" + ejbName + "\": " + home); } return home; } /** * Metodo richiamato dall'EJB container per impostare il context di esecuzione del bean stesso. * * @param context Il contesto di esecuzione. * * @throws EJBException Se si verificano errori durante l'esecuzione. * @throws RemoteException Se si verificano errori durante la comunicazione remota. */ public void setSessionContext(SessionContext context) throws EJBException, RemoteException { this.sessionContext = context; } /** * Azzera e avvia la misurazione dei tempi da parte dello stopwatch. */ protected void start() { this.stopwatch = new StopWatch(ECMENGINE_STOPWATCH_LOG_CATEGORY); this.stopwatch.start(); } /** * Arresta la misurazione dei tempi da parte dello stopwatch. */ protected void stop() { this.stopwatch.stop(); } /** * Controlla se almeno uno degli argomenti in input nell'inserimento o ricerca * dell'audit trail sia valorizzato. * * @param user utente che ha eseguito l'operazione su un contenuto del repository * @param operazione l'operazione eseguita su un contenuto del repository * @param idOggetto identificativo del contenuto * @return {@code true} se almento un attributo è valorizzato,{@code false} altrimenti. */ protected static boolean isValidLogTrailArgument(String user, String operazione, String idOggetto) { if(user!=null || operazione !=null || idOggetto!=null) return true; return false; } /** * Traduce una mappa di metadati ricevuta in input nel corispondente array di oggetti * {@link ResultProperty}. * * @param props La {@code Map} da tradurre. * * @return Un array di {@link ResultProperty}. */ protected ResultProperty [] translatePropertyMap(Map<QName, Serializable> props,Property[] properties) { logger.debug("[EcmEnginePublisherBean::translatePropertyMap] BEGIN"); ResultProperty current = null; ArrayList<ResultProperty> propArray = null; try { if (props == null) { return null; } propArray = new ArrayList<ResultProperty>(); logger.debug("[EcmEnginePublisherBean::translatePropertyMap] Creazione array metadati."); //AF: se non sono richieste proprieta' particolari, vengono restituite tutte le propieta' if(properties==null||properties.length==0){ // Ciclo sulle proprieta` int index = 0; for (Map.Entry<QName, Serializable> entry : props.entrySet()) { ResultProperty rp = new ResultProperty(); final QName propName = entry.getKey(); final Serializable v = entry.getValue(); rp.setPrefixedName(dictionaryService.resolveQNameToPrefixName(propName)); if (v instanceof Collection<?>) { Collection<?> valuesCollection = (Collection<?>) v; String values [] = new String[valuesCollection.size()]; int j = 0; for (Object o : valuesCollection) { values[j] = convertPropertyValueToString(o); j++; } rp.setMultivalue(true); rp.setValues(values); } else { rp.setMultivalue(false); rp.setValues(new String [] { convertPropertyValueToString(v) }); } if( logger.isDebugEnabled() ) { StringBuffer aOut = new StringBuffer(); for( String p : rp.getValues() ){ aOut.append( p +" " ); } logger.debug("[EcmEnginePublisherBean::translatePropertyMap] " +rp.getPrefixedName() +" = " +aOut.toString()); } propArray.add(rp); index++; } } //AF: se sono richieste proprieta' particolari, viene risolto il nome con il prefisso (prefixedName, ad esempio cm:content) convertendo il prefisso nel percorso dello schema di riferimento, e viene inserita solo quella proprieta' else{ for(Property prop:properties){ ResultProperty rp = new ResultProperty(); QName propName = dictionaryService.resolvePrefixNameToQName(prop.getPrefixedName()); Serializable v = props.get(propName); if(propName!=null&&v!=null){ rp.setPrefixedName(dictionaryService.resolveQNameToPrefixName(propName)); if (v instanceof Collection<?>) { Collection<?> valuesCollection = (Collection<?>) v; String values [] = new String[valuesCollection.size()]; int j = 0; for (Object o : valuesCollection) { values[j] = convertPropertyValueToString(o); j++; } rp.setMultivalue(true); rp.setValues(values); } else { rp.setMultivalue(false); rp.setValues(new String [] { convertPropertyValueToString(v) }); } if( logger.isDebugEnabled() ) { StringBuffer aOut = new StringBuffer(); for( String p : rp.getValues() ){ aOut.append( p +" " ); } logger.debug("[EcmEnginePublisherBean::translatePropertyMap] " +rp.getPrefixedName() +" = " +aOut.toString()); } propArray.add(rp); } } } } catch (DictionaryRuntimeException e) { logger.warn("[EcmEnginePublisherBean::translatePropertyMap] " + "Errore nella traduzione della property " + current.getPrefixedName() + ": property sconosciuta!"); } finally { logger.debug("[EcmEnginePublisherBean::translatePropertyMap] END"); } return propArray.toArray(new ResultProperty[propArray.size()]); } /** * Estrae un insieme ridotto dei metadati di un contenuto da utilizzare nel result set * di una ricerca. * * <p>I metadati estratti da questo metodo sono i seguenti:</p> * <ul> * <li>{@code cm:name}: nome del contenuto.</li> * <li>{@code cm:created}: data di creazione.</li> * <li>{@code cm:creator}: creatore.</li> * <li>{@code cm:modified}: data di ultima modifica.</li> * <li>{@code cm:modifier}: autore dell'ultima modifica.</li> * <li>{@code sys:store-identifier}: identificativo dello store.</li> * <li>{@code sys:store-protocol}: protocollo di accesso allo store.</li> * </ul> * * @param props La {@code Map} completa contenente i metadati. * * @return Un array contenente una parte dei metadati del contenuto. */ protected ResultProperty [] translateReducedPropertyMap(Map<QName, Serializable> props) { logger.debug("[EcmEnginePublisherBean::translateReducedPropertyMap] BEGIN"); try { Vector<ResultProperty> propVector = new Vector<ResultProperty>(7); logger.debug("[EcmEnginePublisherBean::translateReducedPropertyMap] Creazione array metadati ridotto: 7"); // Ciclo sulle proprieta` // cm:name ResultProperty propName = new ResultProperty(); propName.setPrefixedName("cm:name"); propName.setValues(new String [] { (String) props.get(ContentModel.PROP_NAME) }); propVector.add(propName); propName = null; // cm:created Date rawCreationDate = (Date) props.get(ContentModel.PROP_CREATED); if (rawCreationDate != null) { ResultProperty propCreationDate = new ResultProperty(); propCreationDate.setPrefixedName("cm:created"); propCreationDate.setValues(new String [] { ISO8601DateFormat.format(rawCreationDate) }); propVector.add(propCreationDate); propCreationDate = null; rawCreationDate = null; } // cm:creator String rawCreator = (String) props.get(ContentModel.PROP_CREATOR); if (rawCreator != null) { ResultProperty propCreator = new ResultProperty(); propCreator.setPrefixedName("cm:creator"); propCreator.setValues(new String [] { rawCreator }); propVector.add(propCreator); propCreator = null; rawCreator = null; } // cm:modified Date rawModifiedDate = (Date) props.get(ContentModel.PROP_MODIFIED); if (rawModifiedDate != null) { ResultProperty propModifiedDate = new ResultProperty(); propModifiedDate.setPrefixedName("cm:modified"); propModifiedDate.setValues(new String [] { ISO8601DateFormat.format(rawModifiedDate) }); propVector.add(propModifiedDate); propModifiedDate = null; rawCreationDate = null; } // cm:modifier String rawModifier = (String) props.get(ContentModel.PROP_MODIFIER); if (rawModifier != null) { ResultProperty propModifier = new ResultProperty(); propModifier.setPrefixedName("cm:modifier"); propModifier.setValues(new String [] { rawCreator }); propVector.add(propModifier); propModifier = null; rawModifier = null; } // sys:store-identifier ResultProperty propStoreId = new ResultProperty(); propStoreId.setPrefixedName("sys:store-identifier"); propStoreId.setValues(new String [] { (String) props.get(ContentModel.PROP_STORE_IDENTIFIER) }); propVector.add(propStoreId); propStoreId = null; // sys:store-protocol ResultProperty propStoreProtocol = new ResultProperty(); propStoreProtocol.setPrefixedName("sys:store-protocol"); propStoreProtocol.setValues(new String [] { (String) props.get(ContentModel.PROP_STORE_PROTOCOL) }); propVector.add(propStoreProtocol); propStoreProtocol = null; return propVector.toArray(new ResultProperty[] {}); } finally { logger.debug("[EcmEnginePublisherBean::translateReducedPropertyMap] END"); } } protected void handleTransactionException(Throwable ex, String msg) throws EcmEngineTransactionException { logger.warn("[EcmEnginePublisherBean::handleTransactionException] Error in transaction: " + msg, ex); throw new EcmEngineTransactionException(msg); } protected enum ValidationType { NOT_NULL, NODE, OPERATION_CONTEXT, SEARCH_PARAMETER, AUDIT_INFO, PREFIXED_NAME, PREFIX, NAME, NOT_GUEST, PASSWORD, CONTENT_ITEM, ASPECT, PROPERTY, CONTENT_READ, CONTENT_WRITE_CONTENT, CONTENT_WRITE_METADATA, CONTENT_WRITE_NEW, ASSOCIATION, ACL_RECORD, USER, GROUP, GROUP_NOT_EMAIL_CONTRIBUTORS, ASSOC_TYPE, ENCRYPTION_INFO_ENCRYPT, ENCRYPTION_INFO_DECRYPT, RULE_TYPE, DATA_ARCHIVE, ARCHIVE_FORMAT, XPATH, XPATH_AGGREGATE, LUCENE, TENANT, CUSTOM_MODEL, BYTE_ARRAY, CATEGORY, CATEGORY_ROOT, CATEGORY_ASPECT, DEPTH, MODE, MASSIVE_CREATE_CONTENT, IS_ZERO, NOT_ZERO, MASSIVE_UPDATE_METADATA, MASSIVE_RETRIEVE, MASSIVE_RETRIEVE_SIZE, MASSIVE_GET_METADATA, MASSIVE_DELETE_CONTENT } /** * Esegue la validazione del parametro specificato. * * <p><strong>NB:</strong> questo metodo è pensato per essere utilizzato <strong>fuori</strong> da una * transazione. <i>Nel caso venisse utilizzato dentro una transazione il chiamante deve gestire la condizione di errore * prevedendo il rollback della transazione stessa.</i></p> * * @see ValidationType * * @param type Il tipo di validazione da eseguire. * @param paramName Il nome del parametro da validare. * @param paramValue Il valore del parametro da validare. * * @throws InvalidParameterException Se la validazione fallisce. */ protected void validate(ValidationType type, String paramName, Object paramValue) throws InvalidParameterException { logger.debug("[EcmEnginePublisherBean::validate] BEGIN"); try { if (paramValue == null) { final String errorMessage = "Parameter validation failed for type '" + type.toString() + "' -- null parameter: " + paramName; logger.warn("[EcmEnginePublisherBean::validate] " + errorMessage); throw new InvalidParameterException(errorMessage); } boolean isValid = false; String objDescription = null; switch (type) { case NOT_NULL: isValid = true; // Se l'esecuzione arriva a questo punto l'oggetto non puo` essere null. break; case NODE: isValid = isValidNode((Node) paramValue); objDescription = "U: " + ((Node) paramValue).getUid(); break; case OPERATION_CONTEXT: isValid = isValidOperationContext((OperationContext) paramValue); objDescription = "U: " + ((OperationContext) paramValue).getUsername() + " - F: " + ((OperationContext) paramValue).getFruitore(); break; case SEARCH_PARAMETER: isValid = isValidSearchParameter((AuditInfo) paramValue); objDescription = "U: " + ((AuditInfo) paramValue).getUtente() + " - OP: " + ((AuditInfo) paramValue).getOperazione() + " - ID: " + ((AuditInfo) paramValue).getIdOggetto(); break; case AUDIT_INFO: isValid = isValidAuditInfo((AuditInfo) paramValue); objDescription = "U: " + ((AuditInfo) paramValue).getUtente() + " - OP: " + ((AuditInfo) paramValue).getOperazione() + " - ID: " + ((AuditInfo) paramValue).getIdOggetto(); break; case PREFIXED_NAME: isValid = isValidPrefixedName((String) paramValue); objDescription = "PN: " + (String) paramValue; break; case PREFIX: isValid = isValidPrefix((String) paramValue); objDescription = "P: " + (String) paramValue; break; case NAME: isValid = isValidName((String) paramValue); objDescription = "N: " + (String) paramValue; break; case NOT_GUEST: isValid = isValidNotGuest((String) paramValue); objDescription = "N: " + (String) paramValue; break; case PASSWORD: isValid = isValidPassword((char[]) paramValue); objDescription = "P: " + new String((char[]) paramValue); break; case CONTENT_ITEM: isValid = isValidContentItem((ContentItem) paramValue); objDescription = "PN: " + ((ContentItem) paramValue).getPrefixedName(); break; case ASPECT: isValid = isValidAspect((Aspect) paramValue); objDescription = "PN: " + ((Aspect) paramValue).getPrefixedName(); break; case PROPERTY: isValid = isValidProperty((Property) paramValue); objDescription = "PN: " + ((Property) paramValue).getPrefixedName() + " - T: " + ((Property) paramValue).getDataType(); break; case CONTENT_READ: isValid = isValidContent((Content) paramValue, ValidationType.CONTENT_READ); objDescription = "PN: " + ((Content) paramValue).getPrefixedName() + " - CPPN: " + ((Content) paramValue).getContentPropertyPrefixedName(); break; case CONTENT_WRITE_NEW: isValid = isValidContent((Content) paramValue, ValidationType.CONTENT_WRITE_NEW); objDescription = "PN: " + ((Content) paramValue).getPrefixedName() + " - PAT: " + ((Content) paramValue).getParentAssocTypePrefixedName() + " - T: " + ((Content) paramValue).getTypePrefixedName() + " - CPPN: " + ((Content) paramValue).getContentPropertyPrefixedName(); break; case CONTENT_WRITE_METADATA: isValid = isValidContent((Content) paramValue, ValidationType.CONTENT_WRITE_METADATA); objDescription = "CPPN: " + ((Content) paramValue).getContentPropertyPrefixedName() + " - A: " + (((Content) paramValue).getAspects() != null ? ((Content) paramValue).getAspects().length : "null"); break; case CONTENT_WRITE_CONTENT: isValid = isValidContent((Content) paramValue, ValidationType.CONTENT_WRITE_CONTENT); objDescription = "CPPN: " + ((Content) paramValue).getContentPropertyPrefixedName() + " - MT: " + ((Content) paramValue).getMimeType() + " - ENC: " + ((Content) paramValue).getEncoding(); break; case ASSOCIATION: isValid = isValidAssociation((Association) paramValue); objDescription = "PN: " + ((Association) paramValue).getPrefixedName() + " - T: " + ((Association) paramValue).getTypePrefixedName(); break; case ACL_RECORD: isValid = isValidAclRecord((AclRecord) paramValue); objDescription = "A: " + ((AclRecord) paramValue).getAuthority() + " - P: " + ((AclRecord) paramValue).getPermission(); break; case USER: isValid = isValidUser((User) paramValue); if( paramValue==null ){ objDescription = "U: null"; } else { String cUserName = ((User) paramValue).getUsername(); objDescription = "U: " + cUserName; objDescription += " N: " + ((User) paramValue).getName(); objDescription += " S: " + ((User) paramValue).getSurname(); if( cUserName!=null ){ objDescription += " U: LEN " + cUserName.length() + " MAXLEN " +(USERNAME_MAX_LENGTH-1); } } break; case GROUP: isValid = isValidGroup((Group) paramValue); objDescription = "G: " + ((Group) paramValue).getName(); break; case GROUP_NOT_EMAIL_CONTRIBUTORS: isValid = isValidGroupNotEmailContributors((Group) paramValue); objDescription = "G: " + ((Group) paramValue).getName(); break; case ASSOC_TYPE: isValid = isValidAssocType((String) paramValue); objDescription = "A: " + ((String) paramValue); break; case ENCRYPTION_INFO_ENCRYPT: isValid = isValidEncryptionInfo((EncryptionInfo) paramValue, false); objDescription = "A: " + ((EncryptionInfo) paramValue).getAlgorithm() + " - KID: " + ((EncryptionInfo) paramValue).getKeyId(); break; case ENCRYPTION_INFO_DECRYPT: isValid = isValidEncryptionInfo((EncryptionInfo) paramValue, true); objDescription = "A: " + ((EncryptionInfo) paramValue).getAlgorithm() + " - K: " + ((EncryptionInfo) paramValue).getKey(); break; case RULE_TYPE: isValid = isValidRuleType((String) paramValue); objDescription = "RT: " + (String) paramValue; break; case DATA_ARCHIVE: isValid = isValidDataArchive((DataArchive) paramValue); objDescription = "F: " + ((DataArchive) paramValue).getFormat() + " - CPN: " + ((DataArchive) paramValue) .getMappedContainerNamePropertyPrefixedName() + " - CT: " + ((DataArchive) paramValue) .getMappedContainerTypePrefixedName(); break; case ARCHIVE_FORMAT: isValid = isValidArchiveFormat((String) paramValue); objDescription = "F: " + (String) paramValue; break; case XPATH: isValid = isValidXpath((SearchParams) paramValue); objDescription = "XQ: " + ((SearchParams) paramValue).getXPathQuery(); break; case XPATH_AGGREGATE: isValid = isValidXpathAggregate((SearchParamsAggregate) paramValue); objDescription = "XQ: " + ((SearchParamsAggregate) paramValue).getXPathQuery(); break; case LUCENE: isValid = isValidLucene((SearchParams) paramValue); objDescription = "LQ: " + ((SearchParams) paramValue).getLuceneQuery(); break; case TENANT: isValid = isValidTenant((Tenant) paramValue); objDescription = "T: " + ((Tenant) paramValue); break; case CUSTOM_MODEL: isValid = isValidCustomModel((CustomModel) paramValue); objDescription = "CM: " + ((CustomModel) paramValue); break; case BYTE_ARRAY: isValid = isValidByteArray((byte[]) paramValue); objDescription = "BA: " + ((byte[]) paramValue); break; case CATEGORY: isValid = isValidCategory((Category) paramValue); objDescription = "CATEGORY: " + ((Category) paramValue); break; case CATEGORY_ROOT: isValid = isValidRootCategory((Category) paramValue); objDescription = "CATEGORY ROOT: " + ((Category) paramValue); break; case DEPTH: isValid = isValidCategoryDepth((String) paramValue); objDescription = "DEPTH CATEGORY : " + ((String) paramValue); break; case MODE: isValid = isValidCategoryMode((String) paramValue); objDescription = "MODE CATEGORY : " + ((String) paramValue); break; case CATEGORY_ASPECT: isValid = isValidCategoryAspect((Category) paramValue); objDescription = "CATEGORY ASPECT: " + ((Category) paramValue); break; case IS_ZERO: isValid=isValidZero((Long)paramValue); break; case NOT_ZERO: isValid=isValidNotZero((Long)paramValue); break; case MASSIVE_CREATE_CONTENT: isValid = isValidMassiveNumberOfContents((Content[])paramValue)&&isValidMassiveSizeOfContents((Content[])paramValue); objDescription = "CONTENTS MAX NUMBER: "+MASSIVE_MAX_CREATE_NUMBER+"\nCONTENTS MAX SIZE: "+MASSIVE_MAX_CREATE_SIZE; break; case MASSIVE_UPDATE_METADATA: isValid = isValidMassiveNumberOfContents((Content[])paramValue); objDescription = "CONTENTS MAX NUMBER: "+MASSIVE_MAX_CREATE_NUMBER; break; case MASSIVE_RETRIEVE: isValid = isValidMassiveNumberOfRetrieve((Node[])paramValue); objDescription = "NODES MAX NUMBER: "+MASSIVE_MAX_RETRIEVE_NUMBER; break; case MASSIVE_RETRIEVE_SIZE: isValid = isValidMassiveNumberOfRetrieveSize((Long)paramValue); objDescription = "RETRIEVE MAX SIZE: "+MASSIVE_MAX_RETRIEVE_SIZE; break; case MASSIVE_GET_METADATA: isValid = isValidMassiveNumberOfGetMetadata((Long)paramValue); objDescription = "GET MAX SIZE: "+MASSIVE_MAX_GET_METADATA_SIZE; break; case MASSIVE_DELETE_CONTENT: isValid = isValidMassiveNumberOfDelete((Node[])paramValue); objDescription = "NODES MAX NUMBER: "+MASSIVE_MAX_DELETE_NUMBER+"\nCONTENTS MAX SIZE: "+MASSIVE_MAX_CREATE_SIZE; break; } if (!isValid) { String errorMessage = "Parameter validation failed for type '" + type.toString() + "' -- invalid parameter: " + paramName + " [" + objDescription + "]"; logger.warn("[EcmEnginePublisherBean::validate] " + errorMessage); throw new InvalidParameterException(errorMessage); } } finally { logger.debug("[EcmEnginePublisherBean::validate] END"); } } /** * Controlla se un'operazione fra i repository specificati è <i>cross-repository</i>. * * <p>Un'operazione è considerata <i>cross-repository</i> se coinvolge un nodo * sorgente e un nodo destinazione che appartengono a due repository diversi.</p> * * @param repositoryA Il primo repository coinvolto nell'operazione. * @param repositoryB Il secondo repository coinvolto nell'operazione. * * @return {@code true} se i repository specificati sono diversi, {@code false} * se sono uguali o nessuno dei due è definito. */ protected static boolean isCrossRepository(String repositoryA, String repositoryB) { final boolean aSpecified = isValidName(repositoryA); final boolean bSpecified = isValidName(repositoryB); if (!aSpecified && !bSpecified) { return false; } if ((aSpecified && bSpecified) && repositoryA.equals(repositoryB)) { return false; } return true; } /** * Controlla se una generica istanza di {@link AclRecord} è valida. * * <p>Un {@link AclRecord} deve rispettare le seguenti condizioni:</p> * <ul> * <li>la sua {@code authority} deve essere un nome con prefisso valido * secondo quanto definito in {@link #isValidPrefixedName(String)};</li> * <li>la sua {@code permission} deve essere un nome con prefisso valido * secondo quanto definito in {@link #isValidPrefixedName(String)}.</li> * </ul> * * @param acl Il {@link AclRecord} da controllare. * * @return {@code true} se è una {@link AclRecord} valida, * {@code false} altrimenti. */ protected static boolean isValidAclRecord(AclRecord acl) { return (acl != null && acl.getAuthority()!=null && acl.getAuthority().length()<101) ? isValidName(acl.getAuthority()) && isValidName(acl.getPermission()) : false; } /** * Controlla se la stringa specificata è un formato di archivio valido. * * <p>Il formato deve assumere uno dei seguienti valori:</p> * <ul> * <li>{@code EcmEngineConstants.ECMENGINE_ARCHIVE_FORMAT_TAR} * <li>{@code EcmEngineConstants.ECMENGINE_ARCHIVE_FORMAT_TAR_GZ} * <li>{@code EcmEngineConstants.ECMENGINE_ARCHIVE_FORMAT_ZIP} * </ul> * * @param format Il formato dell'archivio. * * @return {@code true} se è un formato di archivio valido, * {@code false} altrimenti. * * @see EcmEngineConstants */ protected static boolean isValidArchiveFormat(String format) { return (EcmEngineConstants.ECMENGINE_ARCHIVE_FORMAT_TAR.equals(format) || EcmEngineConstants.ECMENGINE_ARCHIVE_FORMAT_TAR_GZ.equals(format) || EcmEngineConstants.ECMENGINE_ARCHIVE_FORMAT_ZIP.equals(format)); } /** * Controlla se una generica istanza di {@link Aspect} è valida. * * <p>Un {@link Aspect} deve rispettare le seguenti condizioni:</p> * <ul> * <li>deve essere un {@link ContentItem} valido secondo quanto definito * in {@link #isValidContentItem(ContentItem)}.</li> * </ul> * * @param aspect L'{@link Aspect} da controllare. * * @return {@code true} se è un {@link Aspect} valido, * {@code false} altrimenti. */ protected static boolean isValidAspect(Aspect aspect) { return (aspect != null) ? isValidContentItem(aspect) : false; } /** * Controlla se una generica istanza di {@link Association} è valida. * * <p>Una {@link Association} deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code prefixedName}, solo se l'associazione è di tipo padre-figlio, * deve essere un nome con prefisso valido secondo quanto definito * in {@link #isValidPrefixedName(String)};</li> * <li>il suo {@code typePrefixedName} deve essere un nome con prefisso valido * secondo quanto definito in {@link #isValidPrefixedName(String)};</li> * </ul> * * @param association La {@link Association} da controllare. * * @return {@code true} se è una {@link Association} valida, * {@code false} altrimenti. */ protected static boolean isValidAssociation(Association association) { if (association != null){ if (association.isChildAssociation()) { if (isValidPrefixedName(association.getPrefixedName()) && isValidPrefixedName(association.getTypePrefixedName())) return true; } else { if (isValidPrefixedName(association.getTypePrefixedName())) return true; } } return false; } /** * Controlla se il tipo delle associazioni da ricercare è valido. * * <p>Il tipo di un'associazione può essere:</p> * <ul> * <li>PARENT</li> * <li>CHILD</li> * <li>TARGET</li> * <li>SOURCE</li> * </ul> * * @param assocType il tipo di associazione da controllare. * * @return {@code true} se è un tipo valido, * {@code false} altrimenti. */ protected static boolean isValidAssocType(String assocType) { if (assocType != null) { if (assocType.equals(ECMENGINE_ASSOC_TYPE_PARENT) || (assocType.equals(ECMENGINE_ASSOC_TYPE_CHILD)) || (assocType.equals(ECMENGINE_ASSOC_TYPE_SOURCE)) || (assocType.equals(ECMENGINE_ASSOC_TYPE_TARGET))) { return true; } } return false; } /** * Controlla se la profondita di ricerca delle categorie è valida. * * <p>La profondita di ricerca delle categorie può essere:</p> * <ul> * <li>IMMEDIATE</li> * <li>ANY</li> * </ul> * * @param depth il depth di ricerca categorie da controllare. * * @return {@code true} se è un depth valido, * {@code false} altrimenti. */ protected static boolean isValidCategoryDepth(String depth) { if (depth != null) { if (depth.equals(ECMENGINE_DEPTH_IMMEDIATE) || depth.equals(ECMENGINE_DEPTH_ANY)) { return true; } } return false; } /** * Controlla se il tipo di elemento da ricercare nelle categorie è valido. * * <p>Il tipo di elemento da ricercare nelle categorie può essere:</p> * <ul> * <li>MEMBERS</li> * <li>SUB_CATEGORIES</li> * <li>ALL</li> * </ul> * * @param mode il tipo di elemento da ricercare nelle categorie da controllare. * * @return {@code true} se è un mode valido, * {@code false} altrimenti. */ protected static boolean isValidCategoryMode(String mode) { if (mode != null) { if (mode.equals(ECMENGINE_MODE_ALL) || mode.equals(ECMENGINE_MODE_MEMBERS) || mode.equals(ECMENGINE_MODE_SUB_CATEGORY)) { return true; } } return false; } /** * Controlla se una generica istanza di {@link AuditInfo} è valida per * l'inserimento nella tavola di audit trail. * * <p>Uno dei seguenti attributi deve essere valorizzato affinchè possa * essere utilizzato per l'inserimento:</p> * <ul> * <li>utente</li> * <li>operazione</li> * <li>idOggetto</li> * </ul> * * @param auditTrail Il {@link AuditInfo} da controllare. * * @return {@code true} se è un {@link AuditInfo} valido,{@code false} altrimenti. */ protected static boolean isValidAuditInfo(AuditInfo auditTrail){ if (auditTrail!=null){ if (auditTrail.getUtente() != null || auditTrail.getOperazione() != null || auditTrail.getIdOggetto() != null) { return true; } } return false; } /** * Controlla se una generica istanza di {@link Content} è valida. * * <p>Un {@link Content} deve rispettare le seguenti condizioni quando viene usato * in operazioni di scrittura di un nuovo contenuto:</p> * <ul> * <li>deve essere un {@link ContentItem} valido secondo quanto definito * in {@link #isValidContentItem(ContentItem)};</li> * <li>il suo {@code parentAssocTypePrefixedName} deve essere un nome con prefisso valido * secondo quanto definito in {@link #isValidPrefixedName(String)};</li> * <li>il suo {@code typePrefixedName} deve essere un nome con prefisso valido * secondo quanto definito in {@link #isValidPrefixedName(String)};</li> * <li>la sua {@code contentPropertyPrefixedName}, se è settata, deve essere un nome con * prefisso valido secondo quanto definito in {@link #isValidPrefixedName(String)};</li> * <li>se è settata una {@code contentPropertyPrefixedName} valida devono essere specificati anche * MIME-Type, encoding e contenuto non nulli.</li> * </ul> * * <p>Un {@link Content} deve rispettare le seguenti condizioni quando viene usato * in operazioni di aggiornamento di un contenuto:</p> * <ul> * <li>la sua {@code contentPropertyPrefixedName}, se è settata, deve essere un nome con * prefisso valido secondo quanto definito in {@link #isValidPrefixedName(String)};</li> * <li>se è settata una {@code contentPropertyPrefixedName} valida devono essere specificati anche * MIME-Type, encoding e contenuto non nulli.</li> * </ul> * * <p>Un {@link Content} deve rispettare le seguenti condizioni quando viene usato * in operazioni di aggiornamento dei metadadi di un contenuto:</p> * <ul> * <li>la sua {@code contentPropertyPrefixedName}, il MIME-Type, l'encoding e il content non devono essere * settati;</li> * <li>l'array di {@link Aspect} deve essere settato (tipicamente conterrà almeno i due aspect * {@code sys:referenceable} e {@code cm:auditable}).</li> * </ul> * * <p>Un {@link Content} deve rispettare le seguenti condizioni quando viene usato * in operazioni di lettura:</p> * <ul> * <li>la sua {@code contentPropertyPrefixedName}, se è settata, deve essere un nome con * prefisso valido secondo quanto definito in {@link #isValidPrefixedName(String)}.</li> * </ul> * * @param content Il {@link Content} da controllare. * @param type Il {@link ValidationType} da utilizzare. Sono validi solo i tipi {@code CONTENT_READ} * e {@code CONTENT_WRITE_*}. * * @return {@code true} se è un {@link Content} valido, * {@code false} altrimenti. */ protected static boolean isValidContent(Content content, ValidationType type) { final boolean contentPropertyValidForWrite = (content.getContentPropertyPrefixedName() != null) ? content.getMimeType() != null && content.getContent() != null && content.getEncoding() != null : content.getMimeType() == null && content.getContent() == null && content.getEncoding() == null; switch (type) { case CONTENT_READ: return isValidPrefixedName(content.getContentPropertyPrefixedName()); case CONTENT_WRITE_NEW: return isValidContentItem(content) && contentPropertyValidForWrite && isValidPrefixedName(content.getTypePrefixedName()) && isValidPrefixedName(content.getParentAssocTypePrefixedName()); case CONTENT_WRITE_CONTENT: return contentPropertyValidForWrite; case CONTENT_WRITE_METADATA: /* * 21-05-2008 * * La validazione approfondita e` stata rimossa per ripristinare la compatibilita` * con l'applicativo CRECEDO. Vengono validati solo i parametri effettivamente * richiesti dalle operazioni di scrittura metadati. */ // return content.getContentPropertyPrefixedName() == null // && content.getMimeType() == null // && content.getEncoding() == null // && content.getContent() == null // && content.getAspects() != null; return content.getAspects() != null; default: // Tipo di validazione errato return false; } } /** * Controlla se una generica istanza di {@link ContentItem} è valida. * * <p>Un {@link ContentItem} deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code prefixedName} deve essere un nome con prefisso valido * secondo quanto definito in {@link #isValidPrefixedName(String)}.</li> * </ul> * * @param item Il {@link ContentItem} da controllare. * * @return {@code true} se è un {@link ContentItem} valido, * {@code false} altrimenti. */ protected static boolean isValidContentItem(ContentItem item) { return (item != null) ? isValidPrefixedName(item.getPrefixedName()) : false; } /** * Controlla se il DTO {@link DataArchive} specificato è valido per operazioni * di importazione di contenuti. * * <p>Un {@link DataArchive} deve rispettare le seguenti condizioni:</p> * <ul> * <li>deve essere diverso da {@code null};</li> * <li>il suo campo {@code format} deve essere una stringa valida secondo quanto * definito in {@link #isValidName(String)};</li> * <li>il suo campo {@code content} deve essere una array di byte diverso da null * e di lunghezza maggiore di zero.</li> * </ul> * * @param dataArchive L'{@link EncryptionInfo} da controllare. * * @return {@code true} se è un {@link DataArchive} valido, * {@code false} altrimenti. */ protected static boolean isValidDataArchive(DataArchive dataArchive) { return (dataArchive != null) ? isValidName(dataArchive.getFormat()) && dataArchive.getContent() != null && dataArchive.getContent().length > 0 : false; } /** * Controlla se il DTO {@link EncryptionInfo} specificato è valido per operazioni * di criptazione o decriptazione. * * <p>Un {@link EncryptionInfo} deve rispettare le seguenti condizioni:</p> * <ul> * <li>deve essere diverso da {@code null};</li> * <li>il suo campo {@code key} deve essere una stringa valida secondo quanto * definito in {@link #isValidName(String)}, <i>a meno che il contenuto non sia criptato alla fonte * e l'operazione sia una criptazione</i>;</li> * <li>se il contenuto &ergave; criptato alla fonte l'IV sorgente deve essere specificato * (<i>solo nel caso di operazioni di criptazione</i>);</li> * <li>il suo campo {@code algorithm} deve essere una stringa valida secondo quanto * definito in {@link #isValidName(String)};</li> * <li>i campi {@code mode} e {@code padding} devono essere entrambi specificati oppure nessuno dei due deve essere * specificato;</li> * <li>il suo campo {@code sourceIv} deve essere valorizzato con una stringa BASE64 se viene caricato * un contenuto già criptato con modalità di criptazione non specificata oppure diversa da ECB;</li> * <li>il suo campo {@code keyId} deve essere una stringa valida secondo quanto * definito in {@link #isValidName(String)} (<i>solo nel caso di operazioni di criptazione</i>).</li> * </ul> * * @param encInfo L'{@link EncryptionInfo} da controllare. * @param forDecrypt {@code true} se la verifica deve essere effettuata per un'operazione di decriptazione. * * @return {@code true} se è un {@link EncryptionInfo} valido, {@code false} altrimenti. */ protected static boolean isValidEncryptionInfo(EncryptionInfo encInfo, boolean forDecrypt) { // Decrypting if (forDecrypt) { return (encInfo != null && isValidName(encInfo.getKey()) && isValidName(encInfo.getAlgorithm())); } // Encrypting /* * L'IV e` richiesto solo se viene inviato un contenuto gia` criptato e il mode e` * specificato ed e` diverso da ECB. */ final boolean needsIv = encInfo != null && encInfo.isSourceEncrypted() && (encInfo.getMode() != null && !encInfo.getMode().equalsIgnoreCase("ECB")); /* * La chiave serve quando non viene caricato un contenuto gia` criptato alla fonte. */ final boolean needsKey = !(encInfo != null && encInfo.isSourceEncrypted()); /* * Mode e padding devono essere entrambi specificati e validi (etrambi non nulli e non stringhe vuote) * oppure nessuno dei due deve essere specificato (entrambi null). */ final boolean bothOrNoneModeAndPadding = encInfo != null && (isValidName(encInfo.getMode()) && isValidName(encInfo.getPadding()) || (encInfo.getMode() == null && encInfo.getPadding() == null)); /* * Algoritmo e keyId sono sempre necessari, gli altri casi dipendono da quanto valutato sopra. */ return (encInfo != null && (!needsKey || (needsKey && isValidName(encInfo.getKey()))) && (!needsIv || (needsIv && encInfo.getSourceIV() != null && Base64.isArrayByteBase64(encInfo.getSourceIV().getBytes()))) && isValidName(encInfo.getAlgorithm()) && bothOrNoneModeAndPadding && isValidName(encInfo.getKeyId())); } /** * Controlla se una generica istanza di {@link Group} è valida. * * <p>Un {@link Group} deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code name} deve essere un nome valido secondo quanto * definito in {@link #isValidName(String)}.</li> * </ul> * * @param group Il {@link Group} da controllare. * * @return {@code true} se è un {@link Group} valido, * {@code false} altrimenti. */ protected static boolean isValidGroup(Group group) { if(group==null || group.getName()==null || group.getName().contains("?") || group.getName().contains("$")||group.getName().length()>200){ return false; } else{ return isValidName(group.getName()); } /*return (group != null) ? isValidName(group.getName()) : false;*/ } protected static boolean isValidGroupNotEmailContributors(Group group) { if(group==null || group.getName()==null || group.getName().equalsIgnoreCase("EMAIL_CONTRIBUTORS")){ return false; } else{ return isValidName(group.getName()); } /*return (group != null) ? isValidName(group.getName()) : false;*/ } /** * Controlla se il nome specificato in input è un nome valido. * * <p>Un nome deve rispettare le seguenti condizioni:</p> * <ul> * <li>non può essere {@code null};</li> * <li>deve essere lungo almeno un carattere.</li> * </ul> * * @param name Il nome da controllare. * * @return {@code true} se è un nome valido, {@code false} altrimenti. */ protected static boolean isValidName(String name) { return (name != null) ? (name.length() > 0) : false; } protected static boolean isValidNotGuest(String name) { if(name==null || name.length()==0 || name.equalsIgnoreCase("guest")){ return false; } else{ return isValidName(name); } } /** * Controlla se il nodo specificato è valido. * * <p>Un nodo valido deve rispettare le seguenti condizioni:</p> * <ul> * <li>l'Uid associato al nodo deve rispettare la regex definita in * {@link #NODE_CHECK_REGEX}.</li> * </ul> * * @param node Il nodo da controllare. * * @return {@code true} se è un nodo valido, {@code false} altrimenti. */ protected static boolean isValidNode(Node node) { if (node == null || node.getUid() == null || !node.getUid().matches(NODE_CHECK_REGEX)) { return false; } return true; } /** * Controlla se una generica istanza di {@link OperationContext} è valida. * * <p>Un {@link OperationContext} deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code username} deve essere un nome valido secondo quanto definito * in {@link #isValidName(String)};</li> * <li>la sua {@code password} deve essere una password valida secondo quanto definito * in {@link #isValidPassword(char[])};</li> * <li>il suo {@code fruitore} deve essere un nome valido secondo quanto definito * in {@link #isValidName(String)}.</li> * </ul> * * @param ctx Il {@link OperationContext} da controllare. * * @return {@code true} se è un {@link OperationContext} valido, * {@code false} altrimenti. */ protected static boolean isValidOperationContext(OperationContext ctx) { return (ctx != null) ? isValidName(ctx.getUsername()) && isValidName(ctx.getFruitore()) && isValidPassword(ctx.getPassword().toCharArray()) : false; } /** * Controlla se la password specificata in input è valida. * * <p>Una password deve rispettare le seguenti condizioni:</p> * <ul> * <li>non può essere {@code null};</li> * <li>deve essere lunga almeno un carattere;</li> * <li>il primo carattere deve essere diverso da '0'.</li> * </ul> * * @param password La password da controllare. * * @return {@code true} se è una password valida, {@code false} altrimenti. */ protected static boolean isValidPassword(char [] password) { return (password != null) ? (password.length > 0) && (password[0] != 0) : false; } /** * Controlla se il prefisso specificato in input è un prefisso valido. * * <p>Un prefisso valido deve rispettare le seguenti condizioni:</p> * <ul> * <li>non può essere {@code null};</li> * <li>deve essere lungo almeno un carattere;</li> * <li>non può contenere il separatore di prefisso definito in * {@link ContentItem#PREFIXED_NAME_SEPARATOR}.</li> * </ul> * * @param prefix Il prefisso da controllare * * @return {@code true} se è un prefisso valido, {@code false} altrimenti. */ protected static boolean isValidPrefix(String prefix) { return (prefix != null) ? (prefix.length() > 0) && (prefix.indexOf(ContentItem.PREFIXED_NAME_SEPARATOR) < 0) : false; } /** * Controlla se il nome completo di prefisso specificato in input è veramente * un nome completo valido. * * <p>Un nome completo valido deve rispettare le seguenti condizioni:</p> * <ul> * <li>deve contenere il separatore di prefisso definito in * {@link ContentItem#PREFIXED_NAME_SEPARATOR};</li> * <li>la parte precedente al separatore (prefisso) deve essere lunga almeno un carattere;</li> * <li>la parte successiva al separatore (nome) deve essere lunga almeno un carattere.</li> * </ul> * * @param prefixedName Il nome da controllare. * * @return {@code true} se è un nome completo valido, {@code false} altrimenti. */ protected static boolean isValidPrefixedName(String prefixedName) { return (prefixedName != null) ? (prefixedName.length() >= 3) && (prefixedName.indexOf(ContentItem.PREFIXED_NAME_SEPARATOR) > 0) && (prefixedName.indexOf(ContentItem.PREFIXED_NAME_SEPARATOR) < (prefixedName.length() - 1)) : false; } /** * Controlla se una generica istanza di {@link Property} è valida. * * <p>Una {@link Property} deve rispettare le seguenti condizioni:</p> * <ul> * <li>deve essere un {@link ContentItem} valido secondo quanto definito * in {@link #isValidContentItem(ContentItem)};</li> * <li>il suo {@code dataType} deve essere un nome valido secondo quanto definito * in {@link #isValidName(String)};</li> * </ul> * * @param property La {@link Property} da controllare. * * @return {@code true} se è una {@link Property} valida, * {@code false} altrimenti. */ protected static boolean isValidProperty(Property property) { return (property != null) ? isValidContentItem(property) && isValidName(property.getDataType()) : false; } /** * Controlla se la stringa specificata è un rule type valido. * * <p>Un rule type deve assumere uno dei seguienti valori:</p> * <ul> * <li>{@code EcmEngineConstants.ECMENGINE_RULE_TYPE_INBOUND} * <li>{@code EcmEngineConstants.ECMENGINE_RULE_TYPE_OUTBOUND} * <li>{@code EcmEngineConstants.ECMENGINE_RULE_TYPE_UPDATE} * </ul> * * @param ruleType Il rule type da verificare. * * @return {@code true} se è un rule type valido, * {@code false} altrimenti. * * @see EcmEngineConstants */ protected static boolean isValidRuleType(String ruleType) { return (EcmEngineConstants.ECMENGINE_RULE_TYPE_INBOUND.equals(ruleType) || EcmEngineConstants.ECMENGINE_RULE_TYPE_OUTBOUND.equals(ruleType) || EcmEngineConstants.ECMENGINE_RULE_TYPE_UPDATE.equals(ruleType)); } /** * Controlla se una generica istanza di {@link AuditInfo} è valida come filtro * per la ricerca nella tavola di audit trail. * * <p>Almeno uno dei seguenti attributi deve essere valorizzato affinchè possa * essere utilizzato come filtro di ricerca:</p> * <ul> * <li>utente</li> * <li>operazione</li> * <li>idOggetto</li> * </ul> * * @param parametriRicerca Il {@link AuditInfo} da controllare. * * @return {@code true} se è un {@link AuditInfo} valido, {@code false} altrimenti. */ protected static boolean isValidSearchParameter(AuditInfo parametriRicerca){ if (parametriRicerca != null) { if (parametriRicerca.getUtente() != null || parametriRicerca.getOperazione() != null || parametriRicerca.getIdOggetto() != null) return true; } return false; } /** * Controlla se una generica istanza di {@link User} è valida. * * <p>Un {@link User} deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code name} deve essere un nome valido secondo quanto * definito in {@link #isValidName(String)};</li> * <li>il suo {@code surname} deve essere un nome valido secondo quanto * definito in {@link #isValidName(String)};</li> * <li>il suo {@code username} deve essere un nome valido secondo quanto * definito in {@link #isValidName(String)}.</li> * </ul> * * @param user Il {@link User} da controllare. * * @return {@code true} se è un {@link User} valido, * {@code false} altrimenti. */ protected static boolean isValidUser(User user) { return (user != null && user.getUsername()!=null && user.getUsername().length()<USERNAME_MAX_LENGTH) ? isValidName(user.getUsername()) && isValidName(user.getName()) && isValidName(user.getSurname()) : false; } /** * Controlla se un'istanza di {@link SearchParams} è valida * per una ricerca con chiave XPath. * * <p>Per essere valido un {@link SearchParams} deve rispettare le * seguenti condizioni:</p> * <ul> * <li>la sua {@code xpathQuery} deve essere diversa da {@code null}.</li> * </ul> * * @param xpath L'oggetto {@code SearchParams} da validare. * * @return {@code true} se è un {@code SearchParams} valido, * {@code false} altrimenti. */ protected static boolean isValidXpath(SearchParams xpath) { return (xpath != null && xpath.getXPathQuery() != null); } protected static boolean isValidXpathAggregate(SearchParamsAggregate xpath) { return (xpath != null && xpath.getXPathQuery() != null); } /** * Controlla se un'istanza di {@link SearchParams} è valida * per una ricerca con chiave Lucene. * * <p>Per essere valido un {@link SearchParams} deve rispettare le * seguenti condizioni:</p> * <ul> * <li>la sua {@code luceneQuery} deve essere diversa da {@code null}.</li> * </ul> * * @param lucene L'oggetto {@code SearchParams} da validare. * * @return {@code true} se è un {@code SearchParams} valido, * {@code false} altrimenti. */ protected static boolean isValidLucene(SearchParams lucene) { return (lucene != null && lucene.getLuceneQuery() != null); } /** * Controlla se un'istanza di {@link Tenant} è valida. * * <p>Per essere valido un {@link Tenant} deve rispettare le * seguenti condizioni:</p> * <ul> * <li>il suo {@code domain} deve essere diversa da {@code null} * e da string avuota.</li> * </ul> * * @param tenant L'oggetto {@code Tenant} da validare. * * @return {@code true} se è un {@code Tenant} valido, * {@code false} altrimenti. */ protected static boolean isValidTenant(Tenant tenant) { return (tenant != null && tenant.getDomain().length()<30 && isValidName(tenant.getDomain())); } /** * Controlla se un'istanza di {@link CustomModel} è valida. * * <p>Per essere valido un {@link CustomModel} deve rispettare le * seguenti condizioni:</p> * <ul> * <li>il suo {@code domain} deve essere diversa da {@code null} * e da string avuota.</li> * </ul> * * @param customModel L'oggetto {@code CustomModel} da validare. * * @return {@code true} se è un {@code CustomModel} valido, * {@code false} altrimenti. */ protected static boolean isValidCustomModel(CustomModel customModel) { return (customModel != null && isValidName(customModel.getFilename())); } /** * Controlla se una generica istanza di {@link Category} è valida. * * <p>Una {@link Category} deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code name} deve essere valorizzato</li> * </ul> * * @param category La {@link Category} da controllare. * * @return {@code true} se è una {@link Category} valida, * {@code false} altrimenti. */ protected static boolean isValidCategory(Category category) { return (category != null) ? isValidName(category.getName()): false; } /** * Controlla se una istanza di root {@link Category} è valida. * * <p>Una {@link Category} root deve rispettare le seguenti condizioni:</p> * <ul> * <li>il suo {@code name} deve essere valorizzato</li> * <li>il suo {@code aspectPrefixedName} deve essere valorizzato correttamente</li> * </ul> * * @param category La {@link Category} root da controllare. * * @return {@code true} se è una {@link Category} Root valida, * {@code false} altrimenti. */ protected static boolean isValidRootCategory(Category category) { return (category != null) ? isValidName(category.getName()) && isValidPrefixedName(category.getAspectPrefixedName()) : false; } /** * Controlla se una generica istanza di {@link Category} utilizzata per le ricerche * è valida. * * <p>Una {@link Category} ai fini delle ricerche deve rispettare la seguente condizione:</p> * <ul> * <li>il suo {@code aspectPrefixedName} deve essere valorizzato correttamente</li> * </ul> * * @param category La {@link Category} da controllare. * * @return {@code true} se è una {@link Category} valida per le ricerche, * {@code false} altrimenti. */ protected static boolean isValidCategoryAspect(Category category) { return (category != null) ? isValidPrefixedName(category.getAspectPrefixedName()) : false; } /** * Controlla se un'istanza di {@code byte[]} è valida. * * <p>Per essere valido un {@code byte[]} deve rispettare le * seguenti condizioni:</p> * <ul> * <li>deve essere diversa da {@code null}</li> * <li>deve avere length > 0</li> * </ul> * * @param byteArray L'oggetto {@code byte[]} da validare. * * @return {@code true} se è un {@code byte[]} valido, * {@code false} altrimenti. */ protected static boolean isValidByteArray(byte[] byteArray) { return (byteArray != null && byteArray.length > 0); } protected static boolean isValidMassiveNumberOfContents(Content[] contents){ if(contents.length>MASSIVE_MAX_CREATE_NUMBER){ return false; } else{ return true; } } protected static boolean isValidMassiveNumberOfRetrieve(Node[] nodes){ if(nodes.length>MASSIVE_MAX_RETRIEVE_NUMBER){ return false; } else{ return true; } } protected static boolean isValidMassiveNumberOfDelete(Node[] nodes){ if(nodes.length>MASSIVE_MAX_DELETE_NUMBER){ return false; } else{ return true; } } protected static boolean isValidMassiveNumberOfRetrieveSize(Long size){ if(size>MASSIVE_MAX_RETRIEVE_SIZE){ return false; } else{ return true; } } protected static boolean isValidMassiveNumberOfGetMetadata(Long size){ if(size>MASSIVE_MAX_GET_METADATA_SIZE){ return false; } else{ return true; } } protected static boolean isValidMassiveSizeOfContents(Content[] contents){ long somma=0; for(int i=0;i<contents.length;i++){ somma=somma+contents[i].getContent().length; } if(somma>MASSIVE_MAX_CREATE_SIZE){ return false; } else{ return true; } } protected static boolean isValidZero(Long value){ return value==0; } protected static boolean isValidNotZero(Long value){ return value!=0; } /** * Esegue il rollback della transazione specificata in input ignorando * le eventuali eccezioni. * * @param transaction La transazione di cui eseguire il rollback. */ protected static void rollbackQuietely(UserTransaction transaction) { try { transaction.rollback(); } catch (Throwable t) { logger.warn("[EcmEnginePublisherBean::rollbackQuietely] Ignored exception during rollback: " + t.getMessage()); } } /** * Verifica se l'eccezione dei servizi di foundation ricevuta in input indica un problema nelle * credenziali di autenticazione. * * <p>È possibile specificare una transazione come ultimo parametro per fare in modo che il metodo ne esegua il * rollback "silenzioso" nel caso l'eccezione in input corrisponda.</p> * * @param e L'eccezione dei servizi di foundation da analizzare. * @param serviceName Il nome del servizio da cui questo metodo è richiamato. * @param methodName Il nome del metodo da cui questo metodo è richiamato. * @param message Un messaggio di errore da inserire nell'eccezione lanciata. * @param transaction Una transazione di cui eseguire il rollback (facoltativo). * * @throws InvalidCredentialsException Se l'eccezione ricevuta in input indica un problema nelle * credenziali di autenticazione. */ protected static void checkCredentialsException(EcmEngineFoundationException e, String serviceName, String methodName, String message, UserTransaction transaction) throws InvalidCredentialsException { if (e.getCode().equals(FoundationErrorCodes.BAD_CREDENTIALS_ERROR)) { logger.info("[" + serviceName + "::" + methodName + "] Bad credentials: " + message); if (transaction != null) { rollbackQuietely(transaction); } throw new InvalidCredentialsException("Bad credentials: " + message); } } /** * Verifica se l'eccezione dei servizi di foundation ricevuta in input indica un problema nelle * di insufficienti permessi di accesso. * * <p>È possibile specificare una transazione come ultimo parametro per fare in modo che il metodo ne esegua il * rollback "silenzioso" nel caso l'eccezione in input corrisponda.</p> * * @param e L'eccezione dei servizi di foundation da analizzare. * @param serviceName Il nome del servizio da cui questo metodo è richiamato. * @param methodName Il nome del metodo da cui questo metodo è richiamato. * @param message Un messaggio di errore da inserire nell'eccezione lanciata. * @param transaction Una transazione di cui eseguire il rollback (facoltativo). * * @throws InvalidCredentialsException Se l'eccezione ricevuta in input indica un problema nelle * di insufficienti permessi di accesso. */ protected static void checkAccessException(EcmEngineFoundationException e, String serviceName, String methodName, String message, UserTransaction transaction) throws PermissionDeniedException { if (e.getCode().equals(FoundationErrorCodes.ACCESS_DENIED_ERROR)) { logger.info("[" + serviceName + "::" + methodName + "] Access denied: " + message); if (transaction != null) { rollbackQuietely(transaction); } throw new PermissionDeniedException("Access denied: " + message); } } }