1 56 package org.objectstyle.cayenne.project; 57 58 import java.io.File ; 59 import java.io.IOException ; 60 import java.util.ArrayList ; 61 import java.util.Collections ; 62 import java.util.Iterator ; 63 import java.util.List ; 64 65 import org.apache.log4j.Logger; 66 import org.objectstyle.cayenne.conf.ConfigStatus; 67 import org.objectstyle.cayenne.conf.Configuration; 68 import org.objectstyle.cayenne.project.validator.Validator; 69 70 81 public abstract class Project { 82 private static final Logger logObj = Logger.getLogger(Project.class); 83 84 public static final String CURRENT_PROJECT_VERSION = "1.1"; 85 86 protected File projectDir; 87 protected List files = new ArrayList (); 88 protected List upgradeMessages; 89 protected boolean modified; 90 91 94 public static Project createProject(File projectFile) { 95 logObj.debug("createProject: " + projectFile); 96 String fileName = projectFile.getName(); 97 98 if (fileName.endsWith(Configuration.DEFAULT_DOMAIN_FILE)) { 99 return new ApplicationProject(projectFile); 100 } else if (fileName.endsWith(DataMapFile.LOCATION_SUFFIX)) { 101 return new DataMapProject(projectFile); 102 } else { 103 throw new ProjectException( 104 "Unsupported project file: " + projectFile); 105 } 106 } 107 108 113 public Project(File projectFile) { 114 115 if (projectFile != null) { 116 File parent = projectFile.getParentFile(); 117 if (parent == null) { 118 parent = new File (System.getProperty("user.dir")); 119 } 120 121 if (!parent.isDirectory()) { 122 throw new ProjectException( 123 "Project directory does not exist or is not a directory: " 124 + parent); 125 } 126 127 try { 128 projectDir = parent.getCanonicalFile(); 129 } catch (IOException e) { 130 throw new ProjectException("Error creating project.", e); 131 } 132 } 133 134 postInitialize(projectFile); 135 } 136 137 142 protected void postInitialize(File projectFile) { 143 logObj.debug("postInitialize with: " + projectFile); 144 files = Collections.synchronizedList(buildFileList()); 146 upgradeMessages = Collections.synchronizedList(new ArrayList ()); 147 checkForUpgrades(); 148 } 149 150 154 public boolean isLocationUndefined() { 155 return getMainFile() == null; 156 } 157 158 161 public boolean isUpgradeNeeded() { 162 return upgradeMessages.size() > 0; 163 } 164 165 168 public List getUpgradeMessages() { 169 return upgradeMessages; 170 } 171 172 177 public boolean hasRenamedFiles() { 178 if (files == null) { 179 return false; 180 } 181 182 synchronized (files) { 183 Iterator it = files.iterator(); 184 while (it.hasNext()) { 185 if (((ProjectFile) it.next()).isRenamed()) { 186 return true; 187 } 188 } 189 } 190 191 return false; 192 } 193 194 197 public List buildFileList() { 198 List projectFiles = new ArrayList (); 199 200 Iterator nodes = treeNodes(); 201 while (nodes.hasNext()) { 202 ProjectPath nodePath = (ProjectPath) nodes.next(); 203 Object obj = nodePath.getObject(); 204 ProjectFile f = projectFileForObject(obj); 205 206 if (f != null) { 207 projectFiles.add(f); 208 } 209 } 210 211 return projectFiles; 212 } 213 214 217 public Validator getValidator() { 218 return new Validator(this); 219 } 220 221 225 public ProjectFile findFile(Object obj) { 226 if (obj == null) { 227 return null; 228 } 229 230 synchronized (files) { 234 Iterator it = files.iterator(); 235 while (it.hasNext()) { 236 ProjectFile file = (ProjectFile) it.next(); 237 if (file.getObject() == obj) { 238 return file; 239 } 240 } 241 } 242 243 return null; 244 } 245 246 249 public File resolveFile(String symbolicName) { 250 try { 251 if (File.separatorChar != '/') { 253 symbolicName = symbolicName.replace('/', File.separatorChar); 254 } 255 return new File (projectDir, symbolicName).getCanonicalFile(); 256 } catch (IOException e) { 257 logObj.info("Can't convert to canonical form.", e); 259 return null; 260 } 261 } 262 263 269 public String resolveSymbolicName(File file) { 270 String symbolicName = null; 271 try { 272 String otherPath = file.getCanonicalFile().getPath(); 275 String thisPath = projectDir.getPath(); 276 277 if (otherPath.length() + 1 <= thisPath.length() 279 || !otherPath.startsWith(thisPath)) { 280 return null; 281 } 282 283 symbolicName = otherPath.substring(thisPath.length() + 1); 284 285 if ((symbolicName != null) && (File.separatorChar != '/')) { 287 symbolicName = symbolicName.replace(File.separatorChar, '/'); 288 } 289 290 return symbolicName; 291 292 } catch (IOException e) { 293 logObj.info("Can't convert to canonical form.", e); 295 return null; 296 } 297 } 298 299 303 public File getProjectDirectory() { 304 return projectDir; 305 } 306 307 public void setProjectDirectory(File dir) { 308 this.projectDir = dir; 309 } 310 311 314 public File getMainFile() { 315 if (projectDir == null) { 316 return null; 317 } 318 319 ProjectFile f = projectFileForObject(this); 320 return (f != null) ? resolveFile(f.getLocation()) : null; 321 } 322 323 326 public abstract ConfigStatus getLoadStatus(); 327 328 public abstract ProjectFile projectFileForObject(Object obj); 329 330 333 public abstract List getChildren(); 334 335 340 public abstract void checkForUpgrades(); 341 342 345 public Iterator treeNodes() { 346 return FlatProjectView 347 .getInstance() 348 .flattenProjectTree(this) 349 .iterator(); 350 } 351 352 355 public abstract void upgrade() throws ProjectException; 356 357 362 public void save() throws ProjectException { 363 364 if (isLocationUndefined()) { 366 throw new ProjectException("Project location is undefined."); 367 } 368 369 List filesToSave = new ArrayList (); 371 List wrappedObjects = new ArrayList (); 372 prepareSave(filesToSave, wrappedObjects); 373 374 processSave(filesToSave); 376 377 List savedFiles = new ArrayList (); 379 Iterator saved = filesToSave.iterator(); 380 while (saved.hasNext()) { 381 ProjectFile f = (ProjectFile) saved.next(); 382 savedFiles.add(f.saveCommit()); 383 } 384 385 processDelete(wrappedObjects, savedFiles); 387 388 List freshList = buildFileList(); 390 Iterator it = freshList.iterator(); 391 while (it.hasNext()) { 392 ((ProjectFile) it.next()).synchronizeLocation(); 393 } 394 395 files = freshList; 396 397 synchronized (upgradeMessages) { 398 upgradeMessages.clear(); 399 } 400 401 setModified(false); 403 } 404 405 protected void prepareSave(List filesToSave, List wrappedObjects) 406 throws ProjectException { 407 Iterator nodes = treeNodes(); 408 while (nodes.hasNext()) { 409 ProjectPath nodePath = (ProjectPath) nodes.next(); 410 Object obj = nodePath.getObject(); 411 412 ProjectFile existingFile = findFile(obj); 413 414 if (existingFile == null) { 415 ProjectFile newFile = projectFileForObject(obj); 417 if (newFile != null) { 418 filesToSave.add(newFile); 419 } 420 } else if (existingFile.canHandleObject()) { 421 wrappedObjects.add(existingFile.getObject()); 422 filesToSave.add(existingFile); 423 } 424 } 425 426 } 427 428 431 protected void processSave(List modifiedFiles) throws ProjectException { 432 Iterator willSave = modifiedFiles.iterator(); 434 while (willSave.hasNext()) { 435 ProjectFile f = (ProjectFile) willSave.next(); 436 f.willSave(); 437 } 438 439 try { 440 Iterator modified = modifiedFiles.iterator(); 441 while (modified.hasNext()) { 442 ProjectFile f = (ProjectFile) modified.next(); 443 444 if (logObj.isDebugEnabled()) { 445 logObj.info("Saving file " + f.resolveFile()); 446 } 447 448 f.saveTemp(); 449 } 450 } catch (Exception ex) { 451 logObj.info("*** Project save failed, reverting.", ex); 452 453 Iterator modified = modifiedFiles.iterator(); 455 while (modified.hasNext()) { 456 ProjectFile f = (ProjectFile) modified.next(); 457 f.saveUndo(); 458 } 459 460 throw new ProjectException( 461 "Project save failed and was canceled.", 462 ex); 463 } 464 } 465 466 protected void processDelete(List existingObjects, List savedFiles) { 467 468 synchronized (files) { 470 Iterator oldFiles = files.iterator(); 471 while (oldFiles.hasNext()) { 472 ProjectFile f = (ProjectFile) oldFiles.next(); 473 File file = f.resolveOldFile(); 474 475 if (file == null || savedFiles.contains(file)) { 479 continue; 480 } 481 482 boolean delete = false; 483 if (f.isRenamed()) { 484 delete = true; 485 logObj.info("File renamed, deleting old version: " + file); 486 } else if (f.getObject() == null) { 487 delete = true; 488 logObj.info("Null internal object, deleting file: " + file); 489 } else if (!existingObjects.contains(f.getObject())) { 490 delete = true; 491 logObj.info( 492 "Object deleted from the project, deleting file: " 493 + file); 494 } else if (!f.canHandleObject()) { 495 delete = true; 497 logObj.info( 498 "Can no longer handle the object, deleting file: " 499 + file); 500 } 501 502 if (delete) { 503 if (!deleteFile(file)) { 504 logObj.info("*** Failed to delete file, ignoring."); 505 } 506 } 507 } 508 } 509 } 510 511 protected boolean deleteFile(File f) { 512 return (f.exists()) ? f.delete() : true; 513 } 514 515 518 public boolean isModified() { 519 return modified; 520 } 521 522 525 public void setModified(boolean modified) { 526 this.modified = modified; 527 } 528 } 529 | Popular Tags |