001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
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.kuali.rice.ojb;
018:
019: import java.io.BufferedInputStream;
020: import java.io.BufferedOutputStream;
021: import java.io.ByteArrayInputStream;
022: import java.io.ByteArrayOutputStream;
023: import java.io.InputStream;
024: import java.util.Iterator;
025: import java.util.List;
026:
027: import javax.xml.parsers.DocumentBuilderFactory;
028: import javax.xml.transform.Transformer;
029: import javax.xml.transform.TransformerFactory;
030: import javax.xml.transform.dom.DOMSource;
031: import javax.xml.transform.stream.StreamResult;
032: import javax.xml.xpath.XPath;
033: import javax.xml.xpath.XPathConstants;
034: import javax.xml.xpath.XPathFactory;
035:
036: import org.apache.commons.lang.StringUtils;
037: import org.apache.ojb.broker.metadata.ConnectionRepository;
038: import org.apache.ojb.broker.metadata.DescriptorRepository;
039: import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
040: import org.apache.ojb.broker.metadata.MetadataManager;
041: import org.kuali.rice.config.Config;
042: import org.kuali.rice.config.ConfigurationException;
043: import org.kuali.rice.core.Core;
044: import org.kuali.rice.lifecycle.BaseLifecycle;
045: import org.kuali.rice.util.ClassLoaderUtils;
046: import org.springframework.core.io.DefaultResourceLoader;
047: import org.w3c.dom.Document;
048: import org.w3c.dom.Element;
049: import org.w3c.dom.NodeList;
050: import org.xml.sax.InputSource;
051:
052: /**
053: * Base Ojb Configurer implementation which configures OJB for a particular rice module.
054: *
055: * @author Kuali Rice Team (kuali-rice@googlegroups.com)
056: */
057: public abstract class BaseOjbConfigurer extends BaseLifecycle {
058:
059: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
060: .getLogger(BaseOjbConfigurer.class);
061:
062: private static final String OJB_PROPERTIES_PROP = "OJB.properties";
063: private static final String DEFAULT_OJB_PROPERTIES = "org/kuali/rice/ojb/RiceOJB.properties";
064:
065: @Override
066: public void start() throws Exception {
067: // if OJB has not already been loaded, let's trigger a load using our built-in OJB properties file
068: String currentValue = System.getProperty(OJB_PROPERTIES_PROP);
069: try {
070: System.setProperty(OJB_PROPERTIES_PROP,
071: DEFAULT_OJB_PROPERTIES);
072: MetadataManager mm = MetadataManager.getInstance();
073: establishConnectionMetaData(mm);
074: establishRepositoryMetaData(mm);
075: } finally {
076: if (currentValue == null) {
077: System.getProperties().remove(OJB_PROPERTIES_PROP);
078: } else {
079: System.setProperty(OJB_PROPERTIES_PROP, currentValue);
080: }
081: }
082: super .start();
083: }
084:
085: protected String getOjbPropertiesLocation() {
086: return DEFAULT_OJB_PROPERTIES;
087: }
088:
089: protected void establishConnectionMetaData(MetadataManager mm)
090: throws Exception {
091: String connMetadata = getMetadataLocation();
092: if (StringUtils.isBlank(connMetadata)) {
093: LOG.info("No OJB connection metadata loaded.");
094: return;
095: }
096: if (!isConnectionAlreadyConfigured(mm)) {
097: LOG.info("Loading OJB Connection Metadata from "
098: + connMetadata);
099: DefaultResourceLoader resourceLoader = new DefaultResourceLoader(
100: ClassLoaderUtils.getDefaultClassLoader());
101: InputStream is = resourceLoader.getResource(connMetadata)
102: .getInputStream();
103: is = preprocessConnectionMetadata(is);
104: ConnectionRepository cr = mm.readConnectionRepository(is);
105: mm.mergeConnectionRepository(cr);
106: try {
107: is.close();
108: } catch (Exception e) {
109: LOG.warn("Failed to close stream to file "
110: + connMetadata, e);
111: }
112: } else {
113: LOG
114: .info("OJB Connections already configured for jcd aliases '"
115: + StringUtils.join(getJcdAliases(), ", ")
116: + "', skipping Metadata merge.");
117: }
118: }
119:
120: protected InputStream preprocessConnectionMetadata(
121: InputStream inputStream) throws Exception {
122: Document document = DocumentBuilderFactory.newInstance()
123: .newDocumentBuilder().parse(
124: new InputSource(inputStream));
125: XPath xpath = XPathFactory.newInstance().newXPath();
126: NodeList connectionDescriptors = (NodeList) xpath.evaluate(
127: "/descriptor-repository/jdbc-connection-descriptor",
128: document, XPathConstants.NODESET);
129: for (int index = 0; index < connectionDescriptors.getLength(); index++) {
130: Element descriptor = (Element) connectionDescriptors
131: .item(index);
132: String currentPlatform = descriptor
133: .getAttribute("platform");
134: if (StringUtils.isBlank(currentPlatform)) {
135: String ojbPlatform = Core.getCurrentContextConfig()
136: .getProperty(Config.OJB_PLATFORM);
137: if (StringUtils.isEmpty(ojbPlatform)) {
138: throw new ConfigurationException(
139: "Could not configure OJB, the '"
140: + Config.OJB_PLATFORM
141: + "' configuration property was not set.");
142: }
143: LOG
144: .info("Setting OJB connection descriptor database platform to '"
145: + ojbPlatform + "'");
146: descriptor.setAttribute("platform", ojbPlatform);
147: }
148: }
149: Transformer transformer = TransformerFactory.newInstance()
150: .newTransformer();
151: ByteArrayOutputStream baos = new ByteArrayOutputStream();
152: transformer.transform(new DOMSource(document),
153: new StreamResult(new BufferedOutputStream(baos)));
154: return new BufferedInputStream(new ByteArrayInputStream(baos
155: .toByteArray()));
156: }
157:
158: protected boolean isConnectionAlreadyConfigured(MetadataManager mm) {
159: List descriptors = mm.connectionRepository().getAllDescriptor();
160: for (Iterator iterator = descriptors.iterator(); iterator
161: .hasNext();) {
162: JdbcConnectionDescriptor descriptor = (JdbcConnectionDescriptor) iterator
163: .next();
164: for (String jcdAlias : getJcdAliases()) {
165: if (descriptor.getJcdAlias().equals(jcdAlias)) {
166: return true;
167: }
168: }
169: }
170: return false;
171: }
172:
173: protected InputStream preprocessRepositoryMetadata(
174: InputStream inputStream) throws Exception {
175: return inputStream;
176: }
177:
178: protected void establishRepositoryMetaData(MetadataManager mm)
179: throws Exception {
180: String repoMetadata = getMetadataLocation();
181: if (StringUtils.isBlank(repoMetadata)) {
182: LOG.info("No OJB repository metadata loaded.");
183: return;
184: }
185: LOG.info("Loading OJB Metadata from " + repoMetadata);
186: DefaultResourceLoader resourceLoader = new DefaultResourceLoader(
187: ClassLoaderUtils.getDefaultClassLoader());
188: InputStream is = resourceLoader.getResource(repoMetadata)
189: .getInputStream();
190: is = preprocessRepositoryMetadata(is);
191: DescriptorRepository dr = mm.readDescriptorRepository(is);
192: mm.mergeDescriptorRepository(dr);
193: try {
194: is.close();
195: } catch (Exception e) {
196: LOG.warn("Failed to close stream to file " + repoMetadata,
197: e);
198: }
199: }
200:
201: /**
202: * Return the jcd alias of the connection loaded by the connection metadata.
203: * @return
204: */
205: protected abstract String[] getJcdAliases();
206:
207: /**
208: * Should return a String representing the location of a file to load OJB connection and
209: * repository metadata from. If null or empty than no metadata will be loaded.
210: */
211: protected abstract String getMetadataLocation();
212:
213: // protected void establishConnectionMetaData(MetadataManager mm) throws Exception {
214: // ConnectionRepository repository = getConnectionRepository();
215: // if (repository == null) {
216: // throw new ConfigurationException("Could not load OJB connection repository");
217: // }
218: // mm.mergeConnectionRepository(repository);
219: //}
220:
221: //protected ConnectionRepository getConnectionRepository() {
222: // ConnectionRepository repository = new ConnectionRepository();
223: // JdbcConnectionDescriptor descriptor = new JdbcConnectionDescriptor();
224: // descriptor.setJdbcLevel("3.0");
225: // descriptor.setEagerRelease(false);
226: // descriptor.setBatchMode(false);
227: // descriptor.setUseAutoCommit(0);
228: // descriptor.setIgnoreAutoCommitExceptions(false);
229: // descriptor.setJcdAlias(getJcdAlias());
230: // descriptor.setDefaultConnection(false);
231: // String ojbPlatform = Core.getCurrentContextConfig().getProperty(Config.OJB_PLATFORM);
232: // if (StringUtils.isEmpty(ojbPlatform)) {
233: // throw new ConfigurationException("Could not configure OJB, the '" + Config.OJB_PLATFORM + "' configuration property was not set.");
234: // }
235: // if (StringUtils.isBlank(descriptor.getDbms())) {
236: // log.info("Setting " + descriptor.getJcdAlias() + " OJB connection descriptor database platform to '" + ojbPlatform + "'");
237: // descriptor.setDbms(ojbPlatform);
238: // }
239: //
240: // SequenceDescriptor sequenceDescriptor = new SequenceDescriptor(descriptor);
241: // sequenceDescriptor.addAttribute("property.prefix", "datasource.ojb.sequenceManager");
242: // sequenceDescriptor.setSequenceManagerClass(ConfigurableSequenceManager.class);
243: // descriptor.setSequenceDescriptor(sequenceDescriptor);
244: //
245: // ObjectCacheDescriptor cacheDescriptor = descriptor.getObjectCacheDescriptor();
246: // cacheDescriptor.setObjectCache(ObjectCachePerBrokerImpl.class);
247: //
248: // repository.addDescriptor(descriptor);
249: // return repository;
250: //
251: //
252: //}
253:
254: }
|