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) 2011-2012 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.xmla.impl; 011 012import mondrian.olap.MondrianServer; 013import mondrian.olap.Util; 014import mondrian.server.RepositoryContentFinder; 015import mondrian.server.UrlRepositoryContentFinder; 016import mondrian.spi.CatalogLocator; 017import mondrian.spi.impl.ServletContextCatalogLocator; 018import mondrian.xmla.XmlaHandler; 019 020import java.io.File; 021import java.net.MalformedURLException; 022import java.net.URL; 023import javax.servlet.*; 024 025/** 026 * Extension to {@link mondrian.xmla.XmlaServlet} that instantiates a 027 * Mondrian engine. 028 * 029 * @author jhyde 030 */ 031public class MondrianXmlaServlet extends DefaultXmlaServlet { 032 public static final String DEFAULT_DATASOURCE_FILE = "datasources.xml"; 033 034 protected MondrianServer server; 035 036 @Override 037 protected XmlaHandler.ConnectionFactory createConnectionFactory( 038 ServletConfig servletConfig) 039 throws ServletException 040 { 041 if (server == null) { 042 // A derived class can alter how the calalog locator object is 043 // created. 044 CatalogLocator catalogLocator = makeCatalogLocator(servletConfig); 045 046 String dataSources = makeDataSourcesUrl(servletConfig); 047 RepositoryContentFinder contentFinder = 048 makeContentFinder(dataSources); 049 server = 050 MondrianServer.createWithRepository( 051 contentFinder, catalogLocator); 052 } 053 return (XmlaHandler.ConnectionFactory) server; 054 } 055 056 @Override 057 public void destroy() { 058 super.destroy(); 059 if (server != null) { 060 server.shutdown(); 061 server = null; 062 } 063 } 064 065 /** 066 * Creates a callback for reading the repository. Derived classes may 067 * override. 068 * 069 * @param dataSources Data sources 070 * @return Callback for reading repository 071 */ 072 protected RepositoryContentFinder makeContentFinder(String dataSources) { 073 return new UrlRepositoryContentFinder(dataSources); 074 } 075 076 /** 077 * Make catalog locator. Derived classes can roll their own. 078 * 079 * @param servletConfig Servlet configuration info 080 * @return Catalog locator 081 */ 082 protected CatalogLocator makeCatalogLocator(ServletConfig servletConfig) { 083 ServletContext servletContext = servletConfig.getServletContext(); 084 return new ServletContextCatalogLocator(servletContext); 085 } 086 087 /** 088 * Creates the URL where the data sources file is to be found. 089 * 090 * <p>Derived classes can roll their own. 091 * 092 * <p>If there is an initParameter called "DataSourcesConfig" 093 * get its value, replace any "${key}" content with "value" where 094 * "key/value" are System properties, and try to create a URL 095 * instance out of it. If that fails, then assume its a 096 * real filepath and if the file exists then create a URL from it 097 * (but only if the file exists). 098 * If there is no initParameter with that name, then attempt to 099 * find the file called "datasources.xml" under "WEB-INF/" 100 * and if it exists, use it. 101 * 102 * @param servletConfig Servlet config 103 * @return URL where data sources are to be found 104 */ 105 protected String makeDataSourcesUrl(ServletConfig servletConfig) 106 { 107 String paramValue = 108 servletConfig.getInitParameter(PARAM_DATASOURCES_CONFIG); 109 // if false, then do not throw exception if the file/url 110 // can not be found 111 boolean optional = 112 getBooleanInitParameter( 113 servletConfig, PARAM_OPTIONAL_DATASOURCE_CONFIG); 114 115 URL dataSourcesConfigUrl = null; 116 try { 117 if (paramValue == null) { 118 // fallback to default 119 String defaultDS = "WEB-INF/" + DEFAULT_DATASOURCE_FILE; 120 ServletContext servletContext = 121 servletConfig.getServletContext(); 122 File realPath = new File(servletContext.getRealPath(defaultDS)); 123 if (realPath.exists()) { 124 // only if it exists 125 dataSourcesConfigUrl = realPath.toURL(); 126 return dataSourcesConfigUrl.toString(); 127 } else { 128 return null; 129 } 130 } else if (paramValue.startsWith("inline:")) { 131 return paramValue; 132 } else { 133 paramValue = Util.replaceProperties( 134 paramValue, 135 Util.toMap(System.getProperties())); 136 if (LOGGER.isDebugEnabled()) { 137 LOGGER.debug( 138 "XmlaServlet.makeDataSources: paramValue=" 139 + paramValue); 140 } 141 // is the parameter a valid URL 142 MalformedURLException mue = null; 143 try { 144 dataSourcesConfigUrl = new URL(paramValue); 145 } catch (MalformedURLException e) { 146 // not a valid url 147 mue = e; 148 } 149 if (dataSourcesConfigUrl == null) { 150 // see if its a full valid file path 151 File f = new File(paramValue); 152 if (f.exists()) { 153 // yes, a real file path 154 dataSourcesConfigUrl = f.toURL(); 155 } else if (mue != null) { 156 // neither url or file, 157 // is it not optional 158 if (! optional) { 159 throw mue; 160 } 161 } 162 return null; 163 } 164 return dataSourcesConfigUrl.toString(); 165 } 166 } catch (MalformedURLException mue) { 167 throw Util.newError(mue, "invalid URL path '" + paramValue + "'"); 168 } 169 } 170} 171 172// End MondrianXmlaServlet.java