rolapschema.java
来自「数据仓库展示程序」· Java 代码 · 共 1,346 行 · 第 1/4 页
JAVA
1,346 行
} catch (Exception e) {
throw MondrianResource.instance().NamedSetHasBadFormula.ex(
xmlNamedSet.name, e);
}
final Formula formula = new Formula(
new String[] {xmlNamedSet.name},
exp);
return formula.getNamedSet();
}
private Role createRole(MondrianDef.Role xmlRole) {
Role role = new Role();
for (int i = 0; i < xmlRole.schemaGrants.length; i++) {
MondrianDef.SchemaGrant schemaGrant = xmlRole.schemaGrants[i];
role.grant(this, getAccess(schemaGrant.access, schemaAllowed));
for (int j = 0; j < schemaGrant.cubeGrants.length; j++) {
MondrianDef.CubeGrant cubeGrant = schemaGrant.cubeGrants[j];
Cube cube = lookupCube(cubeGrant.cube);
if (cube == null) {
throw Util.newError("Unknown cube '" + cube + "'");
}
role.grant(cube, getAccess(cubeGrant.access, cubeAllowed));
final SchemaReader schemaReader = cube.getSchemaReader(null);
for (int k = 0; k < cubeGrant.dimensionGrants.length; k++) {
MondrianDef.DimensionGrant dimensionGrant =
cubeGrant.dimensionGrants[k];
Dimension dimension = (Dimension)
schemaReader.lookupCompound(
cube, Util.explode(dimensionGrant.dimension), true,
Category.Dimension);
role.grant(dimension,
getAccess(dimensionGrant.access, dimensionAllowed));
}
for (int k = 0; k < cubeGrant.hierarchyGrants.length; k++) {
MondrianDef.HierarchyGrant hierarchyGrant =
cubeGrant.hierarchyGrants[k];
Hierarchy hierarchy = (Hierarchy)
schemaReader.lookupCompound(
cube, Util.explode(hierarchyGrant.hierarchy), true,
Category.Hierarchy);
final int hierarchyAccess =
getAccess(hierarchyGrant.access, hierarchyAllowed);
Level topLevel = null;
if (hierarchyGrant.topLevel != null) {
if (hierarchyAccess != Access.CUSTOM) {
throw Util.newError("You may only specify 'topLevel' if access='custom'");
}
topLevel = (Level) schemaReader.lookupCompound(
cube, Util.explode(hierarchyGrant.topLevel), true,
Category.Level);
}
Level bottomLevel = null;
if (hierarchyGrant.bottomLevel != null) {
if (hierarchyAccess != Access.CUSTOM) {
throw Util.newError("You may only specify 'bottomLevel' if access='custom'");
}
bottomLevel = (Level) schemaReader.lookupCompound(
cube, Util.explode(hierarchyGrant.bottomLevel),
true, Category.Level);
}
role.grant(hierarchy, hierarchyAccess, topLevel, bottomLevel);
for (int m = 0; m < hierarchyGrant.memberGrants.length; m++) {
if (hierarchyAccess != Access.CUSTOM) {
throw Util.newError("You may only specify <MemberGrant> if <Hierarchy> has access='custom'");
}
MondrianDef.MemberGrant memberGrant = hierarchyGrant.memberGrants[m];
Member member = schemaReader.getMemberByUniqueName(Util.explode(memberGrant.member),true);
if (member.getHierarchy() != hierarchy) {
throw Util.newError("Member '" + member + "' is not in hierarchy '" + hierarchy + "'");
}
role.grant(member, getAccess(memberGrant.access, memberAllowed));
}
}
}
}
role.makeImmutable();
return role;
}
private int getAccess(String accessString, int[] allowed) {
final int access = Access.instance().getOrdinal(accessString);
for (int i = 0; i < allowed.length; i++) {
if (access == allowed[i]) {
return access; // value is ok
}
}
throw Util.newError("Bad value access='" + accessString + "'");
}
public Dimension createDimension(Cube cube, String xml) {
MondrianDef.CubeDimension xmlDimension = null;
try {
final Parser xmlParser = XOMUtil.createDefaultParser();
final DOMWrapper def = xmlParser.parse(xml);
final String tagName = def.getTagName();
if (tagName.equals("Dimension")) {
xmlDimension = new MondrianDef.Dimension(def);
} else if (tagName.equals("DimensionUsage")) {
xmlDimension = new MondrianDef.DimensionUsage(def);
} else {
throw new XOMException("Got <" + tagName +
"> when expecting <Dimension> or <DimensionUsage>");
}
} catch (XOMException e) {
throw Util.newError(e, "Error while adding dimension to cube '" +
cube + "' from XML [" + xml + "]");
}
return ((RolapCube) cube).createDimension(xmlDimension);
}
public Cube createCube(String xml) {
MondrianDef.Cube xmlDimension;
try {
final Parser xmlParser = XOMUtil.createDefaultParser();
final DOMWrapper def = xmlParser.parse(xml);
final String tagName = def.getTagName();
if (tagName.equals("Cube")) {
xmlDimension = new MondrianDef.Cube(def);
} else {
throw new XOMException("Got <" + tagName +
"> when expecting <Cube>");
}
} catch (XOMException e) {
throw Util.newError(e, "Error while creating cube from XML [" +
xml + "]");
}
// Create empty XML schema, to keep the method happy. This is okay,
// because there are no forward-references to resolve.
final MondrianDef.Schema xmlSchema = new MondrianDef.Schema();
RolapCube cube = new RolapCube(this, xmlSchema, xmlDimension);
return cube;
}
/**
* A collection of schemas, identified by their connection properties
* (catalog name, JDBC URL, and so forth).
*
* <p>To lookup a schema, call <code>Pool.instance().{@link #get(String, DataSource, Util.PropertyList)}</code>.
*/
static class Pool {
private static MessageDigest md = null;
static {
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
private static Pool pool = new Pool();
private Map mapUrlToSchema = new HashMap();
private Pool() {
}
static Pool instance() {
return pool;
}
/**
* Read a Reader until EOF and return as String.
* Note: this ought to be in a Utility class.
*
* @param rdr Reader to read.
* @param bufferSize size of buffer to allocate for reading.
* @return content of Reader as String or null if Reader was empty.
* @throws IOException
*/
public static String readFully(final Reader rdr, final int bufferSize)
throws IOException {
if (bufferSize <= 0) {
throw new IllegalArgumentException(
"Buffer size must be greater than 0");
}
final char[] buffer = new char[bufferSize];
final StringBuffer buf = new StringBuffer(bufferSize);
int len = rdr.read(buffer);
while (len != -1) {
buf.append(buffer, 0, len);
len = rdr.read(buffer);
}
final String s = buf.toString();
return (s.length() == 0) ? null : s;
}
/**
* Create an MD5 hash of String.
* Note: this ought to be in a Utility class.
*
* @param value String to create one way hash upon.
* @return MD5 hash.
* @throws NoSuchAlgorithmException
*/
public static String encodeMD5(final String value) {
md.reset();
final byte[] bytes = md.digest(value.getBytes());
return (bytes != null) ? new String(bytes) : null;
}
public static final int BUF_SIZE = 8096;
/**
* Read URL and return String containing content.
* Note: this ought to be in a Utility class.
*
* @param urlStr actually a catalog URL
* @return String containing content of catalog.
* @throws MalformedURLException
* @throws IOException
*/
public static String readURL(final String urlStr)
throws MalformedURLException, IOException {
final URL url = new URL(urlStr);
final Reader r =
new BufferedReader(new InputStreamReader(url.openStream()));
final String xmlCatalog = readFully(r, BUF_SIZE);
return xmlCatalog;
}
/**
* Compare two byte arrays for equality checking both length and
* byte values.
* Note: this ought to be in a Utility class.
*
* @param b1 first byte array.
* @param b2 second byte array.
* @return true if lengths and all values are equal and false otherwise.
private static boolean equals(final byte[] b1, final byte[] b2) {
if (b1.length != b2.length) {
return false;
} else {
for (int i = 0; i < b1.length; i++) {
if (b1[i] != b2[i]) {
return false;
}
}
}
return true;
}
*/
/**
* Note: this is a place holder variable. The value of USE_MD5 should be
* determined by a new mondrian property in the connectInfo string.
* Currently a "normal" property is used simply so that I can test it.
*/
private static final String MD5_PROP
= "mondrian.catalog.content.cache.enabled";
private static final boolean USE_MD5 = Boolean.getBoolean(MD5_PROP);
synchronized RolapSchema get(final String catalogName,
final String connectionKey,
final String jdbcUser,
final String dataSourceStr,
final Util.PropertyList connectInfo) {
return get(catalogName,
connectionKey,
jdbcUser,
dataSourceStr,
null,
connectInfo);
}
synchronized RolapSchema get(final String catalogName,
final DataSource dataSource,
final Util.PropertyList connectInfo) {
return get(catalogName,
null,
null,
null,
dataSource,
connectInfo);
}
private RolapSchema get(final String catalogName,
final String connectionKey,
final String jdbcUser,
final String dataSourceStr,
final DataSource dataSource,
final Util.PropertyList connectInfo) {
final String key = (dataSource == null)
? makeKey(catalogName,
connectionKey,
jdbcUser,
dataSourceStr)
: makeKey(catalogName,
dataSource);
RolapSchema schema = null;
final String dynProc =
connectInfo.get(RolapConnectionProperties.DynamicSchemaProcessor);
// If there is a dynamic processor registered, use it. This
// implies there is not MD5 based caching, but, as with the previous
// implementation, if the catalog string is in the connectInfo
// object as catalog content then it is used.
if ( ! Util.isEmpty(dynProc)) {
String catalogStr =
connectInfo.get(RolapConnectionProperties.CatalogContent);
schema = (catalogStr == null)
// If a schema will be dynamically processed, caching is not
// possible.
? new RolapSchema(key,
catalogName,
connectInfo,
dynProc,
dataSource)
// Got the catalog string, no need to get it again in the
// constructor
: new RolapSchema(key,
catalogName,
catalogStr,
connectInfo,
dataSource);
if (LOGGER.isDebugEnabled()) {
String msg = "Pool.get: create schema \"" +
catalogName +
"\" using dynamic processor";
LOGGER.debug(msg);
}
} else {
if (USE_MD5) {
// Different catalogNames can actually yield the same
// catalogStr! So, we use the MD5 as the key as well as
// the key made above - its has two entries in the
// mapUrlToSchema Map. We must then also during the
// remove operation make sure we remove both.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?