📄 repositorystartupservlet.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.jackrabbit.j2ee;import org.apache.jackrabbit.api.JackrabbitRepository;import org.apache.jackrabbit.core.RepositoryImpl;import org.apache.jackrabbit.core.config.RepositoryConfig;import org.apache.jackrabbit.rmi.server.ServerAdapterFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.xml.sax.InputSource;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.net.InetAddress;import java.net.ServerSocket;import java.net.UnknownHostException;import java.rmi.AlreadyBoundException;import java.rmi.Naming;import java.rmi.Remote;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.RMIServerSocketFactory;import java.util.Properties;import javax.jcr.Repository;import javax.jcr.RepositoryException;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * The RepositoryStartupServlet starts a jackrabbit repository and registers it * to the JNDI environment and optional to the RMI registry. * <p id="registerAlgo"> * <b>Registration with RMI</b> * <p/> * Upon successfull creation of the repository in the {@link #init()} method, * the repository is registered with an RMI registry if the web application is * so configured. To register with RMI, the following web application * <code>init-params</code> are considered: <code>rmi-port</code> designating * the port on which the RMI registry is listening, <code>rmi-host</code> * designating the interface on the local host on which the RMI registry is * active, <code>repository-name</code> designating the name to which the * repository is to be bound in the registry, and <code>rmi-uri</code> * designating an RMI URI complete with host, optional port and name to which * the object is bound. * <p/> * If the <code>rmi-uri</code> parameter is configured with a non-empty value, * the <code>rmi-port</code> and <code>rmi-host</code> parameters are ignored. * The <code>repository-name</code> parameter is only considered if a non-empty * <code>rmi-uri</code> parameter is configured if the latter does not contain * a name to which to bind the repository. * <p/> * This is the algorithm used to find out the host, port and name for RMI * registration: * <ol> * <li>If neither a <code>rmi-uri</code> nor a <code>rmi-host</code> nor a * <code>rmi-port</code> parameter is configured, the repository is not * registered with any RMI registry. * <li>If a non-empty <code>rmi-uri</code> parameter is configured extract the * host name (or IP address), port number and name to bind to from the * URI. If the URI is not valid, host defaults to <code>0.0.0.0</code> * meaning all interfaces on the local host, port defaults to the RMI * default port (<code>1099</code>) and the name defaults to the value * of the <code>repository-name</code> parameter. * <li>If a non-empty <code>rmi-uri</code> is not configured, the host is taken * from the <code>rmi-host</code> parameter, the port from the * <code>rmi-port</code> parameter and the name to bind the repository to * from the <code>repository-name</code> parameter. If the * <code>rmi-host</code> parameter is empty or not configured, the host * defaults to <code>0.0.0.0</code> meaning all interfaces on the local * host. If the <code>rmi-port</code> parameter is empty, not configured, * zero or a negative value, the default port for the RMI registry * (<code>1099</code>) is used. * </ol> * <p/> * After finding the host and port of the registry, the RMI registry itself * is acquired. It is assumed, that host and port primarily designate an RMI * registry, which should be active on the local host but has not been started * yet. In this case, the <code>LocateRegistry.createRegistry</code> method is * called to create a registry on the local host listening on the host and port * configured. If creation fails, the <code>LocateRegistry.getRegistry</code> * method is called to get a remote instance of the registry. Note, that * <code>getRegistry</code> does not create an actual registry on the given * host/port nor does it check, whether an RMI registry is active. * <p/> * When the registry has been retrieved, either by creation or by just creating * a remote instance, the repository is bound to the configured name in the * registry. * <p/> * Possible causes for registration failures include: * <ul> * <li>The web application is not configured to register with an RMI registry at * all. * <li>The registry is expected to be running on a remote host but does not. * <li>The registry is expected to be running on the local host but cannot be * accessed. Reasons include another application which does not act as an * RMI registry is running on the configured port and thus blocks creation * of a new RMI registry. * <li>An object may already be bound to the same name as is configured to be * used for the repository. * </ul> * <p/> * <b>Note:</b> if a <code>bootstrap-config</code> init parameter is specified the * servlet tries to read the respective resource, either as context resource or * as file. The properties specified in this file override the init params * specified in the <code>web.xml</code>. * <p/> * <p/> * <b>Setup Wizard Functionality</b><br> * When using the first time, the configuraition can miss the relevant * repository parameters in the web.xml. if so, it must contain a * <code>bootstrap-config</code> parameter that referrs to a propertiy file. * This file must exsit for proper working. If not, the repository is not * started.<br> * If the servlet is not configured correctly and accessed via http, it will * provide a simple wizard for the first time configuration. It propmpts for * a new (or existing) repository home and will copy the templates of the * repository.xml and bootstrap.properties to the respective location. */public class RepositoryStartupServlet extends HttpServlet { /** * the default logger */ private static final Logger log = LoggerFactory.getLogger(RepositoryStartupServlet.class); /** * the context attribute name foe 'this' instance. */ private final static String CTX_PARAM_THIS = "repository.startup.servet"; /** * initial param name for the bootstrap config location */ public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; /** * the registered repository */ private Repository repository; /** * the jndi context; created based on configuration */ private InitialContext jndiContext; /** * Keeps a strong reference to the server side RMI repository instance to * prevent the RMI distributed Garbage Collector from collecting the * instance making the repository unaccessible though it should still be. * This field is only set to a non-<code>null</code> value, if registration * of the repository to an RMI registry succeeded in the * {@link #registerRMI()} method. * * @see #registerRMI() * @see #unregisterRMI() */ private Remote rmiRepository; /** * the file to the bootstrap config */ private File bootstrapConfigFile; /** * The bootstrap configuration */ private BootstrapConfig config; /** * Initializes the servlet.<br> * Please note that only one repository startup servlet may exist per * webapp. it registers itself as context attribute and acts as singleton. * * @throws ServletException if a same servlet is already registered or of * another initialization error occurs. */ public void init() throws ServletException { super.init(); // check if servlet is defined twice if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { throw new ServletException("Only one repository startup servlet allowed per web-app."); } getServletContext().setAttribute(CTX_PARAM_THIS, this); startup(); } /** * Returns an instance of this servlet. Please note, that only 1 * repository startup servlet can exist per webapp. * * @param context the servlet context * @return this servlet */ public static RepositoryStartupServlet getInstance(ServletContext context) { return (RepositoryStartupServlet) context.getAttribute(CTX_PARAM_THIS); } /** * Configures and starts the repository. It registers it then to the * RMI registry and bind is to the JNDI context if so configured. * @throws ServletException if an error occurs. */ public void startup() throws ServletException { if (repository != null) { log.error("Startup: Repository already running."); throw new ServletException("Repository already running."); } log.info("RepositoryStartupServlet initializing..."); try { configure(); initRepository(); registerRMI(); registerJNDI(); log.info("RepositoryStartupServlet initialized."); } catch (ServletException e) { // shutdown repository shutdownRepository(); log.error("RepositoryStartupServlet initializing failed: " + e, e); } } /** * Does a shutdown of the repository and deregisters it from the RMI * registry and unbinds if from the JNDI context if so configured. */ public void shutdown() { if (repository == null) { log.info("Shutdown: Repository already stopped."); } else { log.info("RepositoryStartupServlet shutting down..."); shutdownRepository(); unregisterRMI(); unregisterJNDI(); log.info("RepositoryStartupServlet shut down."); } } /** * Restarts the repository. * @throws ServletException if an error occurs. * @see #shutdown() * @see #startup() */ public void restart() throws ServletException { if (repository != null) { shutdown(); } startup(); } /** * destroy the servlet */ public void destroy() { super.destroy(); shutdown(); } /** * Returns the started repository or <code>null</code> if not started * yet. * @return the JCR repository */ public Repository getRepository() { return repository; } /** * Reads the configuration and initializes the {@link #config} field if * successful. * @throws ServletException if an error occurs. */ private void configure() throws ServletException { // check if there is a loadable bootstrap config Properties bootstrapProps = new Properties(); String bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); if (bstrp != null) { // check if it's a web-resource InputStream in = getServletContext().getResourceAsStream(bstrp); if (in == null) { // check if it's a file bootstrapConfigFile = new File(bstrp); if (bootstrapConfigFile.canRead()) { try { in = new FileInputStream(bootstrapConfigFile); } catch (FileNotFoundException e) { log.error("Error while opening bootstrap properties: {}", e.toString()); throw new ServletException("Error while opening bootstrap properties: " + e.toString()); } } } if (in != null) { try { bootstrapProps.load(in); } catch (IOException e) { log.error("Error while loading bootstrap properties: {}", e.toString()); throw new ServletException("Error while loading bootstrap properties: " + e.toString()); } finally { try { in.close(); } catch (IOException e) { // ignore } } } } // read bootstrap config config = new BootstrapConfig(); config.init(getServletConfig()); config.init(bootstrapProps); config.validate(); if (!config.isValid() || config.getRepositoryHome() == null || config.getRepositoryConfig() == null) { if (bstrp == null) { log.error("Repository startup configuration is not valid."); throw new ServletException("Repository startup configuration is not valid."); } else { log.error("Repository startup configuration is not valid but a bootstrap config is specified."); log.error("Either create the {} file or", bstrp); log.error("use the '/config/index.jsp' for easy configuration."); throw new ServletException("Repository startup configuration is not valid."); } } config.logInfos(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -