001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.hsqldb;
018:
019: import java.io.File;
020: import java.io.IOException;
021:
022: import org.apache.avalon.framework.CascadingRuntimeException;
023: import org.apache.avalon.framework.activity.Startable;
024: import org.apache.avalon.framework.context.Context;
025: import org.apache.avalon.framework.context.ContextException;
026: import org.apache.avalon.framework.context.Contextualizable;
027: import org.apache.avalon.framework.logger.AbstractLogEnabled;
028: import org.apache.avalon.framework.parameters.Parameterizable;
029: import org.apache.avalon.framework.parameters.Parameters;
030: import org.apache.avalon.framework.parameters.ParameterException;
031: import org.apache.avalon.framework.service.ServiceException;
032: import org.apache.avalon.framework.service.ServiceManager;
033: import org.apache.avalon.framework.service.Serviceable;
034: import org.apache.avalon.framework.thread.ThreadSafe;
035:
036: import org.apache.cocoon.Constants;
037: import org.apache.cocoon.components.thread.RunnableManager;
038: import org.hsqldb.Database;
039: import org.hsqldb.DatabaseManager;
040:
041: /**
042: * This class runs an instance of the HSQLDB HSQL protocol network database server.
043: *
044: * @author <a href="mailto:dims@yahoo.com">Davanum Srinivas</a>
045: * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
046: * @version CVS $Id: ServerImpl.java 494848 2007-01-10 15:19:43Z cziegeler $
047: */
048: public class ServerImpl extends AbstractLogEnabled implements Server,
049: Parameterizable, Contextualizable, ThreadSafe, Runnable,
050: Serviceable, Startable {
051:
052: private static final boolean DEFAULT_TRACE = false;
053: private static final boolean DEFAULT_SILENT = true;
054: private static final int DEFAULT_PORT = 9002;
055: private static final String CONTEXT_PROTOCOL = "context:/";
056: private static final String DEFAULT_DB_NAME = "cocoondb";
057: private static final String DEFAULT_DB_PATH = "context://WEB-INF/db";
058:
059: /** Cocoon context **/
060: private org.apache.cocoon.environment.Context cocoonContext;
061:
062: /** The HSQLDB HSQL protocol network database server instance **/
063: private org.hsqldb.Server hsqlServer = new org.hsqldb.Server();
064:
065: /** The threadpool name to be used for daemon thread */
066: private String m_daemonThreadPoolName = "daemon";
067:
068: /** The {@link ServiceManager} instance */
069: private ServiceManager m_serviceManager;
070:
071: /** Contextualize this class */
072: public void contextualize(Context context) throws ContextException {
073: cocoonContext = (org.apache.cocoon.environment.Context) context
074: .get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
075: }
076:
077: /**
078: * Initialize the ServerImpl.
079: * Posible options:
080: * <ul>
081: * <li>port = port where the server is listening</li>
082: * <li>silent = false => display all queries</li>
083: * <li>trace = print JDBC trace messages</li>
084: * <li>name = name of the HSQL-DB</li>
085: * <li>path = path to the database - context-protocol is resolved</li>
086: * </ul>
087: */
088: public void parameterize(Parameters params)
089: throws ParameterException {
090: hsqlServer.setLogWriter(null); /* Remove console log */
091: hsqlServer.setErrWriter(null); /* Remove console log */
092: hsqlServer.setPort(params.getParameterAsInteger("port",
093: DEFAULT_PORT));
094: hsqlServer.setSilent(params.getParameterAsBoolean("silent",
095: DEFAULT_SILENT));
096: hsqlServer.setTrace(params.getParameterAsBoolean("trace",
097: DEFAULT_TRACE));
098: hsqlServer.setNoSystemExit(true);
099: if (getLogger().isDebugEnabled()) {
100: getLogger().debug(
101: "Configure HSQLDB with port: "
102: + hsqlServer.getPort() + ", silent: "
103: + hsqlServer.isSilent() + ", trace: "
104: + hsqlServer.isTrace());
105: }
106:
107: m_daemonThreadPoolName = params.getParameter(
108: "thread-pool-name", m_daemonThreadPoolName);
109:
110: final String dbCfgPath = params.getParameter("path",
111: DEFAULT_DB_PATH);
112: String dbPath = dbCfgPath;
113: // Test if we are running inside a WAR file
114: if (dbPath.startsWith(ServerImpl.CONTEXT_PROTOCOL)) {
115: dbPath = this .cocoonContext.getRealPath(dbPath
116: .substring(ServerImpl.CONTEXT_PROTOCOL.length()));
117: }
118: if (dbPath == null) {
119: throw new ParameterException(
120: "The hsqldb cannot be used inside an unexpanded WAR file. "
121: + "Real path for <" + dbCfgPath
122: + "> is null.");
123: }
124:
125: String dbName = params.getParameter("name", DEFAULT_DB_NAME);
126: try {
127: hsqlServer.setDatabasePath(0, new File(dbPath)
128: .getCanonicalPath()
129: + File.separator + dbName);
130: hsqlServer.setDatabaseName(0, dbName);
131: } catch (IOException e) {
132: throw new ParameterException(
133: "Could not get database directory <" + dbPath + ">",
134: e);
135: }
136:
137: if (getLogger().isDebugEnabled()) {
138: getLogger()
139: .debug(
140: "Database path is <"
141: + hsqlServer.getDatabasePath(0,
142: true) + ">");
143: }
144: }
145:
146: /**
147: * @param serviceManager The <@link ServiceManager} instance
148: * @throws ServiceException In case we cannot find a service needed
149: */
150: public void service(ServiceManager serviceManager)
151: throws ServiceException {
152: m_serviceManager = serviceManager;
153: }
154:
155: /** Start the server */
156: public void start() {
157: RunnableManager runnableManager = null;
158: try {
159: runnableManager = (RunnableManager) m_serviceManager
160: .lookup(RunnableManager.ROLE);
161: runnableManager.execute(m_daemonThreadPoolName, this );
162: } catch (final ServiceException e) {
163: throw new CascadingRuntimeException(
164: "Cannot get RunnableManager", e);
165: } finally {
166: if (null != runnableManager) {
167: m_serviceManager.release(runnableManager);
168: }
169: }
170: }
171:
172: /** Stop the server */
173: public void stop() {
174: getLogger().debug("Shutting down HSQLDB");
175: //AG: Temporally workaround for http://issues.apache.org/jira/browse/COCOON-1862
176: // A newer version of hsqldb or SAP NetWeaver may not need the next line
177: DatabaseManager.closeDatabases(Database.CLOSEMODE_COMPACT);
178: hsqlServer.stop();
179: getLogger().debug("Shutting down HSQLDB: Done");
180: }
181:
182: /** Run the server */
183: public void run() {
184: if (getLogger().isDebugEnabled()) {
185: getLogger().debug(
186: "Starting " + hsqlServer.getProductName() + " "
187: + hsqlServer.getProductVersion()
188: + " with parameters:");
189: }
190: this.hsqlServer.start();
191: }
192: }
|