待辦事項 #20331

Keep line separator while editing an existed layout and event xml file

啟用日期: 2010-01-17 16:51 最後更新: 2010-01-26 01:18

回報者:
負責人:
類型:
狀態:
開啟 [Owner assigned]
元件:
里程碑:
(無)
優先權:
5 - 中
嚴重程度:
5 - 中
處理結果:
檔案:

細節

The patch fixes two issues:

  1. On windows system, as the system line separator is "\r\n", the maskat ide writes the xml prolog manually(outputWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");) with a "\n" ended. This will cause un-unified line separators.
  2. When editing an existed layout/event file, keep the old line separator in the existed file or if not found use line delimiter that in project prefrence or if still not found use the one in workspace prefrence or the system line separator for fail-safe.(Why so? To keep unified line separators between the develop team members if they are using different operating systems)
diff -ruN /Users/sutra/Downloads/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.core/src/jp/sf/maskat/core/betwixt/MaskatBeanIO.java /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.core/src/jp/sf/maskat/core/betwixt/MaskatBeanIO.java
--- /Users/sutra/Downloads/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.core/src/jp/sf/maskat/core/betwixt/MaskatBeanIO.java	2009-07-31 11:15:54.000000000 +0900
+++ /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.core/src/jp/sf/maskat/core/betwixt/MaskatBeanIO.java	2010-01-17 15:38:01.000000000 +0900
@@ -31,6 +31,11 @@
 	public static final String LAYOUT_DEF_CONFIG = "layoutConfig.betwixt";
 
 	/**
+	 * XML declaration string.
+	 */
+	private static final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+
+	/**
 	 * 
 	 * @param input Input source containing the XML data to be parsed
 	 * @return
@@ -99,15 +104,12 @@
 	 * @return
 	 * @throws Exception
 	 */
-	public static String writeEventDef(EventDef eventDef) throws Exception {
+	public static String writeEventDef(EventDef eventDef, String lineSeparator)
+			throws Exception {
         // Start by preparing the writer
         // We'll write to a string 
         StringWriter outputWriter = new StringWriter(); 
         
-        // Betwixt just writes out the bean as a fragment
-        // So if we want well-formed xml, we need to add the prolog
-        outputWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-        
         // Create a BeanWriter which writes to our prepared stream
         BeanWriter beanWriter = new BeanWriter(outputWriter);
         
@@ -122,10 +124,18 @@
         beanWriter.enablePrettyPrint();
         beanWriter.setInitialIndentLevel(0);
         beanWriter.setWriteEmptyElements(false);
+        beanWriter.setEndOfLine(lineSeparator);
 
         XMLIntrospector intro = beanWriter.getXMLIntrospector();
 		InputStream in = MaskatBeanIO.class.getResourceAsStream(EVENT_DEF_CONFIG);
         intro.register(new InputSource(in));
+
+        // Betwixt just writes out the bean as a fragment
+        // So if we want well-formed xml, we need to add the prolog
+        // Write XML declaration string.
+        // See <a href="http://commons.apache.org/betwixt/apidocs/org/apache/commons/betwixt/io/BeanWriter.html#writeXmlDeclaration%28java.lang.String%29">writeXmlDeclaration</a>
+        beanWriter.writeXmlDeclaration(XML_DECLARATION);
+
         // If the base element is not passed in, Betwixt will guess 
         // But let's write bean as base element 
         beanWriter.write(eventDef);
@@ -224,15 +234,12 @@
 		return readLayoutDef(new InputSource(stream));
 	}
 	
-	public static String writeLayoutDef(LayoutDef layoutDef) throws Exception {
+	public static String writeLayoutDef(LayoutDef layoutDef,
+			String lineSeparator) throws Exception {
         // Start by preparing the writer
         // We'll write to a string 
         StringWriter outputWriter = new StringWriter(); 
         
-        // Betwixt just writes out the bean as a fragment
-        // So if we want well-formed xml, we need to add the prolog
-        outputWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-        
         // Create a BeanWriter which writes to our prepared stream
         BeanWriter beanWriter = new MaskatBeanWriter(outputWriter);
         
@@ -246,6 +253,7 @@
         beanWriter.enablePrettyPrint();
         beanWriter.setInitialIndentLevel(0);
         beanWriter.setWriteEmptyElements(false);
+        beanWriter.setEndOfLine(lineSeparator);
 
         MaskatNamespacePrefixMapper namespaceMapper = new MaskatNamespacePrefixMapper();
         Map namespaces = layoutDef.getNamespaces();
@@ -260,6 +268,12 @@
 		InputStream in = MaskatBeanIO.class.getResourceAsStream(LAYOUT_DEF_CONFIG);
         intro.register(new InputSource(in));
 
+        // Betwixt just writes out the bean as a fragment
+        // So if we want well-formed xml, we need to add the prolog
+        // Write XML declaration string.
+        // See <a href="http://commons.apache.org/betwixt/apidocs/org/apache/commons/betwixt/io/BeanWriter.html#writeXmlDeclaration%28java.lang.String%29">writeXmlDeclaration</a>
+        beanWriter.writeXmlDeclaration(XML_DECLARATION);
+
         // If the base element is not passed in, Betwixt will guess 
         // But let's write bean as base element 
         beanWriter.write(layoutDef);
diff -ruN /Users/sutra/Downloads/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/LineSeparatorUtils.java /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/LineSeparatorUtils.java
--- /Users/sutra/Downloads/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/LineSeparatorUtils.java	1970-01-01 09:00:00.000000000 +0900
+++ /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/LineSeparatorUtils.java	2010-01-17 15:47:46.000000000 +0900
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2006-2009 Maskat Project.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Maskat Project - initial API and implementation
+ */
+package jp.sf.maskat.ui.editors.layout;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+
+/**
+ * Provides line separator utility methods for eclipse plugin.
+ */
+public class LineSeparatorUtils {
+
+	private LineSeparatorUtils() {
+		// Use private modifier to avoid to be instantiated.
+	}
+
+	/**
+	 * Finds the first line separator used by the given text.
+	 * 
+	 * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code>,
+	 *         or <code>null</code> if none found
+	 */
+	public static String findLineSeparator(char[] text) {
+		// find the first line separator
+		int length = text.length;
+		if (length > 0) {
+			char nextChar = text[0];
+			for (int i = 0; i < length; i++) {
+				char currentChar = nextChar;
+				nextChar = i < length - 1 ? text[i + 1] : ' ';
+				switch (currentChar) {
+				case '\n':
+					return "\n";
+				case '\r':
+					return nextChar == '\n' ? "\r\n" : "\r";
+				}
+			}
+		}
+		// not found
+		return null;
+	}
+
+	/**
+	 * Returns the line separator of the given file.
+	 * 
+	 * @param file
+	 *            the file
+	 * @param encoding
+	 *            encoding of the file
+	 * @return the line separator
+	 * @throws CoreException
+	 *             if failed while opening stream of the file
+	 * @throws IOException
+	 *             if failed while reading the file stream
+	 * @see #getLineSeparator(String, IProject)
+	 */
+	public static String getLineSeparator(IFile file, String encoding)
+			throws CoreException, IOException {
+		String text = null;
+		if (file.exists()) {
+			InputStream in = file.getContents();
+			try {
+				text = IOUtils.toString(in, encoding);
+			} finally {
+				IOUtils.closeQuietly(in);
+			}
+		}
+		return getLineSeparator(text, file.getProject());
+	}
+
+	/**
+	 * Returns the line separator found in the given text. If it is null, or not
+	 * found returns the line delimiter for the given project. If the project is
+	 * null, returns the line separator for the workspace. If still null,
+	 * returns the system line separator.
+	 * 
+	 * @param text
+	 *            the given text
+	 * @param project
+	 *            the project
+	 * @return the line separator
+	 */
+	public static String getLineSeparator(String text, IProject project) {
+		String lineSeparator = null;
+
+		// Line delimiter in given text
+		if (text != null && text.length() != 0) {
+			lineSeparator = findLineSeparator(text.toCharArray());
+		}
+
+		// Line delimiter in project preference
+		if (lineSeparator == null && project != null) {
+			lineSeparator = getProjectLineSeparator(project);
+		}
+
+		// Line delimiter in workspace preference
+		if (lineSeparator == null) {
+			lineSeparator = getWorkspaceLineSeparator();
+		}
+
+		// System line delimiter
+		if (lineSeparator == null) {
+			lineSeparator = IOUtils.LINE_SEPARATOR;
+		}
+
+		return lineSeparator;
+	}
+
+	/**
+	 * Returns the line delimiter in the project preference.
+	 * 
+	 * @param project
+	 *            the project
+	 * @return the line delimiter in the project preference
+	 */
+	public static String getProjectLineSeparator(IProject project) {
+		IScopeContext[] scopeContext;
+		scopeContext = new IScopeContext[] { new ProjectScope(project
+				.getProject()) };
+		String lineSeparator = Platform.getPreferencesService().getString(
+				Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null,
+				scopeContext);
+		return lineSeparator;
+	}
+
+	/**
+	 * Returns the line delimiter in workspace preference.
+	 * 
+	 * @return the line delimiter in workspace preference
+	 */
+	public static String getWorkspaceLineSeparator() {
+		IScopeContext[] scopeContext = new IScopeContext[] { new InstanceScope() };
+		String lineSeparator = Platform.getPreferencesService().getString(
+				Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null,
+				scopeContext);
+		return lineSeparator;
+	}
+}
diff -ruN /Users/sutra/Downloads/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/MaskatResources.java /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/MaskatResources.java
--- /Users/sutra/Downloads/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/MaskatResources.java	2009-07-31 11:16:06.000000000 +0900
+++ /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/editors/layout/MaskatResources.java	2010-01-17 15:43:26.000000000 +0900
@@ -45,6 +45,10 @@
 
 	private IFile eventXMLFile;
 
+	private String layoutXMLFileLineSeparator;
+
+	private String eventXMLFileLineSeparator;
+
 	MaskatResources(IFile layoutXMLFile) {
 		this.layoutXMLFile = layoutXMLFile;
 
@@ -80,6 +84,9 @@
 	}
 
 	void loadLayout() throws Exception {
+		layoutXMLFileLineSeparator = LineSeparatorUtils.getLineSeparator(
+				layoutXMLFile, "UTF-8");
+
 		InputStream in = null;
 		try {
 			if (layoutXMLFile.exists()) {
@@ -104,6 +111,9 @@
 	}
 
 	void loadEvent() throws Exception {
+		eventXMLFileLineSeparator = LineSeparatorUtils.getLineSeparator(
+				eventXMLFile, "UTF-8");
+
 		// XXX temporarily, assume that files is not empty or null
 		eventDef = new EventDef();
 		InputStream in = null;
@@ -131,7 +141,8 @@
 			((Layout) it.next()).packRadioGroup();
 		}*/
 		//why use clone()?, clone() will cause the propertychange.  
-		String output = MaskatBeanIO.writeLayoutDef((LayoutDef)layoutDef/*.clone()*/);
+		String output = MaskatBeanIO.writeLayoutDef((LayoutDef)layoutDef/*.clone()*/,
+				layoutXMLFileLineSeparator);
 
 //		byte[] bytes = writer.toString().getBytes("UTF-8");
 		byte[] bytes = output.getBytes("UTF-8");
@@ -149,7 +160,8 @@
 
 //		eventDef.shrinkEvent();
 
-		MaskatResources.marshallObj(eventDef, eventXMLFile, null);
+		MaskatResources.marshallObj(eventDef, eventXMLFile, null,
+				eventXMLFileLineSeparator);
 
 		// event is shrinked so expand them
 		eventDef.prepareEvent();
@@ -238,7 +250,8 @@
 		}*/
 	}
 
-	public static String marshallObj(Object obj, IFile file, IProgressMonitor monitor)
+	public static String marshallObj(Object obj, IFile file,
+			IProgressMonitor monitor, String eventXMLFileLineSeparator)
 			throws Exception {
 
 //		StringWriter strWriter = new StringWriter(1024);
@@ -246,7 +259,8 @@
 //		DefXmlSerializer serializer = new EventDefXmlSerializer(obj, strWriter);
 //		serializer.write();
 //		String result = strWriter.toString();
-		String result = MaskatBeanIO.writeEventDef((EventDef)obj);
+		String result = MaskatBeanIO.writeEventDef((EventDef)obj,
+				eventXMLFileLineSeparator);
 
 		if (!file.exists()) {
 			file.create(new ByteArrayInputStream(new byte[0]), false, null);

Ticket History (3/4 Histories)

2010-01-17 16:51 Updated by: sutra
  • New Ticket "Keep line separator while editing an existed layout and event xml file" created
2010-01-20 17:10 Updated by: kazatoh
  • 負責人 Update from (無) to kazatoh
評語

Hi sutra,

Thank you for your contribution. I'm going to merge your patch to the next release of Maskat IDE.

Before doing so, let me confirm the copyright of your patch. It seems that LineSeparatorUtils.java is derived from SpringCoreUtils.java of the Spring IDE, isn't it? Even if it's true, there would be not so much problem -- both files are licensed under Eclipse Puglic License (EPL) 1.0. All I have to do is to list 'Spring IDE Developers' as the initial contributors of this file.

https://fisheye.springsource.org/browse/spring-ide/trunk/org.springframework.ide.eclipse.core/src/org/springframework/ide/eclipse/core/SpringCoreUtils.java?r=HEAD

Thanks in advance,

kaz@

2010-01-26 01:18 Updated by: sutra
評語

Continue the patch for new layout wizard:

diff -ruN /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731.1/jp.sf.maskat.ui/src/jp/sf/maskat/ui/wizards/layout/NewLayoutFileWizard.java /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/wizards/layout/NewLayoutFileWizard.java
--- /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731.1/jp.sf.maskat.ui/src/jp/sf/maskat/ui/wizards/layout/NewLayoutFileWizard.java	2010-01-25 23:46:10.000000000 +0900
+++ /Users/sutra/workspace/maskat-ide-src-2.1.1.v20090731/jp.sf.maskat.ui/src/jp/sf/maskat/ui/wizards/layout/NewLayoutFileWizard.java	2010-01-26 01:10:11.000000000 +0900
@@ -25,7 +25,9 @@
 import jp.sf.maskat.ui.MaskatUIPlugin;
 import jp.sf.maskat.ui.Messages;
 import jp.sf.maskat.ui.editors.layout.LayoutGraphicalEditor;
+import jp.sf.maskat.ui.editors.layout.LineSeparatorUtils;
 
+import org.apache.commons.io.IOUtils;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
@@ -140,20 +142,25 @@
 		
 		IContainer container = (IContainer) resource;
 		final IFile file = container.getFile(new Path(fileName));
-		try {
-			InputStream stream = openContentStream(layoutName);
-			if (file.exists()) {
-				String[] msgArgs = {fileName};
-				throwCoreException(Messages.format(
-					"wizard.layout.msg.error.existfile", msgArgs)); 
-				
+		if (file.exists()) {
+			String[] msgArgs = {fileName};
+			throwCoreException(Messages.format(
+				"wizard.layout.msg.error.existfile", msgArgs)); 
+			
 //				throwCoreException(
 //					Messages.getString("wizard.layout.msg.error.existfile")); //$NON-NLS-1$
-			} else {
+		} else {
+			String lineSeparator = LineSeparatorUtils.getLineSeparator(null,
+					file.getProject());
+			InputStream stream = null;
+			try {
+				stream = openContentStream(layoutName, lineSeparator);
 				file.create(stream, true, monitor);
+			} catch (IOException e) {
+				throwCoreException("Read template failed: " + e.getMessage());
+			} finally {
+				IOUtils.closeQuietly(stream);
 			}
-			stream.close();
-		} catch (IOException e) {
 		}
 		
 		monitor.worked(1);
@@ -173,7 +180,8 @@
 		monitor.worked(1);
 	}
 
-	private String getTemplate(String templateName) throws IOException {
+	private String getTemplate(String templateName, String lineSeparator)
+			throws IOException {
 		InputStream in = null;
 		ByteArrayOutputStream baos = new ByteArrayOutputStream();
 		try {
@@ -183,7 +191,8 @@
 			
 			String line = null;
 			while ((line = reader.readLine()) != null) {
-				pw.println(line);
+				pw.print(line);
+				pw.print(lineSeparator);
 			}
 			pw.close();
 			
@@ -201,9 +210,10 @@
 	 * @throws UnsupportedEncodingException
 	 */
 
-	private InputStream openContentStream(String layoutName)
+	private InputStream openContentStream(String layoutName,
+			String lineSeparator)
 			throws UnsupportedEncodingException, IOException {
-		String contents = getTemplate("layout.template"); //$NON-NLS-1$
+		String contents = getTemplate("layout.template", lineSeparator); //$NON-NLS-1$
 		contents = contents.replaceAll("\\Q${layoutName}\\E", layoutName); //$NON-NLS-1$
 		return new ByteArrayInputStream(contents.getBytes("UTF-8")); //$NON-NLS-1$
 	}

Attachment File List

No attachments

編輯

Please login to add comment to this ticket » 登入