UML Factory facilities leak memory
- Refactor UmlStateMachineModelFactory and UmlUtils so that eclipse emf unloads a resource and thus should work better with gargage collections. - Also try to clean out tmp files. - Relates #572 - Relates #573
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 the original author or authors.
|
* Copyright 2016-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,7 +21,9 @@ import java.net.URI;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||||
import org.eclipse.uml2.uml.Model;
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
import org.eclipse.uml2.uml.UMLPackage;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.statemachine.config.model.AbstractStateMachineModelFactory;
|
import org.springframework.statemachine.config.model.AbstractStateMachineModelFactory;
|
||||||
import org.springframework.statemachine.config.model.DefaultStateMachineModel;
|
import org.springframework.statemachine.config.model.DefaultStateMachineModel;
|
||||||
@@ -68,13 +70,40 @@ public class UmlStateMachineModelFactory extends AbstractStateMachineModelFactor
|
|||||||
@Override
|
@Override
|
||||||
public StateMachineModel<String, String> build() {
|
public StateMachineModel<String, String> build() {
|
||||||
Model model = null;
|
Model model = null;
|
||||||
|
Holder holder = null;
|
||||||
|
org.eclipse.emf.ecore.resource.Resource resource = null;
|
||||||
try {
|
try {
|
||||||
model = UmlUtils.getModel(getResourceUri(resolveResource()).getPath());
|
holder = getResourceUri(resolveResource());
|
||||||
|
resource = UmlUtils.getResource(holder.uri.getPath());
|
||||||
|
model = (Model) EcoreUtil.getObjectByType(resource.getContents(), UMLPackage.Literals.MODEL);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalArgumentException("Cannot build build model from resource " + resource + " or location " + location, e);
|
throw new IllegalArgumentException("Cannot build build model from resource " + resource + " or location " + location, e);
|
||||||
|
} finally {
|
||||||
|
// if we have a path, tmp file were created, clean it
|
||||||
|
if (holder != null && holder.path != null) {
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(holder.path);
|
||||||
|
} catch (Exception e2) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UmlModelParser parser = new UmlModelParser(model, this);
|
UmlModelParser parser = new UmlModelParser(model, this);
|
||||||
DataHolder dataHolder = parser.parseModel();
|
DataHolder dataHolder = parser.parseModel();
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
if (resource != null) {
|
||||||
|
try {
|
||||||
|
resource.unload();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (holder != null && holder.path != null) {
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(holder.path);
|
||||||
|
} catch (Exception e2) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we don't set configurationData here, so assume null
|
// we don't set configurationData here, so assume null
|
||||||
return new DefaultStateMachineModel<String, String>(null, dataHolder.getStatesData(), dataHolder.getTransitionsData());
|
return new DefaultStateMachineModel<String, String>(null, dataHolder.getStatesData(), dataHolder.getTransitionsData());
|
||||||
}
|
}
|
||||||
@@ -87,16 +116,30 @@ public class UmlStateMachineModelFactory extends AbstractStateMachineModelFactor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private URI getResourceUri(Resource resource) throws IOException {
|
private Holder getResourceUri(Resource resource) throws IOException {
|
||||||
// try to see if resource is an actual File and eclipse
|
// try to see if resource is an actual File and eclipse
|
||||||
// libs cannot use input stream. thus creating a tmp file with
|
// libs cannot use input stream. thus creating a tmp file with
|
||||||
// needed .uml prefix and getting URI from there.
|
// needed .uml prefix and getting URI from there.
|
||||||
try {
|
try {
|
||||||
return resource.getFile().toURI();
|
return new Holder(resource.getFile().toURI());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
Path tempFile = Files.createTempFile(null, ".uml");
|
Path tempFile = Files.createTempFile(null, ".uml");
|
||||||
FileCopyUtils.copy(resource.getInputStream(), new FileOutputStream(tempFile.toFile()));
|
FileCopyUtils.copy(resource.getInputStream(), new FileOutputStream(tempFile.toFile()));
|
||||||
return tempFile.toUri();
|
return new Holder(tempFile.toUri(), tempFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Holder {
|
||||||
|
URI uri;
|
||||||
|
Path path;
|
||||||
|
|
||||||
|
public Holder(URI uri) {
|
||||||
|
this(uri, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Holder(URI uri, Path path) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 the original author or authors.
|
* Copyright 2016-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -65,6 +65,21 @@ public abstract class UmlUtils {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the resource for a model.
|
||||||
|
*
|
||||||
|
* @param modelPath the model path
|
||||||
|
* @return the resource
|
||||||
|
*/
|
||||||
|
public static Resource getResource(String modelPath) {
|
||||||
|
URI modelUri = URI.createFileURI(modelPath);
|
||||||
|
ResourceSet resourceSet = new ResourceSetImpl();
|
||||||
|
resourceSet.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
|
||||||
|
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
|
||||||
|
resourceSet.createResource(modelUri);
|
||||||
|
return resourceSet.getResource(modelUri, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if {@link State} is an initial state by checking if
|
* Checks if {@link State} is an initial state by checking if
|
||||||
* it has incoming transition from UML's initial literal.
|
* it has incoming transition from UML's initial literal.
|
||||||
|
|||||||
Reference in New Issue
Block a user