1 19 20 package org.apache.cayenne.project; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 29 import org.apache.cayenne.conf.ConfigStatus; 30 import org.apache.cayenne.conf.Configuration; 31 import org.apache.cayenne.project.validator.Validator; 32 33 43 public abstract class Project { 44 45 public static final String CURRENT_PROJECT_VERSION = "2.0"; 46 static final int UPGRADE_STATUS_OLD = -1; 47 static final int UPGRADE_STATUS_CURRENT = 0; 48 static final int UPGRADE_STATUS_NEW = 1; 49 50 protected File projectDir; 51 protected List files = new ArrayList (); 52 protected int upgradeStatus; 53 protected List upgradeMessages; 54 protected boolean modified; 55 56 59 public static Project createProject(File projectFile) { 60 String fileName = projectFile.getName(); 61 62 if (fileName.endsWith(Configuration.DEFAULT_DOMAIN_FILE)) { 63 return new ApplicationProject(projectFile); 64 } 65 else if (fileName.endsWith(DataMapFile.LOCATION_SUFFIX)) { 66 return new DataMapProject(projectFile); 67 } 68 else { 69 throw new ProjectException("Unsupported project file: " + projectFile); 70 } 71 } 72 73 76 protected Project() { 77 78 } 79 80 85 public Project(File projectFile) { 86 initialize(projectFile); 87 postInitialize(projectFile); 88 } 89 90 93 protected void initialize(File projectFile) { 94 if (projectFile != null) { 95 File parent = projectFile.getParentFile(); 96 if (parent == null) { 97 parent = new File (System.getProperty("user.dir")); 98 } 99 100 if (!parent.isDirectory()) { 101 throw new ProjectException( 102 "Project directory does not exist or is not a directory: " 103 + parent); 104 } 105 106 try { 107 projectDir = parent.getCanonicalFile(); 108 } 109 catch (IOException e) { 110 throw new ProjectException("Error creating project.", e); 111 } 112 } 113 } 114 115 119 protected void postInitialize(File projectFile) { 120 files = Collections.synchronizedList(buildFileList()); 122 upgradeMessages = Collections.synchronizedList(new ArrayList ()); 123 checkForUpgrades(); 124 } 125 126 130 public boolean isLocationUndefined() { 131 return getMainFile() == null; 132 } 133 134 141 public int getUpgradeStatus() { 142 return upgradeStatus; 143 } 144 145 148 public List getUpgradeMessages() { 149 return upgradeMessages; 150 } 151 152 156 public boolean hasRenamedFiles() { 157 if (files == null) { 158 return false; 159 } 160 161 synchronized (files) { 162 Iterator it = files.iterator(); 163 while (it.hasNext()) { 164 if (((ProjectFile) it.next()).isRenamed()) { 165 return true; 166 } 167 } 168 } 169 170 return false; 171 } 172 173 176 public List buildFileList() { 177 List projectFiles = new ArrayList (); 178 179 Iterator nodes = treeNodes(); 180 while (nodes.hasNext()) { 181 ProjectPath nodePath = (ProjectPath) nodes.next(); 182 Object obj = nodePath.getObject(); 183 ProjectFile f = projectFileForObject(obj); 184 185 if (f != null) { 186 projectFiles.add(f); 187 } 188 } 189 190 return projectFiles; 191 } 192 193 196 public Validator getValidator() { 197 return new Validator(this); 198 } 199 200 204 public ProjectFile findFile(Object obj) { 205 if (obj == null) { 206 return null; 207 } 208 209 synchronized (files) { 213 Iterator it = files.iterator(); 214 while (it.hasNext()) { 215 ProjectFile file = (ProjectFile) it.next(); 216 if (file.getObject() == obj) { 217 return file; 218 } 219 } 220 } 221 222 return null; 223 } 224 225 228 public File resolveFile(String symbolicName) { 229 try { 230 if (File.separatorChar != '/') { 232 symbolicName = symbolicName.replace('/', File.separatorChar); 233 } 234 return new File (projectDir, symbolicName).getCanonicalFile(); 235 } 236 catch (IOException e) { 237 return null; 239 } 240 } 241 242 247 public String resolveSymbolicName(File file) { 248 String symbolicName = null; 249 try { 250 String otherPath = file.getCanonicalFile().getPath(); 253 String thisPath = projectDir.getPath(); 254 255 if (otherPath.length() + 1 <= thisPath.length() 257 || !otherPath.startsWith(thisPath)) { 258 return null; 259 } 260 261 symbolicName = otherPath.substring(thisPath.length() + 1); 262 263 if ((symbolicName != null) && (File.separatorChar != '/')) { 265 symbolicName = symbolicName.replace(File.separatorChar, '/'); 266 } 267 268 return symbolicName; 269 270 } 271 catch (IOException e) { 272 return null; 274 } 275 } 276 277 280 public File getProjectDirectory() { 281 return projectDir; 282 } 283 284 public void setProjectDirectory(File dir) { 285 this.projectDir = dir; 286 } 287 288 291 public File getMainFile() { 292 if (projectDir == null) { 293 return null; 294 } 295 296 ProjectFile f = projectFileForObject(this); 297 return (f != null) ? resolveFile(f.getLocation()) : null; 298 } 299 300 303 public abstract ConfigStatus getLoadStatus(); 304 305 public abstract ProjectFile projectFileForObject(Object obj); 306 307 310 public abstract List getChildren(); 311 312 316 public abstract void checkForUpgrades(); 317 318 321 public Iterator treeNodes() { 322 return FlatProjectView.getInstance().flattenProjectTree(this).iterator(); 323 } 324 325 328 public abstract void upgrade() throws ProjectException; 329 330 334 public void save() throws ProjectException { 335 336 if (isLocationUndefined()) { 338 throw new ProjectException("Project location is undefined."); 339 } 340 341 List filesToSave = new ArrayList (); 343 List wrappedObjects = new ArrayList (); 344 prepareSave(filesToSave, wrappedObjects); 345 346 processSave(filesToSave); 348 349 List savedFiles = new ArrayList (); 351 Iterator saved = filesToSave.iterator(); 352 while (saved.hasNext()) { 353 ProjectFile f = (ProjectFile) saved.next(); 354 savedFiles.add(f.saveCommit()); 355 } 356 357 processDelete(wrappedObjects, savedFiles); 359 360 List freshList = buildFileList(); 362 Iterator it = freshList.iterator(); 363 while (it.hasNext()) { 364 ((ProjectFile) it.next()).synchronizeLocation(); 365 } 366 367 files = freshList; 368 369 synchronized (upgradeMessages) { 370 upgradeMessages.clear(); 371 } 372 373 setModified(false); 375 } 376 377 protected void prepareSave(List filesToSave, List wrappedObjects) 378 throws ProjectException { 379 Iterator nodes = treeNodes(); 380 while (nodes.hasNext()) { 381 ProjectPath nodePath = (ProjectPath) nodes.next(); 382 Object obj = nodePath.getObject(); 383 384 ProjectFile existingFile = findFile(obj); 385 386 if (existingFile == null) { 387 ProjectFile newFile = projectFileForObject(obj); 389 if (newFile != null) { 390 filesToSave.add(newFile); 391 } 392 } 393 else if (existingFile.canHandleObject()) { 394 wrappedObjects.add(existingFile.getObject()); 395 filesToSave.add(existingFile); 396 } 397 } 398 399 } 400 401 404 protected void processSave(List modifiedFiles) throws ProjectException { 405 Iterator willSave = modifiedFiles.iterator(); 407 while (willSave.hasNext()) { 408 ProjectFile f = (ProjectFile) willSave.next(); 409 f.willSave(); 410 } 411 412 try { 413 Iterator modified = modifiedFiles.iterator(); 414 while (modified.hasNext()) { 415 ProjectFile f = (ProjectFile) modified.next(); 416 f.saveTemp(); 417 } 418 } 419 catch (Exception ex) { 420 421 Iterator modified = modifiedFiles.iterator(); 423 while (modified.hasNext()) { 424 ProjectFile f = (ProjectFile) modified.next(); 425 f.saveUndo(); 426 } 427 428 throw new ProjectException("Project save failed and was canceled.", ex); 429 } 430 } 431 432 protected void processDelete(List existingObjects, List savedFiles) { 433 434 synchronized (files) { 436 Iterator oldFiles = files.iterator(); 437 while (oldFiles.hasNext()) { 438 ProjectFile f = (ProjectFile) oldFiles.next(); 439 File file = f.resolveOldFile(); 440 441 if (file == null || savedFiles.contains(file)) { 445 continue; 446 } 447 448 boolean delete = false; 449 if (f.isRenamed()) { 450 delete = true; 451 } 452 else if (f.getObject() == null) { 453 delete = true; 454 } 455 else if (!existingObjects.contains(f.getObject())) { 456 delete = true; 457 } 458 else if (!f.canHandleObject()) { 459 delete = true; 461 } 462 463 if (delete) { 464 deleteFile(file); 465 } 466 } 467 } 468 } 469 470 protected boolean deleteFile(File f) { 471 return (f.exists()) ? f.delete() : true; 472 } 473 474 477 public boolean isModified() { 478 return modified; 479 } 480 481 484 public void setModified(boolean modified) { 485 this.modified = modified; 486 } 487 } 488 | Popular Tags |