package tap.config; /* * This file is part of TAPLibrary. * * TAPLibrary 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 3 of the License, or * (at your option) any later version. * * TAPLibrary 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 TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2014-2015 - Astronomisches Rechen Institut (ARI) */ import static tap.config.TAPConfiguration.DEFAULT_TAP_CONF_FILE; import static tap.config.TAPConfiguration.KEY_HOME_PAGE; import static tap.config.TAPConfiguration.KEY_HOME_PAGE_MIME_TYPE; import static tap.config.TAPConfiguration.TAP_CONF_PARAMETER; import static tap.config.TAPConfiguration.fetchClass; import static tap.config.TAPConfiguration.getProperty; import static tap.config.TAPConfiguration.isClassPath; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.util.Properties; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import tap.ServiceConnection; import tap.TAPException; import tap.resource.HomePage; import tap.resource.TAP; public class ConfigurableTAPServlet extends HttpServlet { private static final long serialVersionUID = 1L; private TAP tap = null; @Override public void init(final ServletConfig config) throws ServletException{ // Nothing to do, if TAP is already initialized: if (tap != null) return; /* 1. GET THE FILE PATH OF THE TAP CONFIGURATION FILE */ String tapConfPath = config.getInitParameter(TAP_CONF_PARAMETER); if (tapConfPath == null || tapConfPath.trim().length() == 0) tapConfPath = null; //throw new ServletException("Configuration file path missing! You must set a servlet init parameter whose the name is \"" + TAP_CONF_PARAMETER + "\"."); /* 2. OPEN THE CONFIGURATION FILE */ InputStream input = null; // CASE: No file specified => search in the classpath for a file having the default name "tap.properties". if (tapConfPath == null) input = searchFile(DEFAULT_TAP_CONF_FILE, config); else{ File f = new File(tapConfPath); // CASE: The given path matches to an existing local file. if (f.exists()){ try{ input = new FileInputStream(f); }catch(IOException ioe){ throw new ServletException("Impossible to read the TAP configuration file (" + tapConfPath + ")!", ioe); } } // CASE: The given path seems to be relative to the servlet root directory. else input = searchFile(tapConfPath, config); } // If no file has been found, cancel the servlet loading: if (input == null) throw new ServletException("Configuration file not found with the path: \"" + tapConfPath + "\"! Please provide a correct file path for the TAP configuration file."); /* 3. PARSE IT INTO A PROPERTIES SET */ Properties tapConf = new Properties(); try{ tapConf.load(input); }catch(IOException ioe){ throw new ServletException("Impossible to read the TAP configuration file (" + tapConfPath + ")!", ioe); }finally{ try{ input.close(); }catch(IOException ioe2){} } /* 4. CREATE THE TAP SERVICE */ ServiceConnection serviceConn = null; try{ // Create the service connection: serviceConn = new ConfigurableServiceConnection(tapConf); // Create all the TAP resources: tap = new TAP(serviceConn); }catch(Exception ex){ tap = null; if (ex instanceof TAPException) throw new ServletException(ex.getMessage(), ex.getCause()); else throw new ServletException("Impossible to initialize the TAP service!", ex); } /* 4Bis. SET THE HOME PAGE */ String propValue = getProperty(tapConf, KEY_HOME_PAGE); if (propValue != null){ // If it is a class path, replace the current home page by an instance of this class: if (isClassPath(propValue)){ Class<? extends HomePage> newHomePage = null; try{ // ...fetch the class: newHomePage = fetchClass(propValue, KEY_HOME_PAGE, HomePage.class); // ...get its constructor with TAP object: Constructor<? extends HomePage> constructor = newHomePage.getConstructor(TAP.class); // ...create a new instance and set it as new home page: tap.setHomePage(constructor.newInstance(tap)); }catch(NoSuchMethodException e){ throw new ServletException("Missing constructor " + (newHomePage == null ? "HomePage" : newHomePage.getName()) + "(TAP)! This constructor is required to set a new home page to your TAP service."); }catch(Exception ex){ if (ex instanceof TAPException) throw new ServletException(ex.getMessage(), (ex.getCause() == null ? ex : ex.getCause())); else throw new ServletException("Impossible to set the specified home page: \"" + propValue + "\"!", ex); } } // If it is a file URI (null, file inside WebContent, file://..., http://..., etc...): else{ // ...set the given URI: tap.setHomePageURI(propValue); // ...and its MIME type (if any): propValue = getProperty(tapConf, KEY_HOME_PAGE_MIME_TYPE); if (propValue != null) tap.setHomePageMimeType(propValue); } } /* 5. DEFAULT SERVLET INITIALIZATION */ super.init(config); /* 6. FINALLY MAKE THE SERVICE AVAILABLE */ serviceConn.setAvailable(true, "TAP service available."); } protected final InputStream searchFile(final String filePath, final ServletConfig config){ InputStream input = null; // Try to search in the classpath (with just a file name or a relative path): input = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath); // If not found, try searching in the WebContent directory (as this fileName is a file path relative to WebContent): if (input == null) input = config.getServletContext().getResourceAsStream(filePath); // LAST CHANCE: Only if it is not a path... if (input == null && filePath.indexOf(File.separatorChar) < 0){ // ...try at the root of WEB-INF: input = config.getServletContext().getResourceAsStream("/WEB-INF/" + filePath); // ...and at the root of META-INF: if (input == null) input = config.getServletContext().getResourceAsStream("/META-INF/" + filePath); } return input; } @Override public void destroy(){ // Free all resources used by TAP: if (tap != null){ tap.destroy(); tap = null; } super.destroy(); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ if (tap != null){ try{ tap.executeRequest(req, resp); }catch(Throwable t){ System.err.println("Request aborted !"); t.printStackTrace(System.err); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getMessage()); } }else resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "TAP service not yet initialized!"); } }