/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Kowari Metadata Store.
*
* The Initial Developer of the Original Code is Plugged In Software Pty
* Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions
* created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
* Plugged In Software Pty Ltd. All Rights Reserved.
*
* Contributor(s): N/A.
*
* [NOTE: The text of this Exhibit A may differ slightly from the text
* of the notices in the Source Code files of the Original Code. You
* should use the text of this Exhibit A rather than the text found in the
* Original Code Source Code for Your Modifications.]
*
*/
package org.mulgara.descriptor;
import java.io.*;
// Java 2
import java.net.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
// Log4j
import org.apache.log4j.*;
import org.mulgara.itql.ItqlInterpreterBean;
import org.mulgara.util.StringUtil;
// W3C DOM
import org.w3c.dom.*;
/**
* Represents an Descriptor as an Element in an XSL stylesheet
*
* @created 2002-03-15
*
* @author Keith Ahern
*
* @version $Revision: 1.8 $
*
* @modified $Date: 2005/01/05 04:58:11 $
*
* @maintenanceAuthor $Author: newmana $
*
* @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A>
*
* @copyright © 2001-2003 <A href="http://www.PIsoftware.com/">Plugged In
* Software Pty Ltd</A>
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public class DescriptorElement {
/**
* Get line separator.
*/
private static final String eol = System.getProperty("line.separator");
/**
* doc factory
*/
protected static DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
/**
* descriptor factory
*/
protected static DescriptorFactory factory = DescriptorFactory.getInstance();
/**
* log4j
*/
private static final Logger log = Logger.getLogger(DescriptorElement.class);
/**
* used in Vector.toArray(p)
*
*/
private static Param[] p = new Param[] {};
/**
* delimiter to look for in query strings
*
*/
private final static String DELIM = "@@";
/**
* calls another descriptor... TODO get context
*
* @param context PARAMETER TO DO
* @param extElem PARAMETER TO DO
* @return RETURNED VALUE TO DO
* @throws DescriptorException EXCEPTION TO DO
*/
public static Node descriptor(
org.apache.xalan.extensions.XSLProcessorContext context,
org.apache.xalan.templates.ElemExtensionCall extElem) throws
DescriptorException {
if (log.isDebugEnabled()) {
log.debug("Descriptor Element XSL context: " + context);
}
// the URL of the descriptor as a String
String descURLString = null;
// Now call the descriptor
try {
// _target must always be there....
descURLString =
extElem.getAttribute(Descriptor.DESCRIPTOR_TARGET,
context.getContextNode(), context.getTransformer());
// or throw an error
if (descURLString == null) {
String errorString = Descriptor.DESCRIPTOR_TARGET +
" was not specified as an " +
" attribute - can not invoke Descriptor - good bye";
log.error(errorString);
throw new DescriptorException(errorString);
}
// try and make a URL from this - if not its relative, try and make it
// from the source URL
URL descURL;
// URL of descriptor to invoke
String sourceURLString = null;
try {
// create the descriptor URL
descURL = new URL(descURLString);
} catch (MalformedURLException use) {
log.debug("Unable to use URL from '" + descURLString +
"' as full URL attempting to make full URL");
// if the descURLString is a partial URL such as allCompanies.xsl then
// we must construct it as a proper URL from the _source URL which
// will be fully qualified e.g. http://pike.pisoftware.com:8080/descriptors/default/desc.xsl
// allCompanies.xsl -> scheme://schemespecificpart/path/allCompanies.xsl
sourceURLString =
extElem.getAttribute(Descriptor.DESCRIPTOR_SOURCE,
context.getContextNode(),
context.getTransformer());
// or throw an error
if ( (sourceURLString == null) || (sourceURLString.length() == 0)) {
String errorString = Descriptor.DESCRIPTOR_SOURCE +
" was not specified as an attribute - " +
( (sourceURLString == null) ?
" null string " : " empty string ") +
"can not invoke Descriptor - good bye";
log.error(errorString);
throw new DescriptorException(errorString);
}
if (log.isDebugEnabled()) {
log.debug("Unable to make complete URL from (" + descURLString +
") attempting " +
" to make complete URL using source URL (" +
sourceURLString + ")");
}
descURL = Descriptor.resolveRelativeURL(descURLString, sourceURLString);
}
// get the Descriptor from the Factory
Descriptor des = factory.getDescriptor(descURL);
// get the interpreter bean to use
ItqlInterpreterBean bean = null;
// see if a bean as passed as a parameter, if so use it - otherwise create one.
DescriptorContext descContext =
(DescriptorContext) context.getTransformer().getParameter(Descriptor.
DESCRIPTOR_CONTEXT);
if (descContext == null) {
if (log.isDebugEnabled()) {
log.debug("Element creating own bean");
}
bean = new ItqlInterpreterBean();
} else {
if (log.isDebugEnabled()) {
log.debug("Element using bean passed as parameter: " + bean);
}
bean = descContext.getInterpreterBean();
}
// set the passed in bean on the descriptor
des.setInterpreterBean(bean);
// get descriptor list of parameters to search for
List<Param> paramsList = des.getParams(descURL);
// get original params for this
// List origParams = des.getParams(descURL);
// get the params for the descriptor,
// List paramsList = new Vector(origParams);
// fill paramsList with modifiable copy of descriptor list
// Collections.copy(paramsList, origParams);
// sanity check list of params - should always have one - the implicit
// _self parameter. If we didn't get one then the metadata for the Descriptor
// is probably not loaded
if ( (paramsList == null) || (paramsList.size() == 0)) {
String errorString = "Could not find parameters for (" +
descURL +
") RDF is probably not loaded into the Descriptor Graph";
log.error(errorString);
throw new DescriptorException(errorString);
}
// populate params
String paramName = null;
Object paramValue = null;
Vector<Param> paramVec = new Vector<Param>();
// iterate thru the parameters this desciptor has
for (Param param: paramsList) {
paramName = param.getName();
// we have to map some internal names to their proper values
// map _self to _target to get the value
if (paramName.equalsIgnoreCase(Descriptor.DESCRIPTOR_TARGET)) {
paramValue = descURL.toString();
log.debug("adding special param " + paramValue + " as " +
Descriptor.DESCRIPTOR_TARGET);
} else {
paramValue =
extElem.getAttribute(paramName, context.getContextNode(),
context.getTransformer());
log.debug("adding param " + paramName + " '" + paramName + "'");
}
paramVec.add(new Param(paramName, paramValue));
//param.setValue(paramValue);
}
// add target as _self
paramVec.add(new Param(Descriptor.DESCRIPTOR_SELF, descURL.toString()));
Param[] params = (Param[]) paramVec.toArray(p);
// parameters
if (log.isDebugEnabled()) {
log.debug("Calling descriptor : " + descURL + " with params " +
Param.toString(params));
}
// get the data as a document fragment
//DocumentFragment df = des.processToDocumentFragment(params);
Document doc = des.processToDocument(params);
// return descriptor to factory
factory.releaseDescriptor(des);
return doc;
} catch (TransformerException te) {
String errorString="Transformer problems (" + descURLString + ")";
log.error(errorString + " cause: " + te.getCause() );
throw new DescriptorException(errorString, te);
} catch (Exception e) {
String errorString="General Exception (" + descURLString + ")";
log.error(errorString + " cause: " + e.getCause());
Descriptor.writeStackTrace(e, errorString);
throw new DescriptorException(errorString, e);
}
}
/**
* Executes a query on a Mulgara store and returns the result as a Node
*
* @param context Description of Parameter
* @param extElem Description of Parameter
* @return RETURNED VALUE TO DO
* @throws DescriptorException EXCEPTION TO DO
*/
public static Node query(
org.apache.xalan.extensions.XSLProcessorContext context,
org.apache.xalan.templates.ElemExtensionCall extElem) throws
DescriptorException {
// LOG
if (log.isDebugEnabled()) {
log.debug("JAVA ELEMENT QUERY!");
}
// bean to use
ItqlInterpreterBean bean = null;
// see if a bean as passed as a parameter, if so use it - otherwise create one.
DescriptorContext descContext =
(DescriptorContext) context.getTransformer().getParameter(Descriptor.
DESCRIPTOR_CONTEXT);
if (descContext == null) {
if (log.isDebugEnabled()) {
log.debug("Element creating own bean");
}
bean = new ItqlInterpreterBean();
} else {
if (log.isDebugEnabled()) {
log.debug("Element using bean passed as parameter: " + bean);
}
bean = descContext.getInterpreterBean();
}
// grab the query string
String queryString = extElem.getFirstChild().getNodeValue();
// execute using bean
try {
// populate params
String paramName = null;
Object paramValue = null;
Vector<Param> paramVec = new Vector<Param>();
// replace @@XXX@@
int start;
int end;
int queryStringLen = queryString.length();
start = queryString.indexOf(DELIM);
while (start > 0) {
if (start != queryStringLen) {
end = queryString.indexOf(DELIM, start + 1);
// extract var name
if (end > 0) {
paramName = queryString.substring(start + 2, end);
if (log.isDebugEnabled()) {
log.debug("Replacing " + paramName);
}
paramValue =
extElem.getAttribute(paramName, context.getContextNode(),
context.getTransformer());
// no value - then the XSL:Param was not set
if ( (paramValue == null) ||
(paramValue instanceof String &&
( (String) paramValue).equals(""))) {
if (log.isDebugEnabled()) {
log.debug("query attribute: '" + paramName +
"' is not set for this Descriptor query - please set it");
}
throw new DescriptorException("query attribute: '" + paramName +
"' is not set for this Descriptor query - please set it");
}
// add param to the vector
paramVec.add(new Param(paramName, paramValue));
//queryString = queryString.replaceAll(DELIM + paramName + DELIM,
// paramValue.toString());
queryString =
StringUtil.replaceStringWithString(queryString,
DELIM + paramName + DELIM, paramValue.toString());
} else {
throw new DescriptorException("Could not find closing " + DELIM + " good bye");
}
}
// get next one
start = queryString.indexOf(DELIM);
}
// lose the carraige returns
queryString = queryString.replaceAll(eol, "");
// show the query string
if (log.isDebugEnabled()) {
log.debug("executing query using bean: " + queryString);
}
Element result = bean.execute(queryString);
return result;
} catch (TransformerException te) {
throw new DescriptorException("Transformer probs - query string: " +
queryString, te);
} catch (java.lang.Exception e) {
throw new DescriptorException("Mulgara probs - query String:" +
queryString, e);
}
}
/**
* METHOD TO DO
*
* @param context PARAMETER TO DO
* @param extElem PARAMETER TO DO
* @throws DescriptorException EXCEPTION TO DO
*/
public static void copyURL2File(
org.apache.xalan.extensions.XSLProcessorContext context,
org.apache.xalan.templates.ElemExtensionCall extElem) throws
DescriptorException {
String src = null;
String dest = null;
try {
// src file
src =
extElem.getAttribute("src", context.getContextNode(),
context.getTransformer());
// dest file
dest =
extElem.getAttribute("dest", context.getContextNode(),
context.getTransformer());
URL url = new URL(src);
File srcFile = new File(url.getFile());
File destFile = new File(dest);
copy(srcFile, destFile);
} catch (javax.xml.transform.TransformerException te) {
throw new DescriptorException("Unable to find attributes !", te);
} catch (MalformedURLException mue) {
throw new DescriptorException("Bad File URL for source", mue);
} catch (IOException ie) {
throw new DescriptorException("Unable to copy file:" + src + " to " +
dest, ie);
}
}
/**
* Copies a source file to a dest file creating directories if necessary
*
* @param src PARAMETER TO DO
* @param dst PARAMETER TO DO
* @throws IOException EXCEPTION TO DO
*/
public static void copy(File src, File dst) throws IOException {
File parentDir = dst.getParentFile();
if (parentDir != null) parentDir.mkdirs();
InputStream is = new FileInputStream(src);
OutputStream os = null;
try {
os = new FileOutputStream(dst);
int n;
try {
byte[] buf = new byte[4096];
while ( (n = is.read(buf)) != -1) os.write(buf, 0, n);
} finally {
os.close();
}
} finally {
is.close();
}
}
/**
* Writes a Debug message to the output stream
*
* @param context PARAMETER TO DO
* @param extElem PARAMETER TO DO
* @throws DescriptorException EXCEPTION TO DO
*/
public static void debug(
org.apache.xalan.extensions.XSLProcessorContext context,
org.apache.xalan.templates.ElemExtensionCall extElem) throws
DescriptorException {
// grab the query string
String queryString = extElem.getFirstChild().getNodeValue();
queryString += extElem.getAttribute("msg");
if (log.isDebugEnabled()) log.debug("DEBUG:" + queryString);
}
}