1 /*******************************************************************************
2  * Copyright (c) 2000, 2019 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Microsoft Corporation - copied to jdt.core.manipulation
14  *******************************************************************************/
15 package org.eclipse.jdt.internal.corext.refactoring.nls.changes;
16 
17 import java.io.ByteArrayInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.UnsupportedEncodingException;
21 import java.net.URI;
22 
23 import org.eclipse.core.filesystem.EFS;
24 import org.eclipse.core.filesystem.IFileInfo;
25 
26 import org.eclipse.core.runtime.Assert;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IPath;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.OperationCanceledException;
31 import org.eclipse.core.runtime.Platform;
32 import org.eclipse.core.runtime.SubProgressMonitor;
33 import org.eclipse.core.runtime.content.IContentType;
34 
35 import org.eclipse.core.resources.IFile;
36 import org.eclipse.core.resources.IResource;
37 import org.eclipse.core.resources.ResourcesPlugin;
38 
39 import org.eclipse.ltk.core.refactoring.Change;
40 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
41 import org.eclipse.ltk.core.refactoring.resource.DeleteResourceChange;
42 import org.eclipse.ltk.core.refactoring.resource.ResourceChange;
43 
44 import org.eclipse.jdt.core.IJavaModelStatusConstants;
45 import org.eclipse.jdt.core.JavaModelException;
46 
47 import org.eclipse.jdt.internal.corext.util.Messages;
48 
49 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
50 
51 public class CreateFileChange extends ResourceChange {
52 
53 	private String fChangeName;
54 
55 	private IPath fPath;
56 	private String fSource;
57 	private String fEncoding;
58 	private boolean fExplicitEncoding;
59 	private long fStampToRestore;
60 
CreateFileChange(IPath path, String source, String encoding)61 	public CreateFileChange(IPath path, String source, String encoding) {
62 		this(path, source, encoding, IResource.NULL_STAMP);
63 	}
64 
CreateFileChange(IPath path, String source, String encoding, long stampToRestore)65 	public CreateFileChange(IPath path, String source, String encoding, long stampToRestore) {
66 		Assert.isNotNull(path, "path"); //$NON-NLS-1$
67 		Assert.isNotNull(source, "source"); //$NON-NLS-1$
68 		fPath= path;
69 		fSource= source;
70 		fEncoding= encoding;
71 		fExplicitEncoding= fEncoding != null;
72 		fStampToRestore= stampToRestore;
73 	}
74 
75 	/*
76 	private CreateFileChange(IPath path, String source, String encoding, long stampToRestore, boolean explicit) {
77 		Assert.isNotNull(path, "path"); //$NON-NLS-1$
78 		Assert.isNotNull(source, "source"); //$NON-NLS-1$
79 		Assert.isNotNull(encoding, "encoding"); //$NON-NLS-1$
80 		fPath= path;
81 		fSource= source;
82 		fEncoding= encoding;
83 		fStampToRestore= stampToRestore;
84 		fExplicitEncoding= explicit;
85 	}
86 	*/
87 
setEncoding(String encoding, boolean explicit)88 	protected void setEncoding(String encoding, boolean explicit) {
89 		Assert.isNotNull(encoding, "encoding"); //$NON-NLS-1$
90 		fEncoding= encoding;
91 		fExplicitEncoding= explicit;
92 	}
93 
94 	@Override
getName()95 	public String getName() {
96 		if (fChangeName == null)
97 			return Messages.format(NLSChangesMessages.createFile_Create_file, BasicElementLabels.getPathLabel(fPath, false));
98 		else
99 			return fChangeName;
100 	}
101 
setName(String name)102 	public void setName(String name) {
103 		fChangeName= name;
104 	}
105 
setSource(String source)106 	protected void setSource(String source) {
107 		fSource= source;
108 	}
109 
getSource()110 	protected String getSource() {
111 		return fSource;
112 	}
113 
setPath(IPath path)114 	protected void setPath(IPath path) {
115 		fPath= path;
116 	}
117 
getPath()118 	protected IPath getPath() {
119 		return fPath;
120 	}
121 
122 	@Override
getModifiedResource()123 	protected IResource getModifiedResource() {
124 		return ResourcesPlugin.getWorkspace().getRoot().getFile(fPath);
125 	}
126 
127 	@Override
isValid(IProgressMonitor pm)128 	public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException {
129 		RefactoringStatus result= new RefactoringStatus();
130 		IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(fPath);
131 
132 		URI location= file.getLocationURI();
133 		if (location == null) {
134 			result.addFatalError(Messages.format(
135 				NLSChangesMessages.CreateFileChange_error_unknownLocation,
136 				BasicElementLabels.getPathLabel(file.getFullPath(), false)));
137 			return result;
138 		}
139 
140 		IFileInfo jFile= EFS.getStore(location).fetchInfo();
141 		if (jFile.exists()) {
142 			result.addFatalError(Messages.format(
143 				NLSChangesMessages.CreateFileChange_error_exists,
144 				BasicElementLabels.getPathLabel(file.getFullPath(), false)));
145 			return result;
146 		}
147 		return result;
148 	}
149 
150 	@Override
perform(IProgressMonitor pm)151 	public Change perform(IProgressMonitor pm) throws CoreException, OperationCanceledException {
152 
153 		InputStream is= null;
154 		try {
155 			pm.beginTask(NLSChangesMessages.createFile_creating_resource, 3);
156 
157 			initializeEncoding();
158 			IFile file= getOldFile(new SubProgressMonitor(pm, 1));
159 			/*
160 			if (file.exists()) {
161 				CompositeChange composite= new CompositeChange(getName());
162 				composite.add(new DeleteFileChange(file));
163 				composite.add(new CreateFileChange(fPath, fSource, fEncoding, fStampToRestore, fExplicitEncoding));
164 				pm.worked(1);
165 				return composite.perform(new SubProgressMonitor(pm, 1));
166 			} else { */
167 			try {
168 				is= new ByteArrayInputStream(fSource.getBytes(fEncoding));
169 				file.create(is, false, new SubProgressMonitor(pm, 1));
170 				if (fStampToRestore != IResource.NULL_STAMP) {
171 					file.revertModificationStamp(fStampToRestore);
172 				}
173 				if (fExplicitEncoding) {
174 					file.setCharset(fEncoding, new SubProgressMonitor(pm, 1));
175 				} else {
176 					pm.worked(1);
177 				}
178 				return new DeleteResourceChange(file.getFullPath(), true);
179 			} catch (UnsupportedEncodingException e) {
180 				throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
181 			}
182 		} finally {
183 			try {
184 				if (is != null)
185 					is.close();
186 			} catch (IOException ioe) {
187 				throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION);
188 			} finally {
189 				pm.done();
190 			}
191 		}
192 	}
193 
getOldFile(IProgressMonitor pm)194 	protected IFile getOldFile(IProgressMonitor pm) throws OperationCanceledException {
195 		pm.beginTask("", 1); //$NON-NLS-1$
196 		try {
197 			return ResourcesPlugin.getWorkspace().getRoot().getFile(fPath);
198 		} finally {
199 			pm.done();
200 		}
201 	}
202 
initializeEncoding()203 	private void initializeEncoding() {
204 		if (fEncoding == null) {
205 			fExplicitEncoding= false;
206 			IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(fPath);
207 			if (file != null) {
208 				try {
209 					if (file.exists()) {
210 						fEncoding= file.getCharset(false);
211 						if (fEncoding == null) {
212 							fEncoding= file.getCharset(true);
213 						} else {
214 							fExplicitEncoding= true;
215 						}
216 					} else {
217 						IContentType contentType= Platform.getContentTypeManager().findContentTypeFor(file.getName());
218 						if (contentType != null)
219 							fEncoding= contentType.getDefaultCharset();
220 						if (fEncoding == null)
221 							fEncoding= file.getCharset(true);
222 					}
223 				} catch (CoreException e) {
224 					fEncoding= ResourcesPlugin.getEncoding();
225 					fExplicitEncoding= true;
226 				}
227 			} else {
228 				fEncoding= ResourcesPlugin.getEncoding();
229 				fExplicitEncoding= true;
230 			}
231 		}
232 		Assert.isNotNull(fEncoding);
233 	}
234 }
235