1 11 package org.eclipse.core.internal.resources; 12 13 import java.util.*; 14 import org.eclipse.core.internal.utils.Messages; 15 import org.eclipse.core.internal.utils.Policy; 16 import org.eclipse.core.resources.*; 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.core.runtime.jobs.ISchedulingRule; 19 import org.eclipse.core.runtime.jobs.Job; 20 import org.osgi.framework.Bundle; 21 import org.osgi.service.prefs.BackingStoreException; 22 import org.osgi.service.prefs.Preferences; 23 24 29 public class CharsetManager implements IManager { 30 34 private class CharsetManagerJob extends Job { 35 private static final int CHARSET_UPDATE_DELAY = 500; 36 private List asyncChanges = new ArrayList(); 37 38 public CharsetManagerJob() { 39 super(Messages.resources_charsetUpdating); 40 setSystem(true); 41 setPriority(Job.INTERACTIVE); 42 } 43 44 public void addChanges(Set newChanges) { 45 if (newChanges.isEmpty()) 46 return; 47 synchronized (asyncChanges) { 48 asyncChanges.addAll(newChanges); 49 asyncChanges.notify(); 50 } 51 schedule(CHARSET_UPDATE_DELAY); 52 } 53 54 public IProject getNextChange() { 55 synchronized (asyncChanges) { 56 return asyncChanges.isEmpty() ? null : (IProject) asyncChanges.remove(asyncChanges.size() - 1); 57 } 58 } 59 60 63 protected IStatus run(IProgressMonitor monitor) { 64 MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_SETTING_CHARSET, Messages.resources_updatingEncoding, null); 65 monitor = Policy.monitorFor(monitor); 66 try { 67 monitor.beginTask(Messages.resources_charsetUpdating, Policy.totalWork); 68 final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(workspace.getRoot()); 69 try { 70 workspace.prepareOperation(rule, monitor); 71 workspace.beginOperation(true); 72 IProject next; 73 while ((next = getNextChange()) != null) { 74 if (systemBundle.getState() != Bundle.ACTIVE) 77 return Status.OK_STATUS; 78 try { 79 if (next.isAccessible()) { 80 Preferences projectPrefs = getPreferences(next, false); 81 if (projectPrefs != null) 82 projectPrefs.flush(); 83 } 84 } catch (BackingStoreException e) { 85 String detailMessage = Messages.resources_savingEncoding; 87 result.add(new ResourceStatus(IResourceStatus.FAILED_SETTING_CHARSET, next.getFullPath(), detailMessage, e)); 88 } 89 } 90 monitor.worked(Policy.opWork); 91 } catch (OperationCanceledException e) { 92 workspace.getWorkManager().operationCanceled(); 93 throw e; 94 } finally { 95 workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork)); 96 } 97 } catch (CoreException ce) { 98 return ce.getStatus(); 99 } finally { 100 monitor.done(); 101 } 102 return result; 103 } 104 105 108 public boolean shouldRun() { 109 synchronized (asyncChanges) { 110 return !asyncChanges.isEmpty(); 111 } 112 } 113 } 114 115 class Listener implements IResourceChangeListener { 116 117 private void processEntryChanges(IResourceDelta projectDelta, Set projectsToSave) { 118 boolean resourceChanges = false; 121 IProject currentProject = (IProject) projectDelta.getResource(); 122 Preferences projectPrefs = getPreferences(currentProject, false); 123 if (projectPrefs == null) 124 return; 126 String [] affectedResources; 127 try { 128 affectedResources = projectPrefs.keys(); 129 } catch (BackingStoreException e) { 130 String message = Messages.resources_readingEncoding; 132 Policy.log(new ResourceStatus(IResourceStatus.FAILED_GETTING_CHARSET, currentProject.getFullPath(), message, e)); 133 return; 134 } 135 for (int i = 0; i < affectedResources.length; i++) { 136 IResourceDelta memberDelta = projectDelta.findMember(new Path(affectedResources[i])); 137 if (memberDelta == null) 139 continue; 140 if (memberDelta.getKind() == IResourceDelta.REMOVED) { 141 resourceChanges = true; 142 String currentValue = projectPrefs.get(affectedResources[i], null); 144 projectPrefs.remove(affectedResources[i]); 145 if ((memberDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) { 146 IProject targetProject = workspace.getRoot().getProject(memberDelta.getMovedToPath().segment(0)); 148 Preferences targetPrefs = getPreferences(targetProject, true); 149 targetPrefs.put(getKeyFor(memberDelta.getMovedToPath()), currentValue); 150 if (targetProject != currentProject) 151 projectsToSave.add(targetProject); 152 } 153 } 154 } 155 if (resourceChanges) 156 projectsToSave.add(currentProject); 157 } 158 159 163 public void resourceChanged(IResourceChangeEvent event) { 164 IResourceDelta delta = event.getDelta(); 165 if (delta == null) 166 return; 167 IResourceDelta[] projectDeltas = delta.getAffectedChildren(); 168 Set projectsToSave = new HashSet(); 170 for (int i = 0; i < projectDeltas.length; i++) 171 if (projectDeltas[i].getKind() == IResourceDelta.CHANGED && (projectDeltas[i].getFlags() & IResourceDelta.OPEN) == 0) 173 processEntryChanges(projectDeltas[i], projectsToSave); 174 job.addChanges(projectsToSave); 175 } 176 } 177 178 public static final String ENCODING_PREF_NODE = "encoding"; private static final String PROJECT_KEY = "<project>"; private CharsetDeltaJob charsetListener; 181 CharsetManagerJob job; 182 private IResourceChangeListener listener; 183 protected final Bundle systemBundle = Platform.getBundle("org.eclipse.osgi"); Workspace workspace; 185 186 public CharsetManager(Workspace workspace) { 187 this.workspace = workspace; 188 } 189 190 200 public String getCharsetFor(IPath resourcePath, boolean recurse) { 201 Assert.isLegal(resourcePath.segmentCount() >= 1); 202 IProject project = workspace.getRoot().getProject(resourcePath.segment(0)); 203 Preferences encodingSettings = getPreferences(project, false); 204 if (encodingSettings == null) 205 return recurse ? ResourcesPlugin.getEncoding() : null; 208 return internalGetCharsetFor(resourcePath, encodingSettings, recurse); 209 } 210 211 String getKeyFor(IPath resourcePath) { 212 return resourcePath.segmentCount() > 1 ? resourcePath.removeFirstSegments(1).toString() : PROJECT_KEY; 213 } 214 215 Preferences getPreferences(IProject project, boolean create) { 216 if (create) 217 return new ProjectScope(project).getNode(ResourcesPlugin.PI_RESOURCES).node(ENCODING_PREF_NODE); 219 Preferences node = Platform.getPreferencesService().getRootNode().node(ProjectScope.SCOPE); 221 try { 222 if (!node.nodeExists(project.getName())) 227 return null; 228 node = node.node(project.getName()); 229 if (!node.nodeExists(ResourcesPlugin.PI_RESOURCES)) 230 return null; 231 node = node.node(ResourcesPlugin.PI_RESOURCES); 232 if (!node.nodeExists(ENCODING_PREF_NODE)) 233 return null; 234 return node.node(ENCODING_PREF_NODE); 235 } catch (BackingStoreException e) { 236 String message = Messages.resources_readingEncoding; 238 Policy.log(new ResourceStatus(IResourceStatus.FAILED_GETTING_CHARSET, project.getFullPath(), message, e)); 239 } 240 return null; 241 } 242 243 private String internalGetCharsetFor(IPath resourcePath, Preferences encodingSettings, boolean recurse) { 244 String charset = encodingSettings.get(getKeyFor(resourcePath), null); 245 if (!recurse) 246 return charset; 247 while (charset == null && resourcePath.segmentCount() > 1) { 248 resourcePath = resourcePath.removeLastSegments(1); 249 charset = encodingSettings.get(getKeyFor(resourcePath), null); 250 } 251 return charset == null ? ResourcesPlugin.getEncoding() : charset; 253 } 254 255 public void projectPreferencesChanged(IProject project) { 256 charsetListener.charsetPreferencesChanged(project); 257 } 258 259 public void setCharsetFor(IPath resourcePath, String newCharset) throws CoreException { 260 if (resourcePath.segmentCount() == 0) { 262 org.eclipse.core.runtime.Preferences resourcesPreferences = ResourcesPlugin.getPlugin().getPluginPreferences(); 263 if (newCharset != null) 264 resourcesPreferences.setValue(ResourcesPlugin.PREF_ENCODING, newCharset); 265 else 266 resourcesPreferences.setToDefault(ResourcesPlugin.PREF_ENCODING); 267 ResourcesPlugin.getPlugin().savePluginPreferences(); 268 return; 269 } 270 IProject project = workspace.getRoot().getProject(resourcePath.segment(0)); 272 Preferences encodingSettings = getPreferences(project, true); 273 if (newCharset == null || newCharset.trim().length() == 0) 274 encodingSettings.remove(getKeyFor(resourcePath)); 275 else 276 encodingSettings.put(getKeyFor(resourcePath), newCharset); 277 try { 278 charsetListener.setDisabled(true); 280 encodingSettings.flush(); 282 } catch (BackingStoreException e) { 283 String message = Messages.resources_savingEncoding; 284 throw new ResourceException(IResourceStatus.FAILED_SETTING_CHARSET, project.getFullPath(), message, e); 285 } finally { 286 charsetListener.setDisabled(false); 287 } 288 289 } 290 291 public void shutdown(IProgressMonitor monitor) { 292 workspace.removeResourceChangeListener(listener); 293 if (charsetListener != null) 294 charsetListener.shutdown(); 295 } 296 297 public void startup(IProgressMonitor monitor) { 298 job = new CharsetManagerJob(); 299 listener = new Listener(); 300 workspace.addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE); 301 charsetListener = new CharsetDeltaJob(workspace); 302 charsetListener.startup(); 303 } 304 } 305 | Popular Tags |