// $Id: CatalogServlet.java,v 1.3 2004-02-06 15:23:49 donm Exp $
/*
* Copyright 1997-2000 Unidata Program Center/University Corporation for
* Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
* support@unidata.ucar.edu.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package dods.servers.agg;
import dods.dap.*;
import dods.dap.Server.ServerDDS;
import dods.dap.parser.ParseException;
import dods.util.iniFile;
import dods.util.Debug;
import dods.servers.netcdf.NcDataset;
import dods.servlet.DODSServlet;
import dods.servlet.GuardedDataset;
import dods.servlet.requestState;
import thredds.catalog.AggServerConfig;
import thredds.catalog.InvCatalog;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
//import javax.xml.transform.*;
//import javax.xml.transform.stream.StreamSource;
//import javax.xml.transform.stream.StreamResult;
/***************************************************************************
* This servlet uses an InventoryCatalog XML files to list what datasets it can serve.
* It can currently 1) serve netcdf files and 2) aggregate files into logical datasets using
* files from other DODS servers or from its own set of netcdf files. (It will be possible
* to serve other kinds of files later).
*
* The configuration file is kept in "$user_home/DODSagg.ini"; it should have one or both of
* the following sections:
*
* <pre>
* [Catalog]
* catalogURL = the xml catalog URL
* maxDatasetsCached = number of datasets to cache; old ones are closed using an LRU algorithm.
* dataRoot = data root directory for netcdf files
* </pre>
*
* @author John Caron
* @version $Id: CatalogServlet.java,v 1.3 2004-02-06 15:23:49 donm Exp $
*/
public class CatalogServlet extends DODSServlet {
private static final boolean debugInit = false;
private static final boolean debugLocks = false;
private static final boolean debugDIR = false;
private static final boolean debugOpen = false;
private static final boolean showCatalog = false;
private static final boolean showServerInfo = false;
private static final boolean runWithJBuilder = false; // debugging
private String displayName = "DODS Aggregation/Catalog Server";
private String serverURL = "http://localhost:8080/servlet/dods.servers.agg.CatalogServlet/"; // debugging
private String configURL = null;
private int maxCatalogDatasetsCached = 0;
private int maxAggDatasetsCached = 10;
private int maxDODSDatasetsCached = 100;
private int maxNetcdfFilesCached = 100;
private String catalogPage;
private AggServerConfig catalog;
public void init() throws javax.servlet.ServletException {
//System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
super.init();
if (showServerInfo) {
System.out.println("--------------------");
System.out.println("getServletName() = "+getServletName());
System.out.println("getServletInfo() = "+getServletInfo());
System.out.println("InitParameters = ");
java.util.Enumeration params = getInitParameterNames();
while (params.hasMoreElements()) {
String p = (String) params.nextElement();
System.out.println(" "+p+" == "+getInitParameter(p));
}
ServletContext sc = getServletContext();
System.out.println("ServletContext "+sc);
System.out.println(" getServerInfo() = "+sc.getServerInfo());
System.out.println(" getMajorVersion() = "+sc.getMajorVersion());
System.out.println(" getMinorVersion() = "+sc.getMinorVersion());
System.out.println(" getRealPath() = "+sc.getRealPath("/"));
System.out.println(" ServletContext Attributes = ");
java.util.Enumeration attNames = sc.getAttributeNames();
while (attNames.hasMoreElements()) {
String att = (String) attNames.nextElement();
System.out.println(" "+att+" == "+sc.getAttribute(att));
}
System.out.println(" ServletContext InitParameters = ");
params = sc.getInitParameterNames();
while (params.hasMoreElements()) {
String p = (String) params.nextElement();
System.out.println(" "+p+" == "+sc.getInitParameter(p));
}
ServletConfig sg = getServletConfig();
System.out.println("ServletConfig "+sg);
System.out.println(" Context "+sg.getServletContext());
System.out.println(" Config InitParameters = ");
params = sg.getInitParameterNames();
while (params.hasMoreElements()) {
String p = (String) params.nextElement();
System.out.println(" "+p+" == "+sg.getInitParameter(p));
}
System.out.println("--------------------");
}
String docRoot = getServletContext().getRealPath("/");
if (debugInit) System.out.println("Root = "+ docRoot);
try {
File root = new File(".");
if (debugInit) System.out.println("Test PWD File = "+ root.getAbsolutePath());
if (debugInit) System.out.println("PWD File = "+ root.getCanonicalPath());
} catch (Exception e ) {
e.printStackTrace();
}
// set up the AggDataset cache
String p = getInitParameter("maxAggDatasetsCached");
if (p != null) {
try {
maxAggDatasetsCached = Integer.parseInt(p);
if (debugInit) System.out.println(" maxAggDatasetsCached = "+maxAggDatasetsCached);
} catch (NumberFormatException e) {
System.out.println(" maxAggDatasetsCached bad number format in web.xml; use value "+maxDODSDatasetsCached);
}
}
AggDataset.setCacheMax(maxAggDatasetsCached);
// set up the dodsDataset cache
p = getInitParameter("maxDODSDatasetsCached");
if (p != null) {
try {
maxDODSDatasetsCached = Integer.parseInt(p);
if (debugInit) System.out.println(" maxDODSDatasetsCached = "+maxDODSDatasetsCached);
} catch (NumberFormatException e) {
System.out.println(" maxDODSDatasetsCached bad number format in web.xml; use value "+maxDODSDatasetsCached);
}
}
DODSDataset.setCacheMax(maxDODSDatasetsCached);
// set up the NetcdfFile cache
p = getInitParameter("maxNetcdfFilesCached");
if (p != null) {
try {
maxNetcdfFilesCached = Integer.parseInt(p);
if (debugInit) System.out.println(" maxNetcdfFilesCached = "+maxNetcdfFilesCached);
} catch (NumberFormatException e) {
System.out.println(" maxNetcdfFilesCached bad number format in web.xml; use value "+maxNetcdfFilesCached);
}
}
NcDataset.setCacheMax(maxNetcdfFilesCached);
// read the config file
String configURL = getInitParameter("serverConfig");
if (configURL != null) {
try {
catalog = new AggServerConfig( configURL);
} catch (java.net.MalformedURLException e) {
System.out.println("CatalogServlet reading xml config file: MalformedURLException: "+ configURL);
throw new IllegalStateException(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println("CatalogServlet reading xml config file: URL not found: "+ configURL);
throw new IllegalStateException(e.getMessage());
} catch (IOException e) {
System.out.println("CatalogServlet: error reading xml config file: "+ configURL+"/n"+e);
e.printStackTrace();
throw new IllegalStateException(e.getMessage());
}
if (showCatalog) System.out.println("Parsed Catalog =\n"+catalog.dump());
}
// other parameters
String dn = getInitParameter("displayName");
if (dn != null)
displayName = dn;
if (debugInit) System.out.println("CatalogServlet init done");
// Create the HTML page once
//catalogPage = doTransform( configURL, "http://www.unidata.ucar.edu/projects/THREDDS/xml/AggServerConfig.0.4.xsl");
}
public String getServerVersion() { return "CatalogAggServer/0.2"; }
protected void printCatalog(PrintWriter pw) throws IOException {
String xml = catalog.getSerializedForm(false);
// System.out.println( xml);
pw.write( xml);
}
// to be overridden by servers that implement status report
protected void printStatus(PrintWriter os) throws IOException {
super.printStatus( os);
os.println("<li># Agg files in cache= "+AggDataset.getCacheSize());
Iterator iter = AggDataset.getCache();
while (iter.hasNext()) {
Dataset ds = (Dataset) iter.next();
os.println("<p>- "+ds.getInternalPath()+" "+ds.whoHasLock());
}
os.println("<li># DODS files in cache= "+DODSDataset.getCacheSize());
iter = DODSDataset.getCache();
while (iter.hasNext()) {
Dataset ds = (Dataset) iter.next();
os.println("<p>- "+ds.getInternalPath()+" "+ds.whoHasLock());
}
os.println("<li># Netcdf files in cache= "+NcDataset.getCacheSize());
iter = NcDataset.getCache();
while (iter.hasNext()) {
NcDataset ds = (NcDataset) iter.next();
ucar.nc2.NetcdfFile ncfile = ds.getNetcdfFile();
os.println("<p>- "+ncfile.getPathName()+" "+ds.whoHasLock());
}
}
/* private String doTransform( String xmlURL, String styleSheet) {
//throws TransformerException, TransformerConfigurationException,
// FileNotFoundException, IOException {
System.out.println(" XSLT transform = "+xmlURL+" "+styleSheet);
// debug
javax.xml.parsers.SAXParserFactory factory = null;
try {
factory = javax.xml.parsers.SAXParserFactory.newInstance();
System.out.println(" SAXParserFactory class = "+factory.getClass().getName());
} catch( Error e) {
System.out.println(" SAXParserFactory Exception "+e);
e.printStackTrace();
}
try {
javax.xml.parsers.SAXParser test = factory.newSAXParser();
System.out.println(" SAXParser class = "+test.getClass().getName()
+" "+test.getClass().getClassLoader());
System.out.println(" Namespaces = "+test.isNamespaceAware()+
" Validate = "+test.isValidating());
} catch( Exception e) {
System.out.println(" SAXParser Exception "+e);
e.printStackTrace();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream(10000);
Transformer transformer = null;
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
System.out.println(" TransformerFactory class = "+tFactory.getClass().getName());
transformer = tFactory.newTransformer(new StreamSource(styleSheet));
//transformer = new org.apache.xalan.transformer.TransformerImpl( new StreamSource(styleSheet));
System.out.println(" Transformer class = "+transformer.getClass().getName());
transformer.transform(new StreamSource(xmlURL), new StreamResult(bos));
} catch (Exception e) {
System.out.println(" Exception in XSLT = "+styleSheet+" on file "+xmlURL);
System.out.println(" "+ e.getMessage());
e.printStackTrace();
return "Error";
}
return bos.toString();
} */
/*********************** dataset directory ***************************************************/
public void doGetDIR(HttpServletRequest request, HttpServletResponse response, requestState rs)
throws IOException, ServletException {
response.setHeader("XDODS-Server", getServerVersion());
response.setContentType("text/html");
response.setHeader("Content-Description", "dods_directory");
if (debugDIR) {
System.out.println("doGetDIR request = "+ request);
System.out.println(" URI = "+ request.getRequestURI());
System.out.println(" ServletPath = "+ request.getServletPath());
//System.out.println(" serverPath() = "+ getServerPath());
System.out.println(" URL = "+ HttpUtils.getRequestURL(request));
}
//PrintWriter pw = new PrintWriter(response.getOutputStream());
PrintWriter pw = response.getWriter();
/*pw.print(catalogPage);
pw.flush();
} */
//String thisServer = HttpUtils.getRequestURL(request).toString();
pw.println("<html>");
pw.println("<head>");
pw.println("<title>DODS Directory</title>");
pw.println("<meta http-equiv=\"Content-Type\" content=\"text/html\">");
pw.println("</head>");
pw.println("<body bgcolor=\"#FFFFFF\">");
pw.println("<h1>DODS Directory for:</h1>");
pw.println("<h2>" + displayName+"</h2>");
pw.println("<hr>");
//pw.println("<table border=\"0\">");
InvCatalog.Collection root = catalog.getRootCollection();
showCollection( pw, root);
//pw.println("</table>");
pw.println("<hr>");
pw.println("</html>");
pw.flush();
}
private void showCollection(PrintWriter pw, InvCatalog.Collection c) {
ArrayList datasets = c.getDatasets();
if (datasets.size() > 0) {
pw.println("<ul> ");
for (int i=0; i<datasets.size(); i++) {
InvCatalog.Dataset ds = (InvCatalog.Dataset) datasets.get(i);
pw.println("<li> ");
showDataset(pw, ds);
}
pw.println("</ul> ");
}
ArrayList collections = c.getCollections();
if (collections.size() > 0) {
pw.println("<ul> ");
for (int i=0; i<collections.size(); i++) {
InvCatalog.Collection cc = (InvCatalog.Collection) collections.get(i);
pw.println("<li> " +cc.getName());
showCollection( pw, cc);
}
pw.println("</ul> ");
}
}
private void showDataset(PrintWriter pw, InvCatalog.Dataset dset) {
String urlName;
if (runWithJBuilder)
urlName = serverURL + dset.getURLpath();
else
urlName = dset.getURL();
pw.print("<b>" +dset.getName() + ":</b> ");
pw.print(" <a href='" + urlName + ".dds'>DDS</a> ");
pw.print(" <a href='" +urlName + ".das'>DAS</a> ");
pw.print(" <a href='" +urlName+ ".info'>Information</a> ");
pw.print(" <a href='" +urlName +".html'>Data Request Form</a> ");
}
/************************** dataset caching ************************************************/
protected GuardedDataset getDataset(requestState preq) throws DODSException, IOException, ParseException {
Dataset ds = null;
String urlPath = preq.getDataSet();
// open it
InvCatalog.Dataset invDS = catalog.findDatasetByURLpath( urlPath);
if (invDS == null) throw new IOException( "Dataset not found in catalog; dataURL= <"+urlPath+">");
if (invDS.getUserObj() != null) { // its an agg dataset
try {
if (debugOpen) System.out.println("CatalogServlet try to acquire Agg = "+urlPath);
ds = AggDataset.acquire(urlPath, invDS.getLocalPath(), invDS);
if (debugOpen) System.out.println(" acquire is ok = "+urlPath);
} catch (IOException e) {
System.out.println("CatalogServlet ERROR opening AggDataset "+urlPath);
e.printStackTrace();
throw new DODSException("CatalogServlet ERROR opening AggDataset "+urlPath);
}
} else { // otherwise its a netcdf dataset
try {
if (debugOpen) System.out.println("CatalogServlet try to acquire Nc = "+urlPath);
ds = NcDataset.acquire(urlPath, invDS.getLocalPath(), invDS, true);
} catch (IOException e) {
System.out.println("CatalogServlet ERROR opening NcDataset "+urlPath);
throw new DODSException("CatalogServlet ERROR opening NcDataset "+urlPath);
}
}
if (debugLocks && !ds.isLockedByMe()) {
System.out.println("CatalogServlet Dataset NOT LOCKED "+urlPath);
throw new RuntimeException("CatalogServlet Dataset NOT LOCKED "+urlPath);
}
return ds;
}
}
/* Change History:
$Log: not supported by cvs2svn $
Revision 1.10 2002/02/25 16:35:35 caron
ServletException int
Revision 1.9 2002/02/25 15:49:51 caron
file path debug
Revision 1.8 2001/11/16 01:04:46 caron
doGetDir() params
Revision 1.7 2001/11/05 17:53:47 caron
requestState
Revision 1.6 2001/10/26 19:07:10 caron
getClientDDS()
Revision 1.5 2001/10/24 23:00:47 ndp
added Makefile
Revision 1.4 2001/10/24 22:49:57 ndp
*** empty log message ***
Revision 1.3 2001/10/12 21:21:12 caron
JC: use ParsedRequest
Revision 1.2 2001/10/03 22:47:33 caron
serverVersion
Revision 1.1.1.1 2001/09/26 15:36:47 caron
checkin beta1
*/