This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 63f738d220c9c81649002eaeeef1869dc7d82277
Merge: 4198c1bcd 5f9ab4f8b
Author: Nikita Timofeev <stari...@gmail.com>
AuthorDate: Thu Nov 10 11:15:59 2022 +0300

    Merge remote-tracking branch 'parent/pr/463' into asf-master
    
    # Conflicts:
    #       
cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java

 .../cayenne/project/ConfigurationSourceSetter.java |  23 +-
 .../apache/cayenne/project/FileProjectSaver.java   | 637 +++++++++++----------
 .../org/apache/cayenne/project/ProjectModule.java  |   3 +
 .../xml/XMLDataChannelDescriptorLoader.java        |   1 -
 .../apache/cayenne/modeler/ProjectController.java  |  65 +--
 .../apache/cayenne/modeler/action/SaveAction.java  |   2 +
 .../apache/cayenne/modeler/editor/DataMapView.java |  30 +-
 .../cayenne/modeler/event/ProjectSavedEvent.java   |  37 ++
 .../modeler/event/ProjectSavedListener.java        |  29 +
 9 files changed, 443 insertions(+), 384 deletions(-)

diff --cc 
cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
index a83cf7693,11325634c..cd76e0a64
--- 
a/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
+++ 
b/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java
@@@ -50,321 -50,322 +50,322 @@@ import java.util.List
   */
  public class FileProjectSaver implements ProjectSaver {
  
-       @Inject
-       protected ConfigurationNameMapper nameMapper;
- 
-       protected ConfigurationNodeVisitor<Resource> resourceGetter;
-       protected ConfigurationNodeVisitor<Collection<ConfigurationNode>> 
saveableNodesGetter;
-       protected String fileEncoding;
- 
-       protected Collection<ProjectExtension> extensions;
-       protected SaverDelegate delegate;
- 
-       public FileProjectSaver(@Inject List<ProjectExtension> extensions) {
-               resourceGetter = new ConfigurationSourceGetter();
-               saveableNodesGetter = new SaveableNodesGetter();
- 
-               // this is not configurable yet... probably doesn't have to be
-               fileEncoding = "UTF-8";
- 
-               this.extensions = extensions;
-               Collection<SaverDelegate> delegates = new 
ArrayList<>(extensions.size());
-               for(ProjectExtension extension : extensions) {
-                       delegates.add(extension.createSaverDelegate());
-               }
-               delegate = new CompoundSaverDelegate(delegates);
-       }
- 
-       @Override
-       public String getSupportedVersion() {
-               return String.valueOf(Project.VERSION);
-       }
- 
-       @Override
-       public void save(Project project) {
-               save(project, project.getConfigurationResource(), true);
-       }
- 
-       @Override
-       public void saveAs(Project project, Resource baseDirectory) {
-               if (baseDirectory == null) {
-                       throw new NullPointerException("Null 'baseDirectory'");
-               }
-               save(project, baseDirectory, false);
-       }
- 
-       void save(Project project, Resource baseResource, boolean 
deleteOldResources) {
-               Collection<ConfigurationNode> nodes = 
project.getRootNode().acceptVisitor(saveableNodesGetter);
-               Collection<SaveUnit> units = new ArrayList<>(nodes.size());
- 
-               delegate.setBaseDirectory(baseResource);
- 
-               for(ConfigurationNode node : nodes) {
-                       String targetLocation = 
nameMapper.configurationLocation(node);
-                       Resource targetResource = 
baseResource.getRelativeResource(targetLocation);
-                       units.add(createSaveUnit(node, targetResource, null));
- 
-                       for(ProjectExtension extension : extensions) {
-                               ConfigurationNodeVisitor<String> namingDelegate 
= extension.createNamingDelegate();
-                               SaverDelegate unitSaverDelegate = 
extension.createSaverDelegate();
-                               String fileName = 
node.acceptVisitor(namingDelegate);
-                               if(fileName != null) {
-                                       // not null means that this should go 
to a separate file
-                                       targetResource = 
baseResource.getRelativeResource(fileName);
-                                       units.add(createSaveUnit(node, 
targetResource, unitSaverDelegate));
-                               }
-                       }
-               }
- 
-               checkAccess(units);
- 
-               try {
-                       saveToTempFiles(units);
-                       saveCommit(units);
-               } finally {
-                       clearTempFiles(units);
-               }
- 
-               try {
-                       if (deleteOldResources) {
-                               clearRenamedFiles(units);
- 
-                               Collection<URL> unusedResources = 
project.getUnusedResources();
-                               for (SaveUnit unit : units) {
-                                       
unusedResources.remove(unit.sourceConfiguration.getURL());
-                               }
-                               deleteUnusedFiles(unusedResources);
-                       }
-               } catch (IOException ex) {
-                       throw new CayenneRuntimeException(ex);
-               }
- 
-               // I guess we should reset projects state regardless of the 
value of
-               // 'deleteOldResources'
-               project.getUnusedResources().clear();
-       }
- 
-       SaveUnit createSaveUnit(ConfigurationNode node, Resource 
targetResource, SaverDelegate delegate) {
- 
-               SaveUnit unit = new SaveUnit();
-               unit.node = node;
-               unit.delegate = delegate;
-               unit.sourceConfiguration = node.acceptVisitor(resourceGetter);
- 
-               if (unit.sourceConfiguration == null) {
-                       unit.sourceConfiguration = targetResource;
-               }
- 
-               // attempt to convert targetResource to a File... if that fails,
-               // FileProjectSaver is not appropriate for handling a given 
project..
- 
-               URL targetUrl = targetResource.getURL();
- 
-               try {
-                       unit.targetFile = Util.toFile(targetUrl);
-               } catch (IllegalArgumentException e) {
-                       throw new CayenneRuntimeException("Can't save 
configuration to the following location: '%s'. "
-                                       + "Is this a valid file location?. 
(%s)", e, targetUrl, e.getMessage());
-               }
- 
-               return unit;
-       }
- 
-       void checkAccess(Collection<SaveUnit> units) {
-               for (SaveUnit unit : units) {
- 
-                       File targetFile = unit.targetFile;
- 
-                       File parent = targetFile.getParentFile();
-                       if (!parent.exists()) {
-                               if (!parent.mkdirs()) {
-                                       throw new 
CayenneRuntimeException("Error creating directory tree for '%s'",
-                                                       
parent.getAbsolutePath());
-                               }
-                       }
- 
-                       if (targetFile.isDirectory()) {
-                               throw new CayenneRuntimeException("Target file 
'%s' is a directory", targetFile.getAbsolutePath());
-                       }
- 
-                       if (targetFile.exists() && !targetFile.canWrite()) {
-                               throw new CayenneRuntimeException("Can't write 
to file '%s'", targetFile.getAbsolutePath());
-                       }
- 
-               }
-       }
- 
-       void saveToTempFiles(Collection<SaveUnit> units) {
- 
-               for (SaveUnit unit : units) {
- 
-                       String name = unit.targetFile.getName();
-                       if (name.length() < 3) {
-                               name = "cayenne-project";
-                       }
- 
-                       File parent = unit.targetFile.getParentFile();
- 
-                       try {
-                               unit.targetTempFile = File.createTempFile(name, 
null, parent);
-                       } catch (IOException e) {
-                               throw new CayenneRuntimeException("Error 
creating temp file (%s)", e, e.getMessage());
-                       }
- 
-                       if (unit.targetTempFile.exists()) {
-                               unit.targetTempFile.delete();
-                       }
- 
-                       try (PrintWriter printWriter = new PrintWriter(new 
OutputStreamWriter(
-                                       new 
FileOutputStream(unit.targetTempFile), fileEncoding))) {
-                               saveToTempFile(unit, printWriter);
-                       } catch (UnsupportedEncodingException e) {
-                               throw new CayenneRuntimeException("Unsupported 
encoding '%s' (%s)", e, fileEncoding, e.getMessage());
-                       } catch (FileNotFoundException e) {
-                               throw new CayenneRuntimeException("File not 
found '%s' (%s)", e, unit.targetTempFile.getAbsolutePath(),
-                                               e.getMessage());
-                       }
-               }
-       }
- 
-       void saveToTempFile(SaveUnit unit, PrintWriter printWriter) {
-               ConfigurationNodeVisitor<?> visitor;
-               if(unit.delegate == null) {
-                       visitor = new ConfigurationSaver(printWriter, 
getSupportedVersion(), delegate);
-               } else {
-                       XMLEncoder encoder = new XMLEncoder(printWriter, "\t", 
getSupportedVersion());
-                       encoder.println("<?xml version=\"1.0\" 
encoding=\"utf-8\"?>");
-                       unit.delegate.setXMLEncoder(encoder);
-                       visitor = unit.delegate;
-               }
- 
-               unit.node.acceptVisitor(visitor);
-       }
- 
-       void saveCommit(Collection<SaveUnit> units) {
- 
-               for (SaveUnit unit : units) {
- 
-                       File targetFile = unit.targetFile;
- 
-                       // Per CAY-2119, this is an ugly hack to force Windows 
to unlock the file that was previously locked by
-                       // our process. Without it, the delete operation 
downstream would fail
-                       System.gc();
- 
-                       if (targetFile.exists()) {
-                               if (!targetFile.delete()) {
-                                       throw new 
CayenneRuntimeException("Unable to remove old master file '%s'",
-                                                       
targetFile.getAbsolutePath());
-                               }
-                       }
- 
-                       File tempFile = unit.targetTempFile;
-                       if (!tempFile.renameTo(targetFile)) {
-                               throw new CayenneRuntimeException("Unable to 
move '%s' to '%s'", tempFile.getAbsolutePath(),
-                                               targetFile.getAbsolutePath());
-                       }
- 
-                       unit.targetTempFile = null;
-                       try {
-                               if(unit.delegate == null) {
-                                       unit.node.acceptVisitor(new 
ConfigurationSourceSetter(new URLResource(targetFile.toURI().toURL())));
-                               }
-                       } catch (MalformedURLException e) {
-                               throw new CayenneRuntimeException("Malformed 
URL for file '%s'", e, targetFile.getAbsolutePath());
-                       }
-               }
-       }
- 
-       private void clearTempFiles(Collection<SaveUnit> units) {
-               for (SaveUnit unit : units) {
- 
-                       if (unit.targetTempFile != null && 
unit.targetTempFile.exists()) {
-                               unit.targetTempFile.delete();
-                               unit.targetTempFile = null;
-                       }
-               }
-       }
- 
-       private void clearRenamedFiles(Collection<SaveUnit> units) throws 
IOException {
-               for (SaveUnit unit : units) {
- 
-                       if (unit.sourceConfiguration == null) {
-                               continue;
-                       }
- 
-                       URL sourceUrl = unit.sourceConfiguration.getURL();
-                       File sourceFile;
-                       try {
-                               sourceFile = Util.toFile(sourceUrl);
-                       } catch (IllegalArgumentException e) {
-                               // ignore non-file configurations...
-                               continue;
-                       }
- 
-                       if (!sourceFile.exists()) {
-                               continue;
-                       }
- 
-                       // compare against ALL unit target files, not just the 
current
-                       // unit... if the
-                       // target matches, skip this file
-                       boolean isTarget = false;
-                       for (SaveUnit xunit : units) {
-                               if (isFilesEquals(sourceFile, 
xunit.targetFile)) {
-                                       isTarget = true;
-                                       break;
-                               }
-                       }
- 
-                       if (!isTarget) {
-                               if (!sourceFile.delete()) {
-                                       throw new 
CayenneRuntimeException("Could not delete file '%s'", 
sourceFile.getCanonicalPath());
-                               }
-                       }
-               }
-       }
- 
-       private boolean isFilesEquals(File firstFile, File secondFile) throws 
IOException {
-               boolean isFirstFileExists = firstFile.exists();
-               boolean isSecondFileExists = secondFile.exists();
- 
-               String firstFilePath = firstFile.getCanonicalPath();
-               String secondFilePath = secondFile.getCanonicalPath();
- 
-               return isFirstFileExists && isSecondFileExists && 
firstFilePath.equals(secondFilePath);
-       }
- 
-       private void deleteUnusedFiles(Collection<URL> unusedResources) throws 
IOException {
-               for (URL unusedResource : unusedResources) {
- 
-                       File unusedFile;
-                       try {
-                               unusedFile = Util.toFile(unusedResource);
-                       } catch (IllegalArgumentException e) {
-                               // ignore non-file configurations...
-                               continue;
-                       }
- 
-                       if (!unusedFile.exists()) {
-                               continue;
-                       }
- 
-                       if (!unusedFile.delete()) {
-                               throw new CayenneRuntimeException("Could not 
delete file '%s'", unusedFile.getCanonicalPath());
-                       }
- 
-               }
-       }
- 
-       static class SaveUnit {
- 
-               private ConfigurationNode node;
-               private SaverDelegate delegate;
- 
-               // source can be an abstract resource, but target is always a 
file...
-               private Resource sourceConfiguration;
-               private File targetFile;
-               private File targetTempFile;
- 
-       }
+     @Inject
+     protected ConfigurationNameMapper nameMapper;
+ 
+     protected ConfigurationNodeVisitor<Resource> resourceGetter;
+     protected ConfigurationNodeVisitor<Collection<ConfigurationNode>> 
saveableNodesGetter;
+     protected String fileEncoding;
+ 
+     protected Collection<ProjectExtension> extensions;
+     protected SaverDelegate delegate;
+ 
+     public FileProjectSaver(@Inject List<ProjectExtension> extensions) {
+         resourceGetter = new ConfigurationSourceGetter();
+         saveableNodesGetter = new SaveableNodesGetter();
+ 
+         // this is not configurable yet... probably doesn't have to be
+         fileEncoding = "UTF-8";
+ 
+         this.extensions = extensions;
+         Collection<SaverDelegate> delegates = new 
ArrayList<>(extensions.size());
+         for (ProjectExtension extension : extensions) {
+             delegates.add(extension.createSaverDelegate());
+         }
+         delegate = new CompoundSaverDelegate(delegates);
+     }
+ 
+     @Override
+     public String getSupportedVersion() {
+         return String.valueOf(Project.VERSION);
+     }
+ 
+     @Override
+     public void save(Project project) {
+         save(project, project.getConfigurationResource(), true);
+     }
+ 
+     @Override
+     public void saveAs(Project project, Resource baseDirectory) {
+         if (baseDirectory == null) {
+             throw new NullPointerException("Null 'baseDirectory'");
+         }
+         save(project, baseDirectory, false);
+     }
+ 
+     void save(Project project, Resource baseResource, boolean 
deleteOldResources) {
+         Collection<ConfigurationNode> nodes = 
project.getRootNode().acceptVisitor(saveableNodesGetter);
+         Collection<SaveUnit> units = new ArrayList<>(nodes.size());
+ 
+         delegate.setBaseDirectory(baseResource);
+ 
+         for (ConfigurationNode node : nodes) {
+             String targetLocation = nameMapper.configurationLocation(node);
+             Resource targetResource = 
baseResource.getRelativeResource(targetLocation);
+             units.add(createSaveUnit(node, targetResource, null));
+ 
+             for (ProjectExtension extension : extensions) {
+                 ConfigurationNodeVisitor<String> namingDelegate = 
extension.createNamingDelegate();
+                 SaverDelegate unitSaverDelegate = 
extension.createSaverDelegate();
+                 String fileName = node.acceptVisitor(namingDelegate);
+                 if (fileName != null) {
+                     // not null means that this should go to a separate file
+                     targetResource = 
baseResource.getRelativeResource(fileName);
+                     units.add(createSaveUnit(node, targetResource, 
unitSaverDelegate));
+                 }
+             }
+         }
+ 
+         checkAccess(units);
+ 
+         try {
+             saveToTempFiles(units);
+             saveCommit(units);
+         } finally {
+             clearTempFiles(units);
+         }
+ 
+         try {
+             if (deleteOldResources) {
+                 clearRenamedFiles(units);
+ 
+                 Collection<URL> unusedResources = 
project.getUnusedResources();
+                 for (SaveUnit unit : units) {
+                     unusedResources.remove(unit.sourceConfiguration.getURL());
+                 }
+                 deleteUnusedFiles(unusedResources);
+             }
+         } catch (IOException ex) {
+             throw new CayenneRuntimeException(ex);
+         }
+ 
+         // I guess we should reset projects state regardless of the value of
+         // 'deleteOldResources'
+         project.getUnusedResources().clear();
+     }
+ 
+     SaveUnit createSaveUnit(ConfigurationNode node, Resource targetResource, 
SaverDelegate delegate) {
+ 
+         SaveUnit unit = new SaveUnit();
+         unit.node = node;
+         unit.delegate = delegate;
+         unit.sourceConfiguration = node.acceptVisitor(resourceGetter);
+ 
+         if (unit.sourceConfiguration == null) {
+             unit.sourceConfiguration = targetResource;
+         }
+ 
+         // attempt to convert targetResource to a File... if that fails,
+         // FileProjectSaver is not appropriate for handling a given project..
+ 
+         URL targetUrl = targetResource.getURL();
+ 
+         try {
+             unit.targetFile = Util.toFile(targetUrl);
+         } catch (IllegalArgumentException e) {
+             throw new CayenneRuntimeException("Can't save configuration to 
the following location: '%s'. "
+                     + "Is this a valid file location?. (%s)", e, targetUrl, 
e.getMessage());
+         }
+ 
+         return unit;
+     }
+ 
+     void checkAccess(Collection<SaveUnit> units) {
+         for (SaveUnit unit : units) {
+ 
+             File targetFile = unit.targetFile;
+ 
+             File parent = targetFile.getParentFile();
+             if (!parent.exists()) {
+                 if (!parent.mkdirs()) {
+                     throw new CayenneRuntimeException("Error creating 
directory tree for '%s'",
+                             parent.getAbsolutePath());
+                 }
+             }
+ 
+             if (targetFile.isDirectory()) {
+                 throw new CayenneRuntimeException("Target file '%s' is a 
directory", targetFile.getAbsolutePath());
+             }
+ 
+             if (targetFile.exists() && !targetFile.canWrite()) {
+                 throw new CayenneRuntimeException("Can't write to file '%s'", 
targetFile.getAbsolutePath());
+             }
+ 
+         }
+     }
+ 
+     void saveToTempFiles(Collection<SaveUnit> units) {
+ 
+         for (SaveUnit unit : units) {
+ 
+             String name = unit.targetFile.getName();
+             if (name.length() < 3) {
+                 name = "cayenne-project";
+             }
+ 
+             File parent = unit.targetFile.getParentFile();
+ 
+             try {
+                 unit.targetTempFile = File.createTempFile(name, null, parent);
+             } catch (IOException e) {
+                 throw new CayenneRuntimeException("Error creating temp file 
(%s)", e, e.getMessage());
+             }
+ 
+             if (unit.targetTempFile.exists()) {
+                 unit.targetTempFile.delete();
+             }
+ 
+             try (PrintWriter printWriter = new PrintWriter(new 
OutputStreamWriter(
+                     new FileOutputStream(unit.targetTempFile), 
fileEncoding))) {
+                 saveToTempFile(unit, printWriter);
+             } catch (UnsupportedEncodingException e) {
+                 throw new CayenneRuntimeException("Unsupported encoding '%s' 
(%s)", e, fileEncoding, e.getMessage());
+             } catch (FileNotFoundException e) {
+                 throw new CayenneRuntimeException("File not found '%s' (%s)", 
e, unit.targetTempFile.getAbsolutePath(),
+                         e.getMessage());
+             }
+         }
+     }
+ 
+     void saveToTempFile(SaveUnit unit, PrintWriter printWriter) {
+         ConfigurationNodeVisitor<?> visitor;
+         if (unit.delegate == null) {
+             visitor = new ConfigurationSaver(printWriter, 
getSupportedVersion(), delegate);
+         } else {
+             XMLEncoder encoder = new XMLEncoder(printWriter, "\t", 
getSupportedVersion());
+             encoder.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+             unit.delegate.setXMLEncoder(encoder);
+             visitor = unit.delegate;
+         }
+ 
+         unit.node.acceptVisitor(visitor);
+     }
+ 
+     void saveCommit(Collection<SaveUnit> units) {
+ 
+         for (SaveUnit unit : units) {
+ 
+             File targetFile = unit.targetFile;
+ 
+             // Per CAY-2119, this is an ugly hack to force Windows to unlock 
the file that was previously locked by
+             // our process. Without it, the delete operation downstream would 
fail
+             System.gc();
+ 
+             if (targetFile.exists()) {
+                 if (!targetFile.delete()) {
+                     throw new CayenneRuntimeException("Unable to remove old 
master file '%s'",
+                             targetFile.getAbsolutePath());
+                 }
+             }
+ 
+             File tempFile = unit.targetTempFile;
+             if (!tempFile.renameTo(targetFile)) {
+                 throw new CayenneRuntimeException("Unable to move '%s' to 
'%s'", tempFile.getAbsolutePath(),
+                         targetFile.getAbsolutePath());
+             }
+ 
+             unit.targetTempFile = null;
+             try {
+                 if (unit.delegate == null) {
+                     URLResource targetUrlResource = new 
URLResource(targetFile.toURI().toURL());
+                     unit.node.acceptVisitor(new 
ConfigurationSourceSetter(targetUrlResource, nameMapper));
+                 }
+             } catch (MalformedURLException e) {
+                 throw new CayenneRuntimeException("Malformed URL for file 
'%s'", e, targetFile.getAbsolutePath());
+             }
+         }
+     }
+ 
+     private void clearTempFiles(Collection<SaveUnit> units) {
+         for (SaveUnit unit : units) {
+ 
+             if (unit.targetTempFile != null && unit.targetTempFile.exists()) {
+                 unit.targetTempFile.delete();
+                 unit.targetTempFile = null;
+             }
+         }
+     }
+ 
+     private void clearRenamedFiles(Collection<SaveUnit> units) throws 
IOException {
+         for (SaveUnit unit : units) {
+ 
+             if (unit.sourceConfiguration == null) {
+                 continue;
+             }
+ 
+             URL sourceUrl = unit.sourceConfiguration.getURL();
+             File sourceFile;
+             try {
+                 sourceFile = Util.toFile(sourceUrl);
+             } catch (IllegalArgumentException e) {
+                 // ignore non-file configurations...
+                 continue;
+             }
+ 
+             if (!sourceFile.exists()) {
+                 continue;
+             }
+ 
+             // compare against ALL unit target files, not just the current
+             // unit... if the
+             // target matches, skip this file
+             boolean isTarget = false;
+             for (SaveUnit xunit : units) {
+                 if (isFilesEquals(sourceFile, xunit.targetFile)) {
+                     isTarget = true;
+                     break;
+                 }
+             }
+ 
+             if (!isTarget) {
+                 if (!sourceFile.delete()) {
+                     throw new CayenneRuntimeException("Could not delete file 
'%s'", sourceFile.getCanonicalPath());
+                 }
+             }
+         }
+     }
+ 
+     private boolean isFilesEquals(File firstFile, File secondFile) throws 
IOException {
+         boolean isFirstFileExists = firstFile.exists();
+         boolean isSecondFileExists = secondFile.exists();
+ 
+         String firstFilePath = firstFile.getCanonicalPath();
+         String secondFilePath = secondFile.getCanonicalPath();
+ 
+         return isFirstFileExists && isSecondFileExists && 
firstFilePath.equals(secondFilePath);
+     }
+ 
+     private void deleteUnusedFiles(Collection<URL> unusedResources) throws 
IOException {
+         for (URL unusedResource : unusedResources) {
+ 
+             File unusedFile;
+             try {
+                 unusedFile = Util.toFile(unusedResource);
+             } catch (IllegalArgumentException e) {
+                 // ignore non-file configurations...
+                 continue;
+             }
+ 
+             if (!unusedFile.exists()) {
+                 continue;
+             }
+ 
+             if (!unusedFile.delete()) {
+                 throw new CayenneRuntimeException("Could not delete file 
'%s'", unusedFile.getCanonicalPath());
+             }
+ 
+         }
+     }
+ 
 -    class SaveUnit {
++    static class SaveUnit {
+ 
+         private ConfigurationNode node;
+         private SaverDelegate delegate;
+ 
+         // source can be an abstract resource, but target is always a file...
+         private Resource sourceConfiguration;
+         private File targetFile;
+         private File targetTempFile;
+ 
+     }
  }

Reply via email to