001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.server.hsql;
018:
019: import org.apache.commons.dbcp.BasicDataSource;
020: import org.apache.openejb.loader.SystemInstance;
021: import org.apache.openejb.resource.jdbc.HsqldbDataSourcePlugin;
022: import org.apache.openejb.server.SelfManaging;
023: import org.apache.openejb.server.ServerService;
024: import org.apache.openejb.server.ServiceException;
025: import org.apache.openejb.spi.ContainerSystem;
026: import org.hsqldb.Database;
027: import org.hsqldb.DatabaseManager;
028: import org.hsqldb.Server;
029: import org.hsqldb.ServerConfiguration;
030: import org.hsqldb.ServerConstants;
031: import org.hsqldb.jdbcDriver;
032: import org.hsqldb.persist.HsqlProperties;
033:
034: import javax.naming.Binding;
035: import javax.naming.NameNotFoundException;
036: import javax.naming.NamingEnumeration;
037: import java.io.IOException;
038: import java.io.InputStream;
039: import java.io.OutputStream;
040: import java.net.Socket;
041: import java.util.Collections;
042: import java.util.Map;
043: import java.util.Properties;
044: import java.util.Set;
045: import java.util.TreeSet;
046:
047: /**
048: * @version $Rev: 607077 $ $Date: 2007-12-27 06:55:23 -0800 $
049: */
050: public class HsqlService implements ServerService, SelfManaging {
051: private int port = ServerConfiguration.getDefaultPort(
052: ServerConstants.SC_PROTOCOL_HSQL, false);
053: private String ip = ServerConstants.SC_DEFAULT_ADDRESS;
054: private Server server;
055:
056: public String getName() {
057: return "hsql";
058: }
059:
060: public int getPort() {
061: return port;
062: }
063:
064: public String getIP() {
065: return ip;
066: }
067:
068: public void init(Properties p) throws Exception {
069: Properties properties = new Properties();
070: for (Map.Entry<Object, Object> entry : p.entrySet()) {
071: // Somtimes the properties object has non string values
072: if (!(entry.getKey() instanceof String))
073: continue;
074: if (!(entry.getValue() instanceof String))
075: continue;
076:
077: String property = (String) entry.getKey();
078: String value = (String) entry.getValue();
079:
080: if (property
081: .startsWith(ServerConstants.SC_KEY_DBNAME + ".")
082: || property
083: .startsWith(ServerConstants.SC_KEY_DATABASE
084: + ".")) {
085:
086: throw new ServiceException(
087: "Databases cannot be declared in the hsql.properties. "
088: + "Instead declare a database connection in the openejb.conf file");
089: }
090:
091: if ("port".equals(property)) {
092: properties.setProperty(ServerConstants.SC_KEY_PORT,
093: value);
094: } else if ("bind".equals(property)) {
095: properties.setProperty(ServerConstants.SC_KEY_ADDRESS,
096: value);
097: } else {
098: properties.setProperty(property, value);
099: }
100: }
101: properties.setProperty(ServerConstants.SC_KEY_NO_SYSTEM_EXIT,
102: "true");
103:
104: boolean disabled = Boolean.parseBoolean(properties
105: .getProperty("disabled"));
106: ContainerSystem containerSystem = SystemInstance.get()
107: .getComponent(ContainerSystem.class);
108: if (!disabled && containerSystem != null) {
109: NamingEnumeration<Binding> bindings = null;
110: try {
111: bindings = containerSystem.getJNDIContext()
112: .listBindings("java:openejb/Resource/");
113: Set<String> dbnames = new TreeSet<String>();
114: for (Binding binding : Collections.list(bindings)) {
115: Object value = binding.getObject();
116: if (value instanceof BasicDataSource) {
117: BasicDataSource jdbc = (BasicDataSource) value;
118: String path = getPath(jdbc);
119: if (path != null) {
120: if (dbnames.size() > 9) {
121: throw new ServiceException(
122: "Hsql Server can only host 10 database instances");
123: }
124: String dbname = path.substring(path
125: .lastIndexOf(':') + 1);
126: dbname = dbname.substring(dbname
127: .lastIndexOf('/') + 1);
128: if (!dbnames.contains(dbname)) {
129: properties.put(
130: ServerConstants.SC_KEY_DBNAME
131: + "." + dbnames.size(),
132: dbname);
133: properties.put(
134: ServerConstants.SC_KEY_DATABASE
135: + "." + dbnames.size(),
136: path);
137: dbnames.add(dbname);
138: }
139: }
140: }
141: }
142: } catch (NameNotFoundException e) {
143: }
144:
145: // create the server
146: server = new Server();
147: // add the silent property
148: properties.setProperty(ServerConstants.SC_KEY_SILENT,
149: "true");
150: // set the log and error writers
151: server.setLogWriter(new HsqlPrintWriter(false));
152: server.setErrWriter(new HsqlPrintWriter(true));
153: server.setProperties(new HsqlProperties(properties));
154:
155: // get the port
156: port = server.getPort();
157:
158: // get the Address
159: String ipString = server.getAddress();
160: if (ipString != null && ipString.length() > 0) {
161: this .ip = ipString;
162: }
163: }
164: }
165:
166: private String getPath(BasicDataSource jdbc) {
167: // is this connectoion using the hsql driver?
168: if (!jdbcDriver.class.getName().equals(
169: jdbc.getDriverClassName())) {
170: return null;
171: }
172:
173: String url = jdbc.getUrl();
174:
175: // is this a hsql url?
176: if (url == null || !url.startsWith("jdbc:hsqldb:")) {
177: return null;
178: }
179:
180: // resolve the relative path
181: url = HsqldbDataSourcePlugin.toAbsolutePath(url);
182:
183: // hack off the jdbc:hsqldb stuff
184: String path = url.substring("jdbc:hsqldb:".length());
185:
186: // is this a connection to a local file, mem, or res database?
187: if (!path.startsWith("file:") && !path.startsWith("mem:")
188: && path.startsWith("res:")) {
189: return null;
190: }
191:
192: return path;
193: }
194:
195: public void service(InputStream inputStream,
196: OutputStream outputStream) throws ServiceException,
197: IOException {
198: throw new UnsupportedOperationException(
199: "Method not implemented: service(InputStream in, OutputStream out)");
200: }
201:
202: public void service(Socket socket) throws ServiceException,
203: IOException {
204: throw new UnsupportedOperationException(
205: "Method not implemented: service(Socket socket)");
206: }
207:
208: public void start() throws ServiceException {
209: if (server == null)
210: return;
211: server.start();
212: }
213:
214: public void stop() throws ServiceException {
215: if (server == null)
216: return;
217: try {
218: server.stop();
219: } finally {
220: server = null;
221: DatabaseManager.closeDatabases(Database.CLOSEMODE_COMPACT);
222: }
223: }
224: }
|