/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/agpl.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package se.streamsource.streamflow.web.assembler; import static org.qi4j.api.common.Visibility.application; import static org.qi4j.api.common.Visibility.layer; import static org.qi4j.bootstrap.ImportedServiceDeclaration.INSTANCE; import java.util.Properties; import java.util.ResourceBundle; import org.apache.velocity.app.VelocityEngine; import org.qi4j.api.common.Visibility; import org.qi4j.api.service.qualifier.ServiceQualifier; import org.qi4j.api.specification.Specifications; import org.qi4j.api.structure.Application; import org.qi4j.bootstrap.AssemblyException; import org.qi4j.bootstrap.LayerAssembly; import org.qi4j.bootstrap.ModuleAssembly; import org.qi4j.spi.query.NamedEntityFinder; import org.qi4j.spi.query.NamedQueries; import org.qi4j.spi.query.NamedQueryDescriptor; import org.qi4j.spi.service.importer.ServiceSelectorImporter; import se.streamsource.infrastructure.circuitbreaker.CircuitBreaker; import se.streamsource.infrastructure.index.elasticsearch.NamedESDescriptor; import se.streamsource.streamflow.infrastructure.event.application.replay.ApplicationEventPlayerService; import se.streamsource.streamflow.infrastructure.event.domain.replay.DomainEventPlayerService; import se.streamsource.streamflow.server.plugin.authentication.UserDetailsValue; import se.streamsource.streamflow.server.plugin.ldapimport.GroupDetailsValue; import se.streamsource.streamflow.server.plugin.ldapimport.GroupListValue; import se.streamsource.streamflow.server.plugin.ldapimport.GroupMemberDetailValue; import se.streamsource.streamflow.server.plugin.ldapimport.UserListValue; import se.streamsource.streamflow.web.application.archival.ArchivalConfiguration; import se.streamsource.streamflow.web.application.archival.ArchivalService; import se.streamsource.streamflow.web.application.archival.ArchivalStartJob; import se.streamsource.streamflow.web.application.archival.ArchivalStopJob; import se.streamsource.streamflow.web.application.attachment.RemoveAttachmentsService; import se.streamsource.streamflow.web.application.console.ConsoleResultValue; import se.streamsource.streamflow.web.application.console.ConsoleScriptValue; import se.streamsource.streamflow.web.application.console.ConsoleService; import se.streamsource.streamflow.web.application.contact.StreamflowContactLookupService; import se.streamsource.streamflow.web.application.defaults.AvailabilityConfiguration; import se.streamsource.streamflow.web.application.defaults.AvailabilityService; import se.streamsource.streamflow.web.application.defaults.SystemDefaultsConfiguration; import se.streamsource.streamflow.web.application.defaults.SystemDefaultsService; import se.streamsource.streamflow.web.application.dueon.DueOnNotificationConfiguration; import se.streamsource.streamflow.web.application.dueon.DueOnNotificationJob; import se.streamsource.streamflow.web.application.dueon.DueOnNotificationService; import se.streamsource.streamflow.web.application.external.IntegrationConfiguration; import se.streamsource.streamflow.web.application.external.IntegrationService; import se.streamsource.streamflow.web.application.knowledgebase.KnowledgebaseConfiguration; import se.streamsource.streamflow.web.application.knowledgebase.KnowledgebaseService; import se.streamsource.streamflow.web.application.mail.CreateCaseFromEmailConfiguration; import se.streamsource.streamflow.web.application.mail.CreateCaseFromEmailService; import se.streamsource.streamflow.web.application.mail.HtmlMailGenerator; import se.streamsource.streamflow.web.application.mail.ReceiveMailConfiguration; import se.streamsource.streamflow.web.application.mail.ReceiveMailService; import se.streamsource.streamflow.web.application.mail.SendMailConfiguration; import se.streamsource.streamflow.web.application.mail.SendMailService; import se.streamsource.streamflow.web.application.migration.StartupMigrationConfiguration; import se.streamsource.streamflow.web.application.migration.StartupMigrationService; import se.streamsource.streamflow.web.application.organization.BootstrapAssembler; import se.streamsource.streamflow.web.application.pdf.CasePdfGenerator; import se.streamsource.streamflow.web.application.pdf.PdfGeneratorService; import se.streamsource.streamflow.web.application.security.AuthenticationFilterService; import se.streamsource.streamflow.web.application.security.AuthenticationFilterServiceConfiguration; import se.streamsource.streamflow.web.application.statistics.CaseStatisticsService; import se.streamsource.streamflow.web.application.statistics.CaseStatisticsValue; import se.streamsource.streamflow.web.application.statistics.FormFieldStatisticsValue; import se.streamsource.streamflow.web.application.statistics.JdbcStatisticsStore; import se.streamsource.streamflow.web.application.statistics.LoggingStatisticsStore; import se.streamsource.streamflow.web.application.statistics.OrganizationalStructureValue; import se.streamsource.streamflow.web.application.statistics.OrganizationalUnitValue; import se.streamsource.streamflow.web.application.statistics.RelatedStatisticsValue; import se.streamsource.streamflow.web.application.statistics.StatisticsConfiguration; import se.streamsource.streamflow.web.domain.util.ToJson; import se.streamsource.streamflow.web.infrastructure.caching.CaseCountCacheService; import se.streamsource.streamflow.web.infrastructure.index.NamedSolrDescriptor; import se.streamsource.streamflow.web.infrastructure.plugin.LdapImporterServiceConfiguration; import se.streamsource.streamflow.web.infrastructure.plugin.ldap.LdapImportJob; import se.streamsource.streamflow.web.infrastructure.plugin.ldap.LdapImporterService; import se.streamsource.streamflow.web.infrastructure.scheduler.Qi4JQuartzJobFactory; import se.streamsource.streamflow.web.infrastructure.scheduler.QuartzSchedulerService; import se.streamsource.streamflow.web.rest.service.conversation.EmailTemplatesUpdateService; import se.streamsource.streamflow.web.rest.service.mail.MailSenderService; /** * JAVADOC */ public class AppAssembler extends AbstractLayerAssembler { public void assemble( LayerAssembly layer ) throws AssemblyException { super.assemble( layer ); system( layer.module( "System" )); archival(layer.module("Archival")); replay(layer.module("Replay")); console( layer.module( "Console" ) ); migration( layer.module( "Migration" ) ); security( layer.module( "Security" ) ); new BootstrapAssembler().assemble( layer.module( "Bootstrap" ) ); statistics( layer.module( "Statistics" ) ); contactLookup( layer.module( "Contact lookup" ) ); pdf( layer.module( "Pdf" ) ); attachment( layer.module( "Attachment" )); if (layer.application().mode().equals( Application.Mode.production )) { mail( layer.module( "Mail" ) ); } velocity( layer.module( "Velocity" )); scheduler( layer.module( "Scheduler" ) ); dueOnNotifiation(layer.module("DueOn Notification")); knowledgebase(layer.module("Knowledgebase")); ldapimport( layer.module( "Ldapimport" ) ); external( layer.module( "External" ) ); // All configurations must be visible in the Application scope configuration().layer().entities(Specifications.<Object>TRUE()).visibleIn(Visibility.application); } private void external( ModuleAssembly external ) { external.services( IntegrationService.class ) .identifiedBy( "integration" ).instantiateOnStartup().visibleIn( Visibility.application ); configuration().entities( IntegrationConfiguration.class ); } private void system( ModuleAssembly system ) { NamedQueries namedQueries = new NamedQueries(); namedQueries.addQuery(new NamedESDescriptor("esquery", "")); system.importedServices(NamedEntityFinder.class). importedBy(ServiceSelectorImporter.class). setMetaInfo(namedQueries). setMetaInfo(ServiceQualifier.withId("es-indexing")); system.services( SystemDefaultsService.class ) .identifiedBy( "systemdefaults" ).instantiateOnStartup().visibleIn(Visibility.application); configuration().entities(SystemDefaultsConfiguration.class); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().sortOrderAscending().set( false ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogAttachmentVisible().set( false ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogContactVisible().set( false ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogConversationVisible().set( false ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogCustomVisible().set( true ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogFormVisible().set( true ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogSystemVisible().set( false ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().caseLogSystemTraceVisible().set( false ); ResourceBundle bundle = ResourceBundle.getBundle( AppAssembler.class.getName() ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().supportOrganizationName().set( bundle.getString( "supportOuName" ) ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().supportProjectName().set( bundle.getString( "supportProjectName" ) ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().supportCaseTypeForIncomingEmailName().set( bundle.getString( "supportCaseTypeForIncomingEmailName" ) ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().supportCaseTypeForOutgoingEmailName().set( bundle.getString( "supportCaseTypeForOutgoingEmailName" ) ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().webFormsProxyUrl().set( "https://localhost:8443/surface" ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().defaultMarkReadTimeout().set( 15L ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().mapDefaultStartLocation().set( "59.324258,18.070450" ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().mapDefaultZoomLevel().set( 6 ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().mapDefaultUrlPattern().set( "<a href=\"http://maps.google.com/maps?z=13&t=m&q={0}\" alt=\"Google Maps\">Klicka här för att visa karta</a>" ); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().mapquestReverseLookupUrlPattern().set("http://open.mapquestapi.com/nominatim/v1/reverse?lat=%f&lon=%f&format=json"); configuration().forMixin( SystemDefaultsConfiguration.class ).declareDefaults().webclientBaseUrl().set("http://localhost/webclient/#/cases/" ); // set circuitbreaker time out to 12 hours - availability circuit breaker should only be able to be handled manually system.services( AvailabilityService.class ).identifiedBy( "availability" ). instantiateOnStartup(). visibleIn( Visibility.application ). setMetaInfo( new CircuitBreaker( 1, 1000 * 60 * 60 * 12 ) ); configuration().entities( AvailabilityConfiguration.class ); system.services( CaseCountCacheService.class ).instantiateOnStartup().visibleIn( Visibility.application ); } private void archival(ModuleAssembly archival) { archival.services(ArchivalService.class).identifiedBy("archival").instantiateOnStartup().visibleIn(Visibility.application); configuration().entities(ArchivalConfiguration.class); configuration().forMixin(ArchivalConfiguration.class).declareDefaults().startScheduledArchival().set(false); configuration().forMixin(ArchivalConfiguration.class).declareDefaults().modulo().set(1000); // default schedule - between 19:00 - 23:30 every day configuration().forMixin(ArchivalConfiguration.class).declareDefaults().startSchedule().set("0 0 19 * * ?"); configuration().forMixin(ArchivalConfiguration.class).declareDefaults().stopSchedule().set("0 30 23 * * ?"); archival.transients(ArchivalStartJob.class, ArchivalStopJob.class).visibleIn(application); archival.objects(ToJson.class); } private void dueOnNotifiation(ModuleAssembly module) { module.services(DueOnNotificationService.class).identifiedBy("dueOnNotification").instantiateOnStartup().visibleIn(Visibility.application); configuration().entities(DueOnNotificationConfiguration.class); // default schedule - 08:00 every day configuration().forMixin( DueOnNotificationConfiguration.class ).declareDefaults().schedule().set( "0 0 8 * * ?" ); module.transients( DueOnNotificationJob.class).visibleIn( application ); } private void replay( ModuleAssembly module ) throws AssemblyException { module.services( DomainEventPlayerService.class, ApplicationEventPlayerService.class ).visibleIn( Visibility.application ); } private void attachment( ModuleAssembly module ) throws AssemblyException { module.services( RemoveAttachmentsService.class ) .identifiedBy( "removeattachments" ).visibleIn(application).instantiateOnStartup(); } private void pdf( ModuleAssembly module ) throws AssemblyException { module.objects( CasePdfGenerator.class ).visibleIn( application ); module.services( PdfGeneratorService.class ).identifiedBy( "generatepdf" ) .visibleIn( application ).instantiateOnStartup(); } private void contactLookup( ModuleAssembly module ) throws AssemblyException { module.services(StreamflowContactLookupService.class).visibleIn( Visibility.application ); NamedQueries namedQueries = new NamedQueries(); NamedQueryDescriptor queryDescriptor = new NamedSolrDescriptor( "solrquery", "" ); namedQueries.addQuery( queryDescriptor ); module.importedServices( NamedEntityFinder.class ). importedBy( ServiceSelectorImporter.class ). setMetaInfo(ServiceQualifier.withId("solr")). setMetaInfo(namedQueries); } private void mail( ModuleAssembly module ) throws AssemblyException { module.services(EmailTemplatesUpdateService.class).instantiateOnStartup(); module.services( MailSenderService.class ).identifiedBy( "mailsender" ) .visibleIn( application ).instantiateOnStartup(); module.services( ReceiveMailService.class ). identifiedBy( "receivemail" ). instantiateOnStartup(). visibleIn( Visibility.application ). setMetaInfo( new CircuitBreaker(3, 1000*60*5) ); module.services( SendMailService.class ). identifiedBy( "sendmail" ). instantiateOnStartup(). visibleIn( Visibility.application ). setMetaInfo(new CircuitBreaker(3, 1000 * 60 * 5)); configuration().entities( SendMailConfiguration.class ).visibleIn( Visibility.application ); configuration().entities( ReceiveMailConfiguration.class ).visibleIn( Visibility.application ); module.services(CreateCaseFromEmailService.class).visibleIn(Visibility.application).instantiateOnStartup(); configuration().entities(CreateCaseFromEmailConfiguration.class).visibleIn(Visibility.application); } private void statistics( ModuleAssembly module ) throws AssemblyException { if (module.layer().application().mode().equals( Application.Mode.production )) { module.services( CaseStatisticsService.class ). identifiedBy( "statistics" ). instantiateOnStartup(). visibleIn( application ); configuration().entities( StatisticsConfiguration.class ).visibleIn( Visibility.application ); module.services( LoggingStatisticsStore.class ). identifiedBy( "logstatisticsstore" ). instantiateOnStartup(). visibleIn( Visibility.module ); module.services( JdbcStatisticsStore.class ). identifiedBy( "jdbcstatisticsstore" ). instantiateOnStartup(). visibleIn( Visibility.module ); } module.values(RelatedStatisticsValue.class, FormFieldStatisticsValue.class, OrganizationalStructureValue.class, OrganizationalUnitValue.class, CaseStatisticsValue.class).visibleIn(layer); } private void security( ModuleAssembly module ) throws AssemblyException { Application.Mode mode = module.layer().application().mode(); if (mode.equals( Application.Mode.production )) { module.values( UserDetailsValue.class, GroupDetailsValue.class ); module.services( AuthenticationFilterService.class ) .identifiedBy( "authentication" ) .instantiateOnStartup() .setMetaInfo(new CircuitBreaker(10, 1000 * 60 * 5)) .visibleIn(application); configuration().entities( AuthenticationFilterServiceConfiguration.class ).visibleIn( Visibility.application ); } } private void migration( ModuleAssembly module ) throws AssemblyException { Application.Mode mode = module.layer().application().mode(); if (mode.equals( Application.Mode.production )) { // Migrate state module.services( StartupMigrationService.class ). visibleIn( application ). identifiedBy( "startupmigration" ). instantiateOnStartup(); configuration().entities( StartupMigrationConfiguration.class ).visibleIn( Visibility.application ); } } private void console( ModuleAssembly module ) throws AssemblyException { module.values( ConsoleScriptValue.class, ConsoleResultValue.class ).visibleIn( application ); module.services( ConsoleService.class ).visibleIn( application ); } private void velocity(ModuleAssembly module) throws AssemblyException { Properties props = new Properties(); try { props.load(getClass().getResourceAsStream("/velocity.properties")); VelocityEngine velocity = new VelocityEngine(props); module.importedServices(VelocityEngine.class) .importedBy(INSTANCE).setMetaInfo(velocity).visibleIn( layer ); } catch (Exception e) { throw new AssemblyException("Could not load velocity properties", e); } module.objects( HtmlMailGenerator.class ).visibleIn( Visibility.application ); } private void knowledgebase(ModuleAssembly knowledgebase) throws AssemblyException { knowledgebase.services(KnowledgebaseService.class).identifiedBy("knowledgebase").instantiateOnStartup().visibleIn(Visibility.application); configuration().entities(KnowledgebaseConfiguration.class); } private void ldapimport( ModuleAssembly module ) { module.services( LdapImporterService.class ) .identifiedBy( "ldapimport" ) .instantiateOnStartup() .setMetaInfo(new CircuitBreaker(10, 1000 * 60 * 5)) .visibleIn(application); configuration().entities( LdapImporterServiceConfiguration.class ).visibleIn( Visibility.application ); // default schedule - run att 17:00 every day configuration().forMixin( LdapImporterServiceConfiguration.class ).declareDefaults().schedule().set( "0 0 17 * * ?" ); module.transients( LdapImportJob.class).visibleIn( application ); module.values( UserDetailsValue.class, GroupDetailsValue.class, UserListValue.class, GroupListValue.class, GroupMemberDetailValue.class ).visibleIn( Visibility.application ); } private void scheduler( ModuleAssembly module ) throws AssemblyException { module.addServices( Qi4JQuartzJobFactory.class, QuartzSchedulerService.class ).visibleIn( Visibility.application ); } }