001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2010-2013 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.server; 011 012import mondrian.olap.MondrianServer; 013import mondrian.olap.Util; 014import mondrian.spi.CatalogLocator; 015import mondrian.spi.impl.IdentityCatalogLocator; 016import mondrian.util.LockBox; 017 018import java.io.*; 019import java.net.URL; 020import java.util.*; 021 022/** 023 * Registry of all servers within this JVM, and also serves as a factory for 024 * servers. 025 * 026 * <p>This class is not a public API. User applications should use the 027 * methods in {@link mondrian.olap.MondrianServer}. 028 * 029 * @author jhyde 030 */ 031public class MondrianServerRegistry { 032 public static final MondrianServerRegistry INSTANCE = 033 new MondrianServerRegistry(); 034 035 public MondrianServerRegistry() { 036 super(); 037 } 038 039 /** 040 * Registry of all servers. 041 */ 042 final LockBox lockBox = new LockBox(); 043 044 /** 045 * The one and only one server that does not have a repository. 046 */ 047 final MondrianServer staticServer = 048 createWithRepository(null, null); 049 050 private MondrianServer.MondrianVersion version = null; 051 052 /** 053 * Looks up a server with a given id. If the id is null, returns the 054 * static server. 055 * 056 * @param instanceId Unique identifier of server instance 057 * @return Server 058 * @throws RuntimeException if no server instance exists 059 */ 060 public MondrianServer serverForId(String instanceId) { 061 if (instanceId != null) { 062 final LockBox.Entry entry = lockBox.get(instanceId); 063 if (entry == null) { 064 throw Util.newError( 065 "No server instance has id '" + instanceId + "'"); 066 } 067 return (MondrianServer) entry.getValue(); 068 } else { 069 return staticServer; 070 } 071 } 072 073 public synchronized MondrianServer.MondrianVersion getOrLoadVersion() { 074 if (version == null) { 075 final String[] vendorTitleVersion = loadVersionFile(); 076 String vendor = vendorTitleVersion[0]; 077 final String title = vendorTitleVersion[1]; 078 final String versionString = vendorTitleVersion[2]; 079 if (false) { 080 System.out.println( 081 "vendor=" + vendor 082 + ", title=" + title 083 + ", versionString=" + versionString); 084 } 085 int dot1 = versionString.indexOf('.'); 086 final int majorVersion = 087 dot1 < 0 088 ? 1 089 : Integer.valueOf(versionString.substring(0, dot1)); 090 int dot2 = versionString.indexOf('.', dot1 + 1); 091 final int minorVersion = 092 dot2 < 0 093 ? 0 094 : Integer.valueOf(versionString.substring(dot1 + 1, dot2)); 095 version = new MondrianServer.MondrianVersion() { 096 public String getVersionString() { 097 return versionString; 098 } 099 100 public int getMajorVersion() { 101 return majorVersion; 102 } 103 104 public int getMinorVersion() { 105 return minorVersion; 106 } 107 108 public String getProductName() { 109 return title; 110 } 111 }; 112 } 113 return version; 114 } 115 116 private static String[] loadVersionFile() { 117 // First, try to read the version info from the package. If the classes 118 // came from a jar, this info will be set from manifest.mf. 119 Package pakkage = MondrianServerImpl.class.getPackage(); 120 String implementationVersion = pakkage.getImplementationVersion(); 121 122 // Second, try to read VERSION.txt. 123 String version = "Unknown Version"; 124 String title = "Unknown Database"; 125 String vendor = "Unknown Vendor"; 126 URL resource = 127 Util.getClosestResource( 128 MondrianServerImpl.class.getClassLoader(), 129 "DefaultRules.xml"); 130 if (resource != null) { 131 try { 132 String path = resource.getPath(); 133 String path2 = 134 Util.replace( 135 path, "DefaultRules.xml", "VERSION.txt"); 136 URL resource2 = 137 new URL( 138 resource.getProtocol(), 139 resource.getHost(), 140 path2); 141 142 // Parse VERSION.txt. E.g. 143 // Title: mondrian 144 // Version: 3.4.9 145 // becomes {("Title", "mondrian"), ("Version", "3.4.9")} 146 final Map<String, String> map = new HashMap<String, String>(); 147 final LineNumberReader r = 148 new LineNumberReader( 149 new InputStreamReader(resource2.openStream())); 150 try { 151 String line; 152 while ((line = r.readLine()) != null) { 153 int i = line.indexOf(": "); 154 if (i >= 0) { 155 String key = line.substring(0, i); 156 String value = line.substring(i + ": ".length()); 157 map.put(key, value); 158 } 159 } 160 } finally { 161 r.close(); 162 } 163 164 title = map.get("Title"); 165 version = map.get("Version"); 166 try { 167 Integer.parseInt(version); 168 } catch (NumberFormatException e) { 169 // Version is not a number (e.g. "TRUNK-SNAPSHOT"). 170 // Fall back on VersionMajor, VersionMinor, if present. 171 String versionMajor = map.get("VersionMajor"); 172 String versionMinor = map.get("VersionMinor"); 173 if (versionMajor != null) { 174 version = versionMajor; 175 } 176 if (versionMinor != null) { 177 version += "." + versionMinor; 178 } 179 } 180 vendor = map.get("Vendor"); 181 } catch (IOException e) { 182 // ignore exception - it's OK if file is not found 183 Util.discard(e); 184 } 185 } 186 187 // Version from jar manifest overrides that from VERSION.txt. 188 // But ignore versions like 'TRUNK-SNAPSHOT'. 189 if (implementationVersion != null 190 && !implementationVersion.endsWith("-SNAPSHOT")) 191 { 192 version = implementationVersion; 193 } 194 return new String[] {vendor, title, version}; 195 } 196 197 public MondrianServer createWithRepository( 198 RepositoryContentFinder contentFinder, 199 CatalogLocator catalogLocator) 200 { 201 if (catalogLocator == null) { 202 catalogLocator = new IdentityCatalogLocator(); 203 } 204 final Repository repository; 205 if (contentFinder == null) { 206 // NOTE: registry.staticServer is initialized by calling this 207 // method; this is the only time that it is null. 208 if (staticServer != null) { 209 return staticServer; 210 } 211 repository = new ImplicitRepository(); 212 } else { 213 repository = new FileRepository(contentFinder, catalogLocator); 214 } 215 return new MondrianServerImpl(this, repository, catalogLocator); 216 } 217} 218 219// End MondrianServerRegistry.java