You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2022/11/10 11:51:33 UTC

[cayenne] 01/03: Merge remote-tracking branch 'parent/pr/463' into asf-master

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 <st...@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;
+ 
+     }
  }