Java tutorial
/* * Copyright 2014 Stefan Domnanovits * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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 com.codebullets.external.party.simulator.pipeline; import com.codebullets.external.party.simulator.config.Config; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; import groovy.lang.GroovyClassLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; /** * Loads all groovy handler scripts. */ public class HandlerScriptLoader { private static final Logger LOG = LoggerFactory.getLogger(HandlerScriptLoader.class); private final Config config; /** * Generates a new instance of HandlerScriptLoader. */ @Inject public HandlerScriptLoader(final Config config) { this.config = config; } /** * Loads all scripts and returns a list of matching handlers to be executed. */ public Iterable<AbstractMessageHandler> loadMatchingScriptHandlers(final MessageReceivedEvent messageItem, final GroovyClassLoader classLoader) { List<AbstractMessageHandler> handlers = new ArrayList<>(); Iterable<AbstractMessageHandler> allHandlers = createCollectionOfType(AbstractMessageHandler.class, allHandlers(classLoader).get(HandlerType.MESSAGE)); for (AbstractMessageHandler handler : allHandlers) { if (isMatchingHandler(handler, messageItem.getContentType(), messageItem.getMessageType(), messageItem.getConnectionContext().getConnectionName())) { handlers.add(handler); } } return handlers; } /** * Loads all scripts and returns a list of matching handlers to be executed. */ public Iterable<AbstractConnectionEstablishedHandler> loadMatchingScriptHandlers( final ConnectionEstablishedEvent establishedEvent, final GroovyClassLoader classLoader) { List<AbstractConnectionEstablishedHandler> handlers = new ArrayList<>(); Iterable<AbstractConnectionEstablishedHandler> allHandlers = createCollectionOfType( AbstractConnectionEstablishedHandler.class, allHandlers(classLoader).get(HandlerType.CONNECTION_ESTABLISHED)); for (AbstractConnectionEstablishedHandler handler : allHandlers) { if (isMatchingHandler(handler, establishedEvent.getConnectionContext().getConnectionName())) { handlers.add(handler); } } return handlers; } private boolean isMatchingHandler(final AbstractMessageHandler handler, final ContentType messageContentType, final String messageType, final String connectionName) { boolean isMatch = false; if (messageContentType.equals(handler.getContentType())) { GlobMatcher msgTypeMatcher = new GlobMatcher(handler.getMessageType()); if (msgTypeMatcher.isMatch(messageType)) { GlobMatcher connectionNameMatcher = new GlobMatcher(handler.getConnectionFilter()); if (connectionNameMatcher.isMatch(connectionName)) { isMatch = true; } } } return isMatch; } private boolean isMatchingHandler(final AbstractConnectionEstablishedHandler handler, final String connectionName) { boolean isMatch = false; GlobMatcher connectionNameMatcher = new GlobMatcher(handler.getConnectionFilter()); if (connectionNameMatcher.isMatch(connectionName)) { isMatch = true; } return isMatch; } private Multimap<HandlerType, AbstractHandler> allHandlers(final GroovyClassLoader classLoader) { Multimap<HandlerType, AbstractHandler> handlers = LinkedListMultimap.create(); List<Class> allClasses = new ArrayList<>(); // add all groovy class into class loader Iterable<Path> groovyFiles = findAllGroovyFiles(); for (Path file : groovyFiles) { try { Class scriptClass = classLoader.parseClass(file.toFile()); allClasses.add(scriptClass); } catch (IOException e) { LOG.error("Error parsing groove file " + file.toString()); } } // after all classes are available instantiate handlers for (Class clazz : allClasses) { AbstractHandler handler = createHandlerInstance(clazz); if (handler instanceof AbstractMessageHandler) { addHandler(handlers, HandlerType.MESSAGE, handler); } else if (handler instanceof AbstractConnectionEstablishedHandler) { addHandler(handlers, HandlerType.CONNECTION_ESTABLISHED, handler); } } return handlers; } @SuppressWarnings("unchecked") private <T> Iterable<T> createCollectionOfType(final Class<T> targetType, final Iterable sourceList) { List<T> list = new ArrayList<>(Iterables.size(sourceList)); for (Object entry : sourceList) { if (targetType.isInstance(entry)) { list.add((T) entry); } } return list; } private void addHandler(final Multimap<HandlerType, AbstractHandler> handlers, final HandlerType handlerType, final AbstractHandler handler) { if (handler != null) { handlers.put(handlerType, handler); } } private <T extends AbstractHandler> T createHandlerInstance(final Class<T> clazz) { T handler = null; try { if (AbstractHandler.class.isAssignableFrom(clazz)) { handler = clazz.newInstance(); } } catch (InstantiationException | IllegalAccessException e) { LOG.error("Error creating handler instance {}.", clazz.getSimpleName(), e); } return handler; } /** * Returns the list of connection definition files. */ private Iterable<Path> findAllGroovyFiles() { final List<Path> handlerFiles = new ArrayList<>(); Path startPath = config.handlersPath(); LOG.debug("Search for handler files in directory " + startPath); try { Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) { return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) { if (file.toString().endsWith(".groovy")) { handlerFiles.add(file); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(final Path file, final IOException e) { return FileVisitResult.CONTINUE; } }); } catch (IOException e) { LOG.error("Error finding script files.", e); } return handlerFiles; } /** * Types of known handlers. */ private enum HandlerType { MESSAGE, CONNECTION_ESTABLISHED } }