Commit 7f60d65b authored by Paff's avatar Paff
Browse files

transformation for encrypted connections

parent 3ddb7756
package secarc.ets.cocos.pep;
import java.util.List;
import java.util.Set;
import mc.IErrorCode;
import mc.umlp.arcd.ArcdConstants;
import mc.umlp.arcd._ast.ASTArcComponent;
import mc.umlp.arcd.ets.entries.ComponentEntry;
import mc.umlp.arcd.ets.entries.SubComponentEntry;
import interfaces2.ISTEntry;
import interfaces2.coco.ContextCondition;
import interfaces2.helper.EntryLoadingErrorException;
import interfaces2.loaders.InterfaceLoader;
import interfaces2.resolvers.AmbigousException;
import secarc._ast.ASTSecArcPEP;
import secarc.error.MontiSecArcErrorCodes;
......@@ -98,8 +94,6 @@ public class RoleDefintionInSubcomponents extends ContextCondition implements
}
for(SubComponentEntry subComponentEntry : subComponentEntries) {
SecComponentEntry compType = (SecComponentEntry) subComponentEntry.getComponentType();
Set<ISTEntry> manuallyLoaded = InterfaceLoader.loadExported(getLoader(), compType.getName(), ArcdConstants.ST_KIND_PROTECTED, getDeserializers(),
compType.getExportedInterfaceKindToBeLoaded());
if(compType == null) {
return false;
......
package secarc.ets.transform;
import secarc.ets.transform.transformators.SecAutoConnection;
import mc.DSLRoot;
import mc.umlp.arc.ets.transform.PreCoCoCheckMontiArcTransformationVisitor;
import mc.umlp.arc.ets.transform.transformators.AutoConnection;
import mc.umlp.arcd.ets.transform.transformators.ITransformator;
public class PreCoCoCheckMontiSecArcTransformationVisitor<T extends DSLRoot<?>> extends PreCoCoCheckMontiArcTransformationVisitor<T> {
public PreCoCoCheckMontiSecArcTransformationVisitor(final T dslroot) {
super(dslroot);
createUsefulTransformators();
}
/* (non-Javadoc)
* @see mc.umlp.arcd.ets.transform.TransformationVisitor#register(mc.umlp.arcd.ets.transform.transformators.ITransformator)
*/
@Override
protected void register(ITransformator trafo) {
super.register(trafo);
//remove by SecAutoConnection
if (trafo instanceof AutoConnection) {
autoConnectTransformators.remove(trafo);
}
}
private void createUsefulTransformators() {
register(new SecAutoConnection(getSymtab()));
}
}
package secarc.ets.transform.transformators;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import secarc._ast.ASTSecMontiArcAutoConnect;
import secarc.ets.entries.SecConnectorEntry;
import interfaces2.STEntryState;
import interfaces2.helper.EntryLoadingErrorException;
import interfaces2.helper.SymbolTableInterface;
import mc.MCG;
import mc.helper.NameHelper;
import mc.types._ast.ASTQualifiedName;
import mc.types._ast.ASTQualifiedNameList;
import mc.types._ast.TypesNodeFactory;
import mc.umlp.arc.MontiArcConstants;
import mc.umlp.arc._ast.ASTMontiArcAutoConnect;
import mc.umlp.arc.ets.transform.transformators.AutoConnection;
import mc.umlp.arc.ets.transform.transformators.IAutoConnectTransformator;
import mc.umlp.arc.exceptions.MontiArcErrorCodes;
import mc.umlp.arc.help.AutoconnectMode;
import mc.umlp.arcd._ast.ASTArcComponent;
import mc.umlp.arcd._ast.ASTArcComponentBody;
import mc.umlp.arcd._ast.ASTArcConnector;
import mc.umlp.arcd._ast.ASTArcElement;
import mc.umlp.arcd._ast.ArchitectureDiagramNodeFactory;
import mc.umlp.arcd.ets.check.coco.PortCompatibilityChecker;
import mc.umlp.arcd.ets.entries.ComponentEntry;
import mc.umlp.arcd.ets.entries.ConnectorEntry;
import mc.umlp.arcd.ets.entries.PortEntry;
import mc.umlp.arcd.ets.entries.SubComponentEntry;
import mc.umlp.arcd.ets.transform.transformators.IComponentTransformator;
import mc.umlp.arcd.ets.transform.transformators.TransformatorWithSymtab;
/**
*
* Creates further connectors depending on the auto connect mode (type, port, off, encrypted).
*
* <br>
* <br>
* Copyright (c) 2012 RWTH Aachen. All rights reserved.
*
* @author (last commit) $Author: $
* @version $Date:$<br>
* $Revision: $
*/
public final class SecAutoConnection extends TransformatorWithSymtab implements IComponentTransformator, IAutoConnectTransformator {
/**
* Auto connection mode stack. Inner components may have another auto connection mode then the outer one.
*/
private Stack<List<AutoconnectMode>> modeStack = new Stack<List<AutoconnectMode>>();
private PortCompatibilityChecker portTypeChecker;
private boolean encrypted = false;
/**
* Creates a new {@link AutoConnection} using the given symbol table.
*
* @param symtab symbol table to use
*/
public SecAutoConnection(final SymbolTableInterface symtab) {
super(symtab);
}
@Override
public void transformAtEnd(ASTArcComponent node, ComponentEntry currentComp) {
if (currentComp == null) {
return;
}
List<AutoconnectMode> allModes = this.modeStack.peek();
if (allModes.isEmpty()) {
allModes.add(MontiArcConstants.DEFAULT_AUTO_CONNECT);
}
for (AutoconnectMode mode : allModes) {
if (mode != AutoconnectMode.OFF && currentComp.getSubComponents().size() > 0) {
createAutoconnections(currentComp, node, mode);
}
}
this.modeStack.pop();
}
@Override
public void transformAtStart(ASTArcComponent node, ComponentEntry currentComp) {
modeStack.push(new ArrayList<AutoconnectMode>());
}
@Override
public void transform(ASTMontiArcAutoConnect node, ComponentEntry currentComp) {
List<AutoconnectMode> modes = modeStack.peek();
// add current mode
if (node.isPort()) {
modes.add(AutoconnectMode.AUTOCONNECT_PORT);
}
else if (node.isType()) {
modes.add(AutoconnectMode.AUTOCONNECT_TYPE);
}
else if (node.isOff()) {
modes.add(AutoconnectMode.OFF);
}
// set enrypted
this.encrypted = ((ASTSecMontiArcAutoConnect) node).isEncrypted();
}
/**
* Creates further connectors depending on the auto connect mode (type,
* port, off).
*
* @param currentComponent symbol table entry of the currently processed
* component
* @param node component node in the AST
* @param mode auto connection mode
*/
private void createAutoconnections(ComponentEntry currentComponent, ASTArcComponent node, AutoconnectMode mode) {
portTypeChecker = new PortCompatibilityChecker(getLoader(), getDeserializers());
Map<String, PortEntry> unusedSenders = getUnusedSenders(currentComponent);
Map<String, PortEntry> unusedReceivers = getUnusedReceivers(currentComponent);
for (String receiver : unusedReceivers.keySet()) {
List<ConnectorEntry> matches = new LinkedList<ConnectorEntry>();
int indexReceiver = receiver.indexOf('.');
for (String sender : unusedSenders.keySet()) {
int indexSender = sender.indexOf('.');
boolean matched = false;
// sender from current component, receiver from a reference
if (indexSender == -1 && indexReceiver != -1) {
String receiverPortName = receiver.substring(indexReceiver + 1);
// get types
PortEntry senderPort = unusedSenders.get(sender);
PortEntry receiverPort = unusedReceivers.get(receiver);
if (mode == AutoconnectMode.AUTOCONNECT_PORT && receiverPortName.equals(sender) &&
portTypeChecker.doPortTypesMatch(senderPort, receiverPort)) {
matched = true;
}
else if (mode == AutoconnectMode.AUTOCONNECT_TYPE && portTypeChecker.doPortTypesMatch(senderPort, receiverPort)) {
matched = true;
}
}
// sender from a reference, receiver from current component
else if (indexSender != -1 && indexReceiver == -1) {
String senderPortName = sender.substring(indexSender + 1);
// get types
PortEntry senderPort = unusedSenders.get(sender);
PortEntry receiverPort = unusedReceivers.get(receiver);
if (mode == AutoconnectMode.AUTOCONNECT_PORT && senderPortName.equals(receiver) &&
portTypeChecker.doPortTypesMatch(senderPort, receiverPort)) {
matched = true;
}
else if (mode == AutoconnectMode.AUTOCONNECT_TYPE && portTypeChecker.doPortTypesMatch(senderPort, receiverPort)) {
matched = true;
}
}
// both from referenced components
else if (indexSender != -1 && indexReceiver != -1) {
String senderPortName = sender.substring(indexSender + 1);
String receiverPortName = receiver.substring(indexReceiver + 1);
String senderRef = sender.substring(0, indexSender);
String receiverRef = receiver.substring(0, indexReceiver);
// check if sender and receiver are from different references
if (!senderRef.equals(receiverRef)) {
// get types
PortEntry senderPort = unusedSenders.get(sender);
PortEntry receiverPort = unusedReceivers.get(receiver);
if (mode == AutoconnectMode.AUTOCONNECT_PORT && senderPortName.equals(receiverPortName) &&
portTypeChecker.doPortTypesMatch(senderPort, receiverPort)) {
matched = true;
}
else if (mode == AutoconnectMode.AUTOCONNECT_TYPE && portTypeChecker.doPortTypesMatch(senderPort, receiverPort)) {
matched = true;
}
}
}
// create connector entry and add to matched
if (matched) {
SecConnectorEntry conEntry = new SecConnectorEntry();
conEntry.setSource(sender);
conEntry.setTarget(receiver);
conEntry.setEntryState(STEntryState.FULL, conEntry);
conEntry.setEncryption(encrypted);
matches.add(conEntry);
}
}
if (matches.size() == 1) {
ConnectorEntry created = matches.iterator().next();
// add symbol
currentComponent.addConnector(created);
// add to ast
addConnectorToAST(node, created);
// add connector to symtab
addToSymtab(node, created);
writePositiveInfoMessage(node, created);
}
else if (matches.size() > 1) {
writeDuplicateMessage(node, matches);
}
else {
writeNegativeMessage(node, receiver);
}
}
}
private void writeNegativeMessage(ASTArcComponent node, String receiver) {
StringBuilder sb = new StringBuilder();
sb.append("Unable to autoconnect port '");
sb.append(receiver);
sb.append("'.");
getDelegator().addWarningToCurrentResource(sb.toString(), MontiArcErrorCodes.AutoConnectionFailed, node.get_SourcePositionStart());
}
private void writePositiveInfoMessage(ASTArcComponent node,
ConnectorEntry created) {
getDelegator().addInfoToCurrentResource("Created connector '" + created + "'.", MontiArcErrorCodes.AutoConnected,
node.get_SourcePositionStart());
}
private void writeDuplicateMessage(ASTArcComponent node, List<ConnectorEntry> matches) {
StringBuilder sb = new StringBuilder();
sb.append("Duplicate autoconnection matches for the connector target '");
sb.append(matches.iterator().next().getTarget());
sb.append("' with the sources '");
String sep = "";
for (ConnectorEntry con : matches) {
sb.append(sep);
sep = "', '";
sb.append(con.getSource());
}
sb.append("'!");
getDelegator().addWarningToCurrentResource(sb.toString(), MontiArcErrorCodes.AutoConnectionFailed, node.get_SourcePositionStart());
}
public static void addConnectorToAST(ASTArcComponent node, ConnectorEntry conEntry) {
// create ast node
ASTArcConnector astConnector = ArchitectureDiagramNodeFactory.createASTArcConnector();
ASTQualifiedName source = TypesNodeFactory.createASTQualifiedName();
source.setParts(NameHelper.createListFromDotSeparatedString(conEntry.getSource()));
ASTQualifiedNameList targets = TypesNodeFactory.createASTQualifiedNameList();
ASTQualifiedName target = TypesNodeFactory.createASTQualifiedName();
target.setParts(NameHelper.createListFromDotSeparatedString(conEntry.getTarget()));
targets.add(target);
astConnector.setSource(source);
astConnector.setTargets(targets);
ASTMontiArcAutoConnect auto = resolveAutoconnect(node);
if (auto != null) {
astConnector.set_SourcePositionStart(auto.get_SourcePositionStart());
astConnector.set_SourcePositionEnd(auto.get_SourcePositionEnd());
}
// add node to arc elements
node.getBody().getArcElement().add(astConnector);
}
/**
* @param comp used component node.
* @return searches the autoconnect statement in the given comp ast. returns
* null, if it does not exist.
*/
public static ASTMontiArcAutoConnect resolveAutoconnect(ASTArcComponent comp) {
ASTMontiArcAutoConnect result = null;
for (ASTArcElement cfg : ((ASTArcComponentBody) comp.getBody()).getArcElement()) {
if (cfg instanceof ASTMontiArcAutoConnect) {
result = (ASTMontiArcAutoConnect) cfg;
break;
}
}
return result;
}
/**
* Finds all incoming ports of a given component (and all referenced components) which are not connected.
*
* @param currentComponent
* the component for which to find the unused ports
* @return unused incoming ports of a given component represented in a map from port names to types
*/
private Map<String, PortEntry> getUnusedReceivers(ComponentEntry currentComponent) {
Map<String, PortEntry> unusedReceivers = new HashMap<String, PortEntry>();
// check incoming ports
for (PortEntry receiver : currentComponent.getOutgoingPorts()) {
if (!currentComponent.hasConnector(receiver.getName())) {
unusedReceivers.put(receiver.getName(), receiver);
}
}
// check references
for (SubComponentEntry ref : currentComponent.getSubComponents()) {
String name = ref.getName();
ComponentEntry refType = ref.getComponentType();
if (refType.getEntryState() == STEntryState.QUALIFIED) {
try {
refType.loadFullVersion(getLoader(), getDeserializers());
}
catch (EntryLoadingErrorException e) {
MCG.getLogger().severe(e.getMessage());
}
}
for (PortEntry port : refType.getIncomingPorts()) {
String portNameInConnector = name + "." + port.getName();
if (!currentComponent.hasConnector(portNameInConnector)) {
// check, if the current type is generic
PortEntry portGenericsReplaced = port;
if (!ref.getTypeParameters().isEmpty()) {
portGenericsReplaced = portTypeChecker.replaceGenericByUsedTypes(port, ref);
}
unusedReceivers.put(portNameInConnector, portGenericsReplaced);
}
}
}
return unusedReceivers;
}
/**
* Finds all outgoing ports of a given component (and all referenced components) which are not connected.
*
* @param currentComponent
* the component for which to find the unused ports
* @return unused outgoing ports of a given component represented in a map from port names to types
*/
private Map<String, PortEntry> getUnusedSenders(ComponentEntry currentComponent) {
Map<String, PortEntry> unusedSenders = new HashMap<String, PortEntry>();
// as senders could send to more then one receiver, all senders are added
for (PortEntry sender : currentComponent.getIncomingPorts()) {
if (!currentComponent.hasConnectors(sender.getName())) {
unusedSenders.put(sender.getName(), sender);
}
}
// check references
for (SubComponentEntry ref : currentComponent.getSubComponents()) {
String name = ref.getName();
ComponentEntry refType = ref.getComponentType();
if (refType.getEntryState() == STEntryState.QUALIFIED) {
try {
refType.loadFullVersion(getLoader(), getDeserializers());
}
catch (EntryLoadingErrorException e) {
MCG.getLogger().severe(e.getMessage());
}
}
for (PortEntry port : refType.getOutgoingPorts()) {
String portNameInConnector = name + "." + port.getName();
// do we have a generic component here
PortEntry portGenericsReplaced = port;
if (!ref.getTypeParameters().isEmpty()) {
portGenericsReplaced = portTypeChecker.replaceGenericByUsedTypes(port, ref);
}
if (!currentComponent.hasConnectors(portNameInConnector)) {
unusedSenders.put(portNameInConnector, portGenericsReplaced);
}
}
}
return unusedSenders;
}
}
......@@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.List;
import mc.ProblemReport;
import mc.umlp.arcd.TestWithSymtab;
import org.junit.Test;
......@@ -24,7 +23,7 @@ import secarc.error.MontiSecArcErrorCodes;
* @version $Revision$, $Date$
*
*/
public class MontiSecArcCoCoTest extends TestWithSymtab<MontiSecArcTestTool> {
public class MontiSecArcCoCoTest extends TestWithSymbolTableSec<MontiSecArcTestTool> {
public MontiSecArcCoCoTest() {
......@@ -183,7 +182,7 @@ public class MontiSecArcCoCoTest extends TestWithSymtab<MontiSecArcTestTool> {
for(ProblemReport error : handler.getErrors()) {
assertTrue(errorCodes.contains(error.getErrorcode()));
}
assertEquals(1, handler.getWarnings().size());
assertEquals(2, handler.getWarnings().size());
}
/**
......
......@@ -12,11 +12,15 @@ component AutoEncryptedConnect {
component Help help {
port out int pHelp;
trustlevel +1;
}
component TargetHelp targetHelp {
access user;
port in int pTargetHelp;
}
}
\ No newline at end of file
......@@ -16,9 +16,6 @@ component FilterComponent {
component TargetHelp targetHelp {
access user;
}
port
in String input;
component (filter url) FilterURL {
......
......@@ -16,9 +16,6 @@ component WrongNaming {
component TargetHelp targetHelp {
access user;
}
port
in String input;
component (filter Url) FilterURL {
......
......@@ -15,9 +15,6 @@ component ReferenceRoleDoNotExist {
component Test test {
trustlevel +2;
port
in String ptest;
access ptestq (user);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment