1 20 package org.openi.project; 21 22 import org.apache.log4j.*; 23 24 import org.openi.analysis.Analysis; 25 import org.openi.analysis.AnalysisGenerator; 26 import org.openi.analysis.ChangeLog; 27 import org.openi.analysis.Datasource; 28 import org.openi.analysis.LogEntry; 29 30 import org.openi.application.Application; 31 32 import org.openi.menu.*; 33 34 import org.openi.security.Permission; 35 36 import org.openi.util.NameValue; 37 import org.openi.util.Util; 38 39 import org.openi.xml.BeanStorage; 40 41 import java.io.File ; 42 import java.io.FileInputStream ; 43 import java.io.IOException ; 44 45 import java.util.AbstractList ; 46 import java.util.Date ; 47 import java.util.HashMap ; 48 import java.util.Iterator ; 49 import java.util.LinkedList ; 50 import java.util.List ; 51 import java.util.Map ; 52 import java.util.Properties ; 53 import java.util.zip.ZipEntry ; 54 import java.util.zip.ZipOutputStream ; 55 import java.io.FileOutputStream ; 56 import java.io.FileNotFoundException ; 57 import org.openi.stat.r.*; 58 59 import com.tonbeller.jpivot.olap.model.OlapException; 60 66 public class ProjectContext { 67 public static final String ALL_USERS = "public"; 68 private static Logger logger = LogManager.getLogger(ProjectContext.class); 69 70 73 private String baseDirectory; private String username; 75 private Project project; 76 77 82 public ProjectContext(Project project, String baseDirectory, 83 String username) { 84 this.baseDirectory = baseDirectory; 85 this.username = username; 86 this.project = project; 87 } 88 89 92 public String getBaseDirectory() { 93 return baseDirectory; 94 } 95 96 99 public void setBaseDirectory(String baseDirectory) { 100 this.baseDirectory = baseDirectory; 101 } 102 103 public String getProjectDirectory() { 104 return this.getBaseDirectory() + "/" + 105 this.getProject().getProjectId(); 106 } 107 108 111 public Project getProject() { 112 return project; 113 } 114 115 118 public void setProject(Project project) { 119 this.project = project; 120 } 121 122 125 public String getUsername() { 126 return username; 127 } 128 129 132 public void setUsername(String username) { 133 this.username = username; 134 } 135 136 141 public Object getDatasourceObject(String datasourceName) { 142 return project.getDataSourceMap().get(datasourceName); 143 } 144 145 150 public Datasource getDatasource(String datasourceName) { 151 return (Datasource) project.getDataSourceMap().get(datasourceName); 152 } 153 154 159 public void setDatasource(String datasourceKey, Object dataSource) { 160 synchronized (this) { 161 this.project.getDataSourceMap().put(datasourceKey, dataSource); 162 } 163 } 164 165 169 public Map getJdbcDatasourceMap() { 170 Map map = new HashMap (); 171 Iterator iter = project.getDataSourceMap().keySet().iterator(); 172 173 while (iter.hasNext()) { 174 String key = (String ) iter.next(); 175 Object obj = project.getDataSourceMap().get(key); 176 177 if ((obj != null) && obj instanceof JdbcDatasource) { 178 map.put(key, obj); 179 } 180 } 181 182 return map; 183 } 184 185 189 public Map getXmlaDatasourceMap() { 190 Map map = new HashMap (); 191 Iterator iter = project.getDataSourceMap().keySet().iterator(); 192 193 while (iter.hasNext()) { 194 String key = (String ) iter.next(); 195 Object obj = project.getDataSourceMap().get(key); 196 197 if ((obj != null) && obj instanceof Datasource) { 198 map.put(key, obj); 199 } 200 } 201 202 return map; 203 } 204 205 210 public Properties getJdbcDataSourceProperties(Analysis analysis) { 211 JdbcDatasource jdbcSource = getJdbcDatasource(analysis.getDrillthroughDatasource()); 212 if(jdbcSource == null) { 213 throw new NullPointerException ("There is no configuration for jdbc datasource in project"); 214 } 215 Properties properties = new Properties (); 216 217 properties.put("driver", jdbcSource.getDriverClassName()); 218 properties.put("url", jdbcSource.getUrl()); 219 properties.put("user", jdbcSource.getUsername()); 220 properties.put("password", jdbcSource.getPassword()); 221 222 return properties; 223 } 224 225 230 public Properties getJdbcDataSourceProperties(String dataSourceName) { 231 JdbcDatasource jdbcSource = getJdbcDatasource(dataSourceName); 232 if(jdbcSource == null) { 233 throw new NullPointerException ("There is no configuration for jdbc datasource in project"); 234 } 235 Properties properties = new Properties (); 236 237 properties.put("driver", jdbcSource.getDriverClassName()); 238 properties.put("url", jdbcSource.getUrl()); 239 properties.put("user", jdbcSource.getUsername()); 240 properties.put("password", jdbcSource.getPassword()); 241 242 return properties; 243 } 244 249 public JdbcDatasource getJdbcDatasource(String dataSourceName) { 250 251 if (dataSourceName != null && !"".equals(dataSourceName)) { 252 Object datasource = getDatasourceObject(dataSourceName); 253 if(datasource instanceof JdbcDatasource) 254 return (JdbcDatasource)datasource; 255 else 256 throw new ClassCastException ("Not a valid jdbc datasource name"); 257 258 } else { 259 Map dsMap = getJdbcDatasourceMap(); 260 if (dsMap != null && dsMap.size() > 0) 261 return (JdbcDatasource) dsMap.values().iterator().next(); 262 } 263 return null; 264 265 } 266 267 272 public void deleteDatasource(String datasourceName) { 273 try { 274 this.project.getDataSourceMap().remove(datasourceName); 275 this.saveProject(); 276 } catch (Exception e) { 277 } 278 } 279 280 285 public JdbcDatasource getJasperDatasource(String template) { 286 if (project.getJdbcMap() == null) { 287 return null; 288 } 289 290 Iterator iter = project.getJdbcMap().keySet().iterator(); 291 292 while (iter.hasNext()) { 293 String key = (String ) iter.next(); 294 295 if (key.equalsIgnoreCase(template)) { 296 String datasource = (String ) project.getJdbcMap().get(key); 297 298 if ((datasource != null) && !datasource.equals("")) { 299 Object obj = getDatasourceObject(datasource); 300 301 if ((obj != null) && obj instanceof JdbcDatasource) { 302 return (JdbcDatasource) obj; 303 } 304 } 305 } 306 } 307 308 return null; 309 } 310 311 320 public Menu buildMenu() throws IOException { 321 List modules = getProjectModules(false, true); 322 323 List tmp = new LinkedList (modules); 326 tmp.add("/" + username.toLowerCase()); 327 328 MenuBuilder builder = new MenuBuilder(); 329 Menu menu = builder.build(this.getProjectDirectory(), tmp); 330 331 menu.addSubMenu(createAdminMenu()); 332 333 return menu; 334 } 335 336 342 private Menu createAdminMenu() { 343 logger.debug("creating admin menu"); 344 345 Menu adminMenu = new Menu("Administration"); 347 Map config = this.getProject().getMenuConfig(); 348 349 if (Util.isItemInList(this.getUsername(), 354 Application.getInstance().getApplicationAdmins())) { 355 this.addItemList(adminMenu, (List ) config.get("appAdminList")); 356 this.addItemList(adminMenu, (List ) config.get("projectAdminList")); 357 this.addItemList(adminMenu, (List ) config.get("projectUserList")); 358 } 359 360 if (Util.isItemInList(this.getUsername(), 361 this.getProject().getProjectAdmins())) { 362 this.addItemList(adminMenu, (List ) config.get("projectAdminList")); 363 this.addItemList(adminMenu, (List ) config.get("projectUserList")); 364 } 365 366 if (Util.isItemInList(this.getUsername(), 367 this.getProject().getProjectUsers())) { 368 this.addItemList(adminMenu, (List ) config.get("projectUserList")); 369 } 370 371 return adminMenu; 372 } 373 374 private void addItemList(Menu menu, List list) { 375 Iterator items = list.iterator(); 376 377 while (items.hasNext()) { 378 MenuItem item = (MenuItem) items.next(); 379 menu.addMenuItem(item); 380 } 381 382 } 384 385 public void savePublic(String relativeUrl, Analysis analysis, 386 String comment) throws IOException { 387 logger.debug("trying to save public analysis for: " + 388 this.getProject().getProjectId()); 389 390 String filename = ALL_USERS + "/" + relativeUrl; 391 save(filename, analysis, comment); 392 } 393 394 public void savePersonal(String relativeUrl, Analysis analysis, 395 String comment) throws IOException { 396 logger.debug("trying to save personal analysis for user: " + 397 this.getUsername().toLowerCase()); 398 399 String relativeFilename = this.getUsername().toLowerCase() + "/" + 400 relativeUrl; 401 save(relativeFilename, analysis, comment); 402 } 403 404 public void save(String relativeFilename, Analysis analysis, String comment) throws 405 IOException { 406 String filename = this.getProjectDirectory() + "/" + relativeFilename; 407 logger.info("saving: " + filename); 408 409 BeanStorage storage = new BeanStorage(); 410 storage.saveBeanToFile(filename, analysis); 411 412 ChangeLog changelog = this.getChangeLog(); 413 changelog.addLogEntry(new LogEntry(relativeFilename, new Date (), 414 this.getUsername(), comment)); 415 storage.saveBeanToFile(this.getChangeLogFilename(), changelog); 416 } 417 418 421 public void deleteAnalysis(String relativeUrl) { 422 String filename = this.getProjectDirectory() + "/" + relativeUrl; 425 logger.debug("trying to delete analysis using filename: " + filename); 426 427 BeanStorage storage = new BeanStorage(); 428 storage.deleteFile(filename); 429 } 430 431 public Analysis restoreAnalysis(String analysisConfigName) throws 432 IOException { 433 String filename = this.getProjectDirectory() + "/" + 435 analysisConfigName; 436 logger.debug("trying to restore analysis using filename: " + filename); 437 438 BeanStorage storage = new BeanStorage(); 439 440 Analysis analysis = (Analysis) storage.restoreBeanFromFile(filename, 442 new Analysis()); 443 analysis.setAnalysisTitle(MenuBuilder.constructDisplayName( 444 new File (filename))); 445 446 return analysis; 447 } 448 449 453 public void saveProject() { 454 String filename = this.getProjectDirectory() + "/project.xml"; 455 logger.info("saving: " + filename); 456 457 BeanStorage storage = new BeanStorage(); 458 459 try { 460 storage.saveBeanToFile(filename, this.project); 461 } catch (IOException e) { 462 logger.error(e); 463 } 464 } 465 466 471 public ChangeLog getChangeLog() { 472 ChangeLog changelog = null; 473 String filename = this.getChangeLogFilename(); 474 logger.debug("trying to restore changelog using filename: " + filename); 475 476 BeanStorage storage = new BeanStorage(); 477 478 try { 479 changelog = (ChangeLog) storage.restoreBeanFromFile(filename); 480 } catch (IOException e) { 481 logger.info(e); 482 changelog = new ChangeLog(); 483 } 484 485 return changelog; 486 } 487 488 private String getChangeLogFilename() { 489 return this.getProjectDirectory() + "/changelog.xml"; 490 } 491 492 498 public boolean hasPermission(Permission permission) { 499 boolean granted = false; 500 501 if (Util.isItemInList(username, 503 Application.getInstance().getApplicationAdmins())) { 504 if (Util.isItemInList(permission.toString(), 506 Application.getInstance() 507 .getApplicationAdminPermissions())) { 508 granted = true; 509 } 510 } 511 else if (Util.isItemInList(username, project.getProjectAdmins())) { 513 if (Util.isItemInList(permission.toString(), 515 Application.getInstance(). 516 getProjectAdminPermissions())) { 517 granted = true; 518 } 519 } 520 else if (Util.isItemInList(username, project.getProjectUsers())) { 522 if (Util.isItemInList(permission.toString(), 524 Application.getInstance(). 525 getProjectUserPermissions())) { 526 granted = true; 527 } 528 } 529 else if (Util.isItemInList(username, project.getProjectReadOnlyUsers())) { 531 532 if(permission == Permission.READ_ONLY) { 534 granted = true; 535 } 536 else if (Util.isItemInList(permission.toString(), 537 Application.getInstance(). 538 getProjectUserPermissions())) { 539 granted = true; 540 } 541 542 } 543 544 return granted; 545 } 546 547 552 public synchronized void createDirectory(String relativeDirectoryName) { 553 File newDir = new File (this.getProjectDirectory() + "/" + 554 relativeDirectoryName); 555 556 if (!newDir.exists()) { 557 try { 558 logger.info("creating new subdirectory: " + 559 newDir.getCanonicalPath()); 560 } catch (IOException e) { 561 logger.error(e); 562 } 563 564 boolean result = newDir.mkdir(); 565 logger.debug("directory create result: " + result); 566 } 567 } 568 569 573 public List getProjectModules(boolean includePrivate, boolean includePublic) { 574 List modules = new LinkedList (); 575 Iterator iterator = this.project.getModules().iterator(); 576 577 while (iterator.hasNext()) { 578 Module module = (Module) iterator.next(); 579 String folderName = module.getFolderName().toLowerCase(); 580 581 if (!includePublic && 582 (folderName.startsWith("public") || 583 folderName.startsWith("/public"))) { 584 continue; 585 } 586 587 if (isModuleAllowed(module)) { 588 modules.add(module.getFolderName()); 589 } 590 } 591 592 if (includePrivate) { 593 modules.add(this.username); 594 } 595 596 return modules; 597 } 598 599 604 public boolean isPathAllowed(String path) { 605 path = extractModulePath(path); 606 607 Iterator iterator = project.getModules().iterator(); 609 610 while (iterator.hasNext()) { 613 Module module = (Module) iterator.next(); 614 615 if (path.startsWith(module.getFolderName())) { 616 if (!isModuleAllowed(module)) { 618 return false; 619 } 620 } 621 } 622 623 return true; 624 } 625 626 633 public boolean isPathAllowed(String path, Permission permission) { 634 if (!isPathAllowed(path)) { 636 return false; 637 } 638 639 path = extractModulePath(path); 640 641 if (path.toLowerCase().startsWith("public")) { 644 if (permission.equals(Permission.DELETE_PUBLIC) || 645 permission.equals(Permission.SAVE_PUBLIC)) { 646 if (!hasPermission(permission)) { 647 return false; 648 } 649 } 650 } 651 652 if (path.startsWith(getUsername())) { 654 if (permission.equals(Permission.DELETE_PRIVATE) || 655 permission.equals(Permission.SAVE_PRIVATE)) { 656 if (!hasPermission(permission)) { 657 return false; 658 } 659 } 660 } 661 662 return true; 663 } 664 665 670 public String extractModulePath(String path) { 671 if (path.toLowerCase().startsWith(getProjectDirectory().toLowerCase())) { 672 path = path.substring(getProjectDirectory().length()); 673 } 674 675 return path; 676 } 677 678 private boolean isModuleAllowed(Module module) { 679 String users = module.getAllowedUsers(); 680 681 if ((users == null) || users.trim().equals("")) { 683 return true; 684 } 685 686 if (module != null) { 687 String [] allowedUsers; 688 allowedUsers = users.trim().split(","); 689 690 for (int i = 0; i < allowedUsers.length; i++) { 691 String user = allowedUsers[i].trim(); 692 693 if ((user != null) && !user.equals("") && 694 user.equals(this.username)) { 695 return true; 696 } 697 } 698 } 699 700 return false; 701 } 702 703 710 public boolean addSubFolder(String base, String folderName) throws 711 Exception { 712 String path = constructPathWithProjectDir(base); 713 File file = new File (path); 714 715 if (!isPathBeneathProjectDir(path)) { 716 throw new SecurityException ( 717 "Folder creation is not allowed outside project directory. Base path is:" + 718 file.getCanonicalPath()); 719 } 720 721 if (!file.exists()) { 722 throw new java.io.FileNotFoundException ("Specified path '" + path + 723 "' does not exists"); 724 } 725 726 if (!file.isDirectory()) { 727 throw new java.io.IOException ("Specified path'" + path + 728 "' is not a directory"); 729 } 730 731 String newfilepath = file.getPath() + "/" + folderName; 732 newfilepath = new File (newfilepath).getCanonicalPath(); 733 734 File newfile = new File (newfilepath); 735 736 if (newfile.exists()) { 737 throw new java.io.IOException ("Specified path '" + newfilepath + 738 "' already exists"); 739 } 740 741 return newfile.mkdir(); 742 } 743 744 749 public boolean isPathBeneathProjectDir(String path) throws Exception { 750 File file = new File (path); 751 String fullpath = file.getCanonicalPath(); 752 File prjdir = new File (getProjectDirectory()); 753 754 return fullpath.startsWith(prjdir.getCanonicalPath()); 755 } 756 757 765 public boolean renameFileFolder(String existing, String newname) throws 766 Exception { 767 String path = constructPathWithProjectDir(existing); 768 File file = new File (path); 769 770 if (!isPathBeneathProjectDir(path)) { 771 throw new SecurityException ( 772 "Rename is not allowed outside project directory"); 773 } 774 775 if (!file.exists()) { 776 throw new java.io.FileNotFoundException ("Specified path '" + path + 777 "' does not exists"); 778 } 779 780 String newpath = file.getParentFile().getPath() + "/" + newname; 781 File newfile = new File (newpath); 782 783 if (newfile.exists()) { 784 throw new java.io.IOException ("Specified path '" + newpath + 785 "' already exists"); 786 } 787 788 return file.renameTo(newfile); 789 } 790 791 797 public boolean removeFileFolder(String pathname) throws Exception { 798 String path = constructPathWithProjectDir(pathname); 799 File file = new File (path); 800 801 if (!file.exists()) { 802 throw new java.io.FileNotFoundException ("Specified path '" + path + 803 "' does not exists"); 804 } 805 806 if (!isPathBeneathProjectDir(path)) { 807 throw new SecurityException ( 808 "Delete is not allowed outside project directory"); 809 } 810 811 return deleteDir(file); 812 } 813 814 private String constructPathWithProjectDir(String path) { 815 String actualpath = ""; 816 817 if (path.startsWith("/") || path.startsWith("\\")) { 818 actualpath = getProjectDirectory() + path; 819 } else { 820 actualpath = path; 821 } 822 823 return actualpath; 824 } 825 826 private boolean deleteDir(File dir) { 827 if (dir.isDirectory()) { 828 String [] children = dir.list(); 829 830 for (int i = 0; i < children.length; i++) { 831 boolean success = deleteDir(new File (dir, children[i])); 832 833 if (!success) { 834 return false; 835 } 836 } 837 } 838 839 return dir.delete(); 840 } 841 842 847 public String resolvePathWithProjectDir(String path) { 848 if (!(path.startsWith("\\") || path.startsWith("/"))) { 849 path = "/" + path; 850 } 851 852 return getProjectDirectory() + path; 853 } 854 855 859 public List getProjectSubDirs() { 860 return DirectoryLister.buildProjectRootSubDirList(getProjectDirectory()); 861 } 862 863 868 public List getFilesByExtension(String extension) { 869 return DirectoryLister.buildFileListByExtension(getProjectDirectory(), 870 getProjectModules(true, true), extension); 871 } 872 873 880 public void zipProjectContents(ZipOutputStream zos) throws IOException { 881 logger.debug("zipping project directory: " + this.getProjectDirectory()); 882 if (this.hasPermission(Permission.APP_ADMINISTRATION)) { 883 zipDir(this.getBaseDirectory(), this.getProjectDirectory(), zos); 884 } else { 885 throw new SecurityException ("user does not have this permission"); 886 } 887 } 888 889 898 private void zipDir(String baseDir, String dir2zip, ZipOutputStream zos) throws 899 IOException { 900 902 File zipDir = new File (dir2zip); 904 905 String [] dirList = zipDir.list(); 907 908 909 for (int i = 0; i < dirList.length; i++) { 911 File f = new File (zipDir, dirList[i]); 912 913 if (f.isDirectory()) { 914 String filePath = f.getPath(); 917 zipDir(baseDir, filePath, zos); 918 } else { 919 FileInputStream fis = new FileInputStream (f); 922 923 String basePath = new File (baseDir).getCanonicalPath(); 925 String entryName = f.getCanonicalPath(); 926 927 if(entryName.length() > basePath.length()) 928 entryName = entryName.substring(basePath.length()+1); 929 930 ZipEntry anEntry = new ZipEntry (entryName); 932 zos.putNextEntry(anEntry); 934 935 byte[] readBuffer = new byte[512]; 936 int bytesIn = 0; 937 while ((bytesIn = fis.read(readBuffer)) != -1) { 939 zos.write(readBuffer, 0, bytesIn); 940 } 941 942 fis.close(); 944 } 945 } 946 } 947 948 954 public void saveTextFileContent(String file, String content) throws 955 Exception { 956 logger.info("saving text content to file :" + file); 957 File fileToSave = new File (resolvePathWithProjectDir(file)); 958 if (!fileToSave.exists()) 959 throw new java.io.FileNotFoundException ("Specified path '" + file + 960 "' does not exists"); 961 if (!fileToSave.isFile()) 962 throw new java.io.FileNotFoundException ("Specified path '" + file + 963 "' is not a file"); 964 965 if (!isPathBeneathProjectDir(fileToSave.getCanonicalPath())) { 966 throw new SecurityException ( 967 "save is not allowed outside project directory"); 968 } 969 970 if (!isPathAllowed(file)) { 971 throw new SecurityException ("user does not have this permission"); 972 } 973 FileOutputStream out = new FileOutputStream (fileToSave); 974 out.write(content.getBytes()); 975 out.close(); 976 } 977 978 984 public RFunctionList getRFunctionList() throws Exception { 985 String xmlFile = this.getProjectDirectory() + "/" + "rfunction.xml"; 986 RFunctionList rFunctionList; 987 if(!new File (xmlFile).exists()) { 988 logger.error("R Function file 'rfunction.xml' in project dir is not defined"); 989 rFunctionList = new RFunctionList(); 990 } else { 991 BeanStorage bean = new BeanStorage(); 992 rFunctionList = (RFunctionList) bean.restoreBeanFromFile(xmlFile); 993 } 994 return rFunctionList; 995 } 996 997 1002 public void saveRFunctionListBean(RFunctionList object) throws Exception { 1003 BeanStorage bean = new BeanStorage(); 1004 String xmlFile = this.getProjectDirectory() + "/" + "rfunction.xml"; 1005 bean.saveBeanToFile(xmlFile, object); 1006 } 1007 1008 1014 public void autogenerate(String datasourceName, String cube, String relativeDir) throws OlapException, IOException { 1015 1016 this.createDirectory(relativeDir); 1017 AnalysisGenerator gen = new AnalysisGenerator(); 1018 Datasource ds = this.getDatasource(datasourceName); 1019 Map mdx = gen.generateMdxForDimensions(ds.getServer(), ds.getCatalog(), cube); 1020 Iterator keys = mdx.keySet().iterator(); 1021 while(keys.hasNext()){ 1022 String key = (String )keys.next(); 1023 Analysis analysis = new Analysis(); 1024 analysis.setAnalysisTitle(key); 1025 analysis.setChartType(1); 1026 analysis.setMdxQuery( (String )mdx.get(key) ); 1027 analysis.setDescription("automatically generated on: " + new java.util.Date ()); 1028 analysis.setDataSourceName(datasourceName); 1029 String filename = relativeDir + "/" + key + ".analysis"; 1031 savePublic(filename.replaceAll(" ", "_"), analysis, null); 1032 } 1033 } 1034 1035 1039 public List getAutoGeneratedMenuNames(){ 1040 List displayNames = new LinkedList (); 1041 try { 1042 Menu subMenu = this.buildMenu().getSubMenu("Auto Generated"); 1043 if(subMenu !=null){ 1044 displayNames = subMenu.getMenuDisplayNames(); 1045 } 1046 1047 } catch (IOException e) { 1048 logger.error(e); 1049 } 1050 return displayNames; 1051 } 1052} 1053 | Popular Tags |